Files
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

275 lines
13 KiB
PHP

<?php
namespace App\Services\AtencaoBasica\RelatorioInconsistencia;
use App\Enums\AtencaoBasica\CadastroDomiciliar\ImovelTipo;
use App\Enums\AtencaoBasica\Exportacao\Inconsistencia;
use App\Enums\AtencaoBasica\Parametrizacao\Permissao;
use App\Rules\AtencaoBasica\Exportacao\AlturaLimitIsValid;
use App\Rules\AtencaoBasica\Exportacao\CnesIsValid;
use App\Rules\AtencaoBasica\Exportacao\CnsPaciente;
use App\Rules\AtencaoBasica\Exportacao\DataAtendimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\DataNascimentoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\DataNascimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\DesfechoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\GlicemiaIsRequired;
use App\Rules\AtencaoBasica\Exportacao\GlicemiaLimitIsValid;
use App\Rules\AtencaoBasica\Exportacao\IbgeIsValid;
use App\Rules\AtencaoBasica\Exportacao\LatitudeIsRequired;
use App\Rules\AtencaoBasica\Exportacao\LongitudeIsRequired;
use App\Rules\AtencaoBasica\Exportacao\MomentoColetaGlicemiaIsRequired;
use App\Rules\AtencaoBasica\Exportacao\MotivoVisitaIsValid;
use App\Rules\AtencaoBasica\Exportacao\OcupacaoIsAllowed;
use App\Rules\AtencaoBasica\Exportacao\PesoLimitIsValid;
use App\Rules\AtencaoBasica\Exportacao\SexoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\TipoImovelsRequired;
use App\Rules\AtencaoBasica\Exportacao\TurnoIsRequired;
use App\Rules\Cns;
use App\Rules\Cpf;
use App\Services\Service;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class FichaVisitaDomiciliarService extends Service
{
private const ERROR_MAP = [
CnesIsValid::class => Inconsistencia::CNES_DA_UNIDADE_COM_TAMANHO_DIFERENTE_DE_7_CARACTERES,
IbgeIsValid::class => Inconsistencia::IBGE_DO_MUNICIPIO_SEM_PREENCHIMENTO_OU_INVALIDO,
Cns::class => Inconsistencia::CNS_DO_PROFISSIONAL_INVALIDO,
OcupacaoIsAllowed::class => Inconsistencia::OCUPACAO_DO_USUARIO_SEM_PERMISSAO_PARA_REGISTRAR_A_FICHA,
DataAtendimentoIsValid::class => Inconsistencia::DATA_ATENDIMENTO_INVALIDO,
CnsPaciente::class => Inconsistencia::CNS_DO_PACIENTE_INVALIDO,
Cpf::class => Inconsistencia::CPF_DO_PACIENTE_INVALIDO,
DataNascimentoIsRequired::class => Inconsistencia::DATA_NASCIMENTO_SEM_PREENCHIMENTO,
DataNascimentoIsValid::class => Inconsistencia::DATA_DE_NASCIMENTO_POSTERIOR_A_DATA_DE_ATENDIMENTO_SUPERIOR_A_130_ANOS_OU_NAO_PREENCHIDA,
MotivoVisitaIsValid::class => Inconsistencia::MOTIVO_INVALIDO,
TipoImovelsRequired::class => Inconsistencia::TIPO_IMOVEL_SEM_PREENCHIMENTO,
DesfechoIsRequired::class => Inconsistencia::DESFECHO_SEM_PREENCHIMENTO,
LatitudeIsRequired::class => Inconsistencia::LATITUDE_SEM_PREENCHIMENTO,
LongitudeIsRequired::class => Inconsistencia::LONGITUDE_SEM_PREENCHIMENTO,
TurnoIsRequired::class => Inconsistencia::TURNO_SEM_PREENCHIMENTO,
SexoIsRequired::class => Inconsistencia::SEXO_DO_PACIENTE_SEM_PREENCHIMENTO,
GlicemiaLimitIsValid::class => Inconsistencia::GLICEMIA_DO_PACIENTE_MENOR_QUE_0_OU_MAIOR_QUE_800_KG,
GlicemiaIsRequired::class => Inconsistencia::GLICEMIA_SEM_PREENCHIMENTO,
MomentoColetaGlicemiaIsRequired::class => Inconsistencia::MOMENTO_COLETA_GLICEMIA_SEM_PREENCHIMENTO,
PesoLimitIsValid::class => Inconsistencia::PESO_DO_PACIENTE_MENOR_QUE_0_5_OU_MAIOR_QUE_500_KG,
AlturaLimitIsValid::class => Inconsistencia::ALTURA_DO_PACIENTE_MENOR_QUE_20_OU_MAIOR_QUE_250_CM,
];
public static function index()
{
$mes_ano = request()->mes_ano;
$date = Carbon::createFromFormat('mY', $mes_ano);
$start = $date->copy()->startOfMonth()->toDateString();
$end = $date->copy()->endOfMonth()->toDateString();
$inconsistencias = DB::table('atencao_basica_inconsistencia')
->select('id', 'descricao')
->get()
->pluck('descricao', 'id');
$fichasVisitaDomiciliar = DB::table('atencao_basica_visita_domiciliar')
->select([
'atencao_basica_visita_domiciliar.id as id',
'atencao_basica_visita_domiciliar.usuario_id as usuario_id',
'atencao_basica_visita_domiciliar.data_usuario_responsavel as data_atendimento',
'cadastro_unidade.cnes as unidade_cnes',
'cadastro_municipio.ibge as municipio_ibge',
'sigtap.ocupacao.codigo as ocupacao_codigo',
'cadastro_cidadao.cns AS usuario_cns',
'cadastro_cidadao.nome AS profissional_nome',
'paciente_cidadao.cns as paciente_cns',
'paciente_cidadao.cpf as paciente_cpf',
'paciente_cidadao.nome as paciente_nome',
'paciente_cidadao.nome_social as paciente_nome_social',
'paciente_cidadao.preferencia_nome_id as paciente_preferencia_nome_id',
'paciente_cidadao.data_nascimento as paciente_data_nascimento',
'paciente_cidadao.sexo_id as paciente_sexo_id',
DB::raw('LPAD(cadastro_paciente.prontuario,7,0) AS paciente_prontuario'),
'atencao_basica_visita_domiciliar.turno_id',
'atencao_basica_visita_domiciliar.peso',
'atencao_basica_visita_domiciliar.altura',
'atencao_basica_visita_domiciliar.paciente_id',
'atencao_basica_visita_domiciliar.imovel_tipo_id',
'atencao_basica_visita_domiciliar.latitude',
'atencao_basica_visita_domiciliar.longitude',
'atencao_basica_visita_domiciliar.visita_compartilhada',
'atencao_basica_visita_domiciliar.temperatura',
'atencao_basica_visita_domiciliar.afericao_pa',
'atencao_basica_visita_domiciliar.glicemia',
'atencao_basica_visita_domiciliar.momento_coleta_id',
'atencao_basica_visita_domiciliar.desfecho_id',
'atencao_basica_cadastro_imovel_tipo.codigo_esus as imovel_tipo_codigo_esus',
])
->join('atencao_basica_parametrizacao_equipe', 'atencao_basica_parametrizacao_equipe.id', 'atencao_basica_visita_domiciliar.equipe_id')
->join('atencao_basica_cadastro_imovel_tipo', 'atencao_basica_cadastro_imovel_tipo.id', 'atencao_basica_visita_domiciliar.imovel_tipo_id')
->join('cadastro_unidade', 'cadastro_unidade.id', 'atencao_basica_parametrizacao_equipe.unidade_id')
->join('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'atencao_basica_parametrizacao_equipe.infraestrutura_id')
->leftJoin('cadastro_endereco', 'cadastro_endereco.id', 'cadastro_infraestrutura.endereco_id')
->leftJoin('cadastro_logradouro', 'cadastro_logradouro.id', 'cadastro_endereco.logradouro_id')
->leftJoin('intranet.cadastro_municipio', 'cadastro_municipio.id', 'cadastro_logradouro.municipio_id')
->join('cadastro_usuario', 'cadastro_usuario.id', 'atencao_basica_visita_domiciliar.usuario_id')
->join('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_usuario.cidadao_id')
->join('sigtap.ocupacao', 'sigtap.ocupacao.id', 'atencao_basica_visita_domiciliar.usuario_ocupacao_id')
->join('cadastro_paciente', 'cadastro_paciente.id', 'atencao_basica_visita_domiciliar.paciente_id')
->join('cadastro_cidadao as paciente_cidadao', 'paciente_cidadao.id', 'cadastro_paciente.cidadao_id')
->whereBetween('atencao_basica_visita_domiciliar.data_usuario_responsavel', [$start, $end])
->when(request()->unidade_id, fn ($query) => $query->where('atencao_basica_parametrizacao_equipe.unidade_id', request()->unidade_id))
->when(request()->infraestrutura_id, fn ($query) => $query->where('atencao_basica_parametrizacao_equipe.infraestrutura_id', request()->infraestrutura_id))
->when(request()->usuario_id, fn ($query) => $query->where('atencao_basica_visita_domiciliar.usuario_id', request()->usuario_id))
->get();
$groupedList = [];
foreach ($fichasVisitaDomiciliar as $ficha) {
$errors = RelatorioInconsistenciaService::validHeader($ficha, Permissao::VISITA_DOMICILIAR)
->merge(self::validAtendimento($ficha));
$errorDescriptions = self::mapErrorsToDescriptions($errors, $inconsistencias);
if ($errorDescriptions->isEmpty()) {
continue;
}
$key = $ficha->data_atendimento . '|' . $ficha->paciente_id . '|' . $ficha->usuario_id;
if (!isset($groupedList[$key])) {
$groupedList[$key] = [
'data' => (new Carbon($ficha->data_atendimento))->format('d/m/Y'),
'ficha' => 'Visita Domiciliar',
'paciente_nome' => $ficha->paciente_nome,
'paciente_nome_social' => $ficha->paciente_nome_social,
'paciente_preferencia_nome_id' => $ficha->paciente_preferencia_nome_id,
'paciente_prontuario' => $ficha->paciente_prontuario,
'paciente_cns' => $ficha->paciente_cns ? MaskUtil::getCnsMasked($ficha->paciente_cns) : '-',
'paciente_cpf' => $ficha->paciente_cpf ? MaskUtil::getCpfMasked($ficha->paciente_cpf) : '-',
'profissional' => $ficha->profissional_nome,
'erros' => $errorDescriptions,
];
} else {
$groupedList[$key]['erros'] = $groupedList[$key]['erros']->merge($errorDescriptions);
}
}
$result = [];
foreach ($groupedList as $group) {
$unique = $group['erros']->unique();
$group['erros'] = $unique->implode('<br />');
$group['total_erros'] = $unique->count();
$result[] = $group;
}
return $result;
}
private static function mapErrorsToDescriptions(Collection $errors, Collection $inconsistencias): Collection
{
$descriptions = collect();
foreach ($errors as $error) {
$inconsistenciaId = self::ERROR_MAP[$error] ?? null;
if ($inconsistenciaId === null) {
continue;
}
$descricao = $inconsistencias[$inconsistenciaId] ?? null;
if ($descricao !== null) {
$descriptions->push($descricao);
}
}
return $descriptions;
}
private static function validAtendimento($ficha): Collection
{
$errors = collect();
if (!Cns::isValid($ficha->paciente_cns) && !Cpf::isValid($ficha->paciente_cpf)) {
$errors->push(CnsPaciente::class);
$errors->push(Cpf::class);
}
if (self::getTipoImovelValido($ficha->imovel_tipo_codigo_esus) && !DataNascimentoIsRequired::isValid($ficha->paciente_data_nascimento)) {
$errors->push(DataNascimentoIsRequired::class);
}
if (!DataNascimentoIsValid::isValid([
'data_nascimento' => $ficha->paciente_data_nascimento,
'data_atendimento' => $ficha->data_atendimento
])) {
$errors->push(DataNascimentoIsValid::class);
}
if (!MotivoVisitaIsValid::isValid($ficha)) {
$errors->push(MotivoVisitaIsValid::class);
}
if (!TurnoIsRequired::isValid($ficha->turno_id)) {
$errors->push(TurnoIsRequired::class);
}
if ($ficha->longitude && !LatitudeIsRequired::isValid($ficha->latitude)) {
$errors->push(LatitudeIsRequired::class);
}
if ($ficha->latitude && !LongitudeIsRequired::isValid($ficha->longitude)) {
$errors->push(LongitudeIsRequired::class);
}
if (!DesfechoIsRequired::isValid($ficha->desfecho_id)) {
$errors->push(DesfechoIsRequired::class);
}
if (!TipoImovelsRequired::isValid($ficha->imovel_tipo_id)) {
$errors->push(TipoImovelsRequired::class);
}
if (!SexoIsRequired::isValid($ficha->paciente_sexo_id)) {
$errors->push(SexoIsRequired::class);
}
if (!GlicemiaLimitIsValid::isValid($ficha->glicemia)) {
$errors->push(GlicemiaLimitIsValid::class);
}
if ($ficha->momento_coleta_id && !GlicemiaIsRequired::isValid($ficha->glicemia)) {
$errors->push(GlicemiaIsRequired::class);
}
if ($ficha->glicemia && !MomentoColetaGlicemiaIsRequired::isValid($ficha->momento_coleta_id)) {
$errors->push(MomentoColetaGlicemiaIsRequired::class);
}
if (!PesoLimitIsValid::isValid($ficha->peso)) {
$errors->push(PesoLimitIsValid::class);
}
if (!AlturaLimitIsValid::isValid($ficha->altura)) {
$errors->push(AlturaLimitIsValid::class);
}
return $errors;
}
private static function getTipoImovelValido($tipoImovelId): bool
{
return $tipoImovelId == ImovelTipo::DOMICILIO
|| $tipoImovelId == ImovelTipo::ABRIGO
|| $tipoImovelId == ImovelTipo::INSTITUICAO_LONGA_PERMANENCIA_IDOSOS
|| $tipoImovelId == ImovelTipo::UNIDADE_PRISIONAL
|| $tipoImovelId == ImovelTipo::UNIDADE_MEDIDA_SOCIO_EDUCATIVA
|| $tipoImovelId == ImovelTipo::DELEGACIA
|| $tipoImovelId == ImovelTipo::OUTROS;
}
}