init commit
All checks were successful
build-api-image / build (push) Successful in 51s

This commit is contained in:
Antonio Lopes dos Santos
2026-08-04 16:52:02 -03:00
commit afec302c3e
11594 changed files with 1636728 additions and 0 deletions

View File

@@ -0,0 +1,460 @@
<?php
namespace App\Services\AtencaoBasica\RelatorioInconsistencia;
use App\Enums\AtencaoBasica\Exportacao\Imunobiologico;
use App\Enums\AtencaoBasica\Exportacao\Inconsistencia;
use App\Enums\AtencaoBasica\Exportacao\VacinaAplicadaExterior;
use App\Enums\AtencaoBasica\Parametrizacao\Permissao;
use App\Rules\AtencaoBasica\Exportacao\AplicadoExteriorIsRequired;
use App\Rules\AtencaoBasica\Exportacao\CnesIsValid;
use App\Rules\AtencaoBasica\Exportacao\CnsPaciente;
use App\Rules\AtencaoBasica\Exportacao\ComunicanteHanseniaseIsRequired;
use App\Rules\AtencaoBasica\Exportacao\DataAtendimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\DataNascimentoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\DataNascimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\DataRegistroAnteriorIsRequired;
use App\Rules\AtencaoBasica\Exportacao\DataRegistroAnteriorIsValid;
use App\Rules\AtencaoBasica\Exportacao\DoseIsValid;
use App\Rules\AtencaoBasica\Exportacao\EstrategiaIsRequired;
use App\Rules\AtencaoBasica\Exportacao\EstrategiaIsValid;
use App\Rules\AtencaoBasica\Exportacao\EstrategiaIsValidForFicha;
use App\Rules\AtencaoBasica\Exportacao\FabricanteIsRequired;
use App\Rules\AtencaoBasica\Exportacao\FabricanteIsValid;
use App\Rules\AtencaoBasica\Exportacao\GestanteIsValidForFicha;
use App\Rules\AtencaoBasica\Exportacao\GrupoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\GrupoIsValid;
use App\Rules\AtencaoBasica\Exportacao\IbgeIsValid;
use App\Rules\AtencaoBasica\Exportacao\LocalAtendimentoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\LocalAtendimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\LoteIsRequired;
use App\Rules\AtencaoBasica\Exportacao\OcupacaoIsAllowed;
use App\Rules\AtencaoBasica\Exportacao\PuerperaAndGestanteIsChecked;
use App\Rules\AtencaoBasica\Exportacao\PuerperaIsValidForFicha;
use App\Rules\AtencaoBasica\Exportacao\VacinaIsDuplicate;
use App\Rules\AtencaoBasica\Exportacao\VacinaIsValid;
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 FichaVacinacaoService extends Service
{
private const FICHA_LABEL = 'Ficha de vacinação';
private const HEADER_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,
];
private const PACIENTE_ERROR_MAP = [
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,
LocalAtendimentoIsRequired::class => Inconsistencia::LOCAL_DE_ATENDIMENTO_SEM_PREENCHIMENTO,
LocalAtendimentoIsValid::class => Inconsistencia::LOCAL_DE_ATENDIMENTO_INVALIDO,
GestanteIsValidForFicha::class => Inconsistencia::GESTANTE_PREENCHIDO_PARA_PACIENTES_DO_SEXO_MASCULINO,
PuerperaIsValidForFicha::class => Inconsistencia::PUERPERA_PREENCHIDO_PARA_PACIENTES_DO_SEXO_MASCULINO,
PuerperaAndGestanteIsChecked::class => Inconsistencia::GESTANTE_E_PUERPERA_AMBOS_PREENCHIDOS,
ComunicanteHanseniaseIsRequired::class => Inconsistencia::COMUNICANTE_HANSENIASE_SEM_PREENCHIMENTO,
];
private const VACINA_ERROR_MAP = [
EstrategiaIsValid::class => Inconsistencia::ESTRATEGIA_INVALIDA,
EstrategiaIsRequired::class => Inconsistencia::ESTRATEGIA_SEM_PREENCHIMENTO,
DoseIsValid::class => Inconsistencia::DOSE_INVALIDA,
LoteIsRequired::class => Inconsistencia::LOTE_EM_PREENCHIMENTO,
DataRegistroAnteriorIsRequired::class => Inconsistencia::DATA_REGISTRO_ANTERIOR_SEM_PREENCHIMENTO,
FabricanteIsRequired::class => Inconsistencia::FABRICANTE_SEM_PREENCHIMENTO,
AplicadoExteriorIsRequired::class => Inconsistencia::APLICADO_EXTERIOR_SEM_PREENCHIMENTO,
GrupoIsRequired::class => Inconsistencia::GRUPO_SEM_PREENCHIMENTO,
GrupoIsValid::class => Inconsistencia::GRUPO_INVALIDO,
VacinaIsDuplicate::class => Inconsistencia::VACINA_DUPLICADA,
VacinaIsValid::class => Inconsistencia::VACINA_INVALIDA,
];
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');
$fichasVacinacao = DB::table('atencao_basica_ficha_vacinacao')
->select([
'atencao_basica_ficha_vacinacao.id as id',
'atencao_basica_ficha_vacinacao.usuario_id as usuario_id',
'atencao_basica_ficha_vacinacao.data_atendimento as data_atendimento',
'cadastro_unidade.cnes as unidade_cnes',
'cadastro_municipio.ibge as municipio_ibge',
'cadastro_cidadao.cns AS usuario_cns',
'cadastro_cidadao.nome AS profissional_nome',
'sigtap.ocupacao.codigo as ocupacao_codigo',
])
->join('atencao_basica_parametrizacao_equipe', 'atencao_basica_parametrizacao_equipe.id', 'atencao_basica_ficha_vacinacao.equipe_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_ficha_vacinacao.usuario_id')
->join('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_usuario.cidadao_id')
->join('sigtap.ocupacao', 'sigtap.ocupacao.id', 'atencao_basica_ficha_vacinacao.ocupacao_id')
->whereBetween('atencao_basica_ficha_vacinacao.data_atendimento', [$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_ficha_vacinacao.usuario_id', request()->usuario_id))
->get();
if ($fichasVacinacao->isEmpty()) {
return [];
}
$vacinacoesPorFicha = self::loadVacinacoes($fichasVacinacao->pluck('id')->all());
$todosVacinacaoIds = [];
foreach ($vacinacoesPorFicha as $vacinacoes) {
foreach ($vacinacoes as $vacinacao) {
$todosVacinacaoIds[] = $vacinacao->id;
}
}
$itensPorVacinacao = self::loadVacinacaoItens($todosVacinacaoIds);
$groupedList = [];
foreach ($fichasVacinacao as $ficha) {
$errosHeader = RelatorioInconsistenciaService::validHeader($ficha, Permissao::FICHA_DE_VACINACAO);
$headerDescriptions = self::mapErrors($errosHeader, self::HEADER_ERROR_MAP, $inconsistencias);
foreach ($vacinacoesPorFicha[$ficha->id] ?? [] as $vacinacao) {
$errosVacinacao = self::validVacinacao($vacinacao, $ficha->data_atendimento);
$pacienteDescriptions = self::mapErrors($errosVacinacao, self::PACIENTE_ERROR_MAP, $inconsistencias);
$vacinaDescriptions = collect();
foreach ($itensPorVacinacao[$vacinacao->id] ?? [] as $item) {
$errosVacina = self::validVacina($item, $vacinacao->paciente_data_nascimento, $vacinacao->hanseniase);
$vacinaDescriptions = $vacinaDescriptions->merge(
self::mapVacinaErrors($errosVacina, $item, $inconsistencias)
);
}
$errorDescriptions = collect($headerDescriptions->all())
->merge($pacienteDescriptions)
->merge($vacinaDescriptions);
if ($errorDescriptions->isEmpty()) {
continue;
}
$key = $ficha->data_atendimento . '|' . $vacinacao->paciente_id . '|' . $ficha->usuario_id;
if (!isset($groupedList[$key])) {
$groupedList[$key] = [
'data' => (new Carbon($ficha->data_atendimento))->format('d/m/Y'),
'ficha' => self::FICHA_LABEL,
'paciente_nome' => $vacinacao->paciente_nome,
'paciente_cns' => $vacinacao->paciente_cns ? MaskUtil::getCnsMasked($vacinacao->paciente_cns) : '-',
'paciente_cpf' => $vacinacao->paciente_cpf ? MaskUtil::getCpfMasked($vacinacao->paciente_cpf) : '-',
'paciente_nome_social' => $vacinacao->paciente_nome_social,
'paciente_preferencia_nome_id' => $vacinacao->paciente_preferencia_nome_id,
'paciente_prontuario' => $vacinacao->paciente_prontuario,
'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 mapErrors(Collection $errors, array $map, Collection $inconsistencias): Collection
{
$descriptions = collect();
foreach ($errors as $error) {
$inconsistenciaId = $map[$error] ?? null;
if ($inconsistenciaId === null) {
continue;
}
$descricao = $inconsistencias[$inconsistenciaId] ?? null;
if ($descricao !== null) {
$descriptions->push($descricao);
}
}
return $descriptions;
}
private static function mapVacinaErrors(Collection $errors, $item, Collection $inconsistencias): Collection
{
$descriptions = collect();
foreach ($errors as $error) {
if ($error === EstrategiaIsValidForFicha::class) {
$descricao = $inconsistencias[Inconsistencia::ESTRATEGIA_INCORRETA] ?? null;
if ($descricao !== null) {
$descriptions->push($descricao . ' - ' . $item->vacina_descricao);
}
continue;
}
if ($error === FabricanteIsValid::class) {
continue;
}
$inconsistenciaId = self::VACINA_ERROR_MAP[$error] ?? null;
if ($inconsistenciaId === null) {
continue;
}
$descricao = $inconsistencias[$inconsistenciaId] ?? null;
if ($descricao !== null) {
$descriptions->push($descricao);
}
}
return $descriptions;
}
private static function handleVacinaAplicadaExterior($item): bool
{
return $item->registro_anterior && in_array($item->vacina_codigo, VacinaAplicadaExterior::getConstants());
}
private static function validVacinacao($vacinacao, $data_atendimento): Collection
{
$errors = collect();
if (!Cns::isValid($vacinacao->paciente_cns) && !Cpf::isValid($vacinacao->paciente_cpf)) {
$errors->push(CnsPaciente::class);
$errors->push(Cpf::class);
}
if (!DataNascimentoIsRequired::isValid($vacinacao->paciente_data_nascimento)) {
$errors->push(DataNascimentoIsRequired::class);
}
if (!DataNascimentoIsValid::isValid([
'data_nascimento' => $vacinacao->paciente_data_nascimento,
'data_atendimento' => $data_atendimento
])) {
$errors->push(DataNascimentoIsValid::class);
}
if (!LocalAtendimentoIsRequired::isValid($vacinacao->local_atendimento_id)) {
$errors->push(LocalAtendimentoIsRequired::class);
}
if (!LocalAtendimentoIsValid::isValid($vacinacao->local_atendimento_id)) {
$errors->push(LocalAtendimentoIsValid::class);
}
if (!GestanteIsValidForFicha::isValid($vacinacao)) {
$errors->push(GestanteIsValidForFicha::class);
}
if (!PuerperaIsValidForFicha::isValid($vacinacao)) {
$errors->push(PuerperaIsValidForFicha::class);
}
if (PuerperaAndGestanteIsChecked::isValid($vacinacao)) {
$errors->push(PuerperaAndGestanteIsChecked::class);
}
return $errors;
}
private static function validVacina($item, $pacienteDataNascimento, $hanseniase): Collection
{
$errors = collect();
if (!$item->registro_anterior && !EstrategiaIsValid::isValid($item->estrategia_codigo)) {
$errors->push(EstrategiaIsValid::class);
}
if ($item->registro_anterior) {
if (!EstrategiaIsValidForFicha::isValid($item)) {
$errors->push(EstrategiaIsValidForFicha::class);
}
}
if (!DoseIsValid::isValid($item->dose_id)) {
$errors->push(DoseIsValid::class);
}
if (!$item->registro_anterior && !LoteIsRequired::isValid($item->entrada_lote)) {
$errors->push(LoteIsRequired::class);
}
if ($item->registro_anterior && !DataRegistroAnteriorIsRequired::isValid($item->data)) {
$errors->push(DataRegistroAnteriorIsRequired::class);
}
if (!$item->registro_anterior && !FabricanteIsRequired::isValid($item->produtor_id)) {
$errors->push(FabricanteIsRequired::class);
}
if (!DataRegistroAnteriorIsValid::isValid([
'registro_anterior' => $item->registro_anterior,
'data' => $item->data,
'data_nascimento' => $pacienteDataNascimento
])) {
$errors->push(DataRegistroAnteriorIsValid::class);
}
if ($item->produtor_nome && $item->vacina_codigo && !FabricanteIsValid::isValid(['fabricante' => $item->produtor_nome, 'vacina' => $item->vacina_codigo])) {
$errors->push(FabricanteIsValid::class);
}
if (self::handleVacinaAplicadaExterior($item) && !AplicadoExteriorIsRequired::isValid($item->aplicado_exterior)) {
$errors->push(AplicadoExteriorIsRequired::class);
}
if (!$item->registro_anterior && !GrupoIsRequired::isValid($item->grupo_id)) {
$errors->push(GrupoIsRequired::class);
}
if ($item->registro_anterior && !GrupoIsValid::isValid($item->grupo_id)) {
$errors->push(GrupoIsValid::class);
}
if (VacinaIsDuplicate::isValid($item)) {
$errors->push(VacinaIsDuplicate::class);
}
if (!$item->registro_anterior && !VacinaIsValid::isValid($item)) {
$errors->push(VacinaIsValid::class);
}
if ($item->vacina_codigo == Imunobiologico::BCG
&& !ComunicanteHanseniaseIsRequired::isValid($hanseniase)) {
$errors->push(ComunicanteHanseniaseIsRequired::class);
}
return $errors;
}
private static function loadVacinacoes(array $fichaIds): array
{
if (empty($fichaIds)) {
return [];
}
$rows = DB::table('atencao_basica_vacinacao_paciente as vacinacao')
->select(
'vacinacao.id as id',
'vacinacao.vacinacao_id',
'cadastro_cidadao.cns as paciente_cns',
'cadastro_cidadao.cpf as paciente_cpf',
'cadastro_cidadao.nome as paciente_nome',
'cadastro_cidadao.nome_social as paciente_nome_social',
'cadastro_cidadao.preferencia_nome_id as paciente_preferencia_nome_id',
'cadastro_cidadao.data_nascimento as paciente_data_nascimento',
'cadastro_cidadao.sexo_id as paciente_sexo_id',
DB::raw('LPAD(cadastro_paciente.prontuario,7,0) AS paciente_prontuario'),
'vacinacao.paciente_id as paciente_id',
'vacinacao.local_atendimento_id as local_atendimento_id',
'vacinacao.gestante as gestante',
'vacinacao.puerpera as puerpera',
'vacinacao.hanseniase as hanseniase',
)
->join('cadastro_paciente', 'cadastro_paciente.id', 'vacinacao.paciente_id')
->join('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_paciente.cidadao_id')
->whereIn('vacinacao.vacinacao_id', $fichaIds)
->get();
$porFicha = [];
foreach ($rows as $row) {
$porFicha[$row->vacinacao_id][] = $row;
}
return $porFicha;
}
private static function loadVacinacaoItens(array $vacinacaoIds): array
{
if (empty($vacinacaoIds)) {
return [];
}
$rows = DB::table('atencao_basica_vacinacao_paciente_item as item')
->select(
'item.estrategia_id as estrategia_id',
'imunizacao_estrategia.codigo_rnds as estrategia_codigo',
'item.vacina_id as vacina_id',
'cadastro_vacina.nome as vacina_descricao',
'item.dose_id as dose_id',
'imunizacao_dose.codigo_esus as dose_codigo',
'item.registro_anterior as registro_anterior',
'item.produtor_id as produtor_id',
'item.grupo_id as grupo_id',
'item.aplicado_exterior as aplicado_exterior',
'item.data as data',
'item.vacinacao_paciente_id as vacinacao_paciente_id',
'cadastro_vacina.codigo as vacina_codigo',
'imunizacao_produtor.nome as produtor_nome',
'imunizacao_entrada_vacina.lote as entrada_lote',
)
->join('cadastro_vacina', 'cadastro_vacina.id', 'item.vacina_id')
->leftJoin('imunizacao_produtor', 'imunizacao_produtor.id', 'item.produtor_id')
->leftJoin('imunizacao_entrada_vacina', 'imunizacao_entrada_vacina.id', 'item.entrada_id')
->leftJoin('imunizacao_estrategia', 'imunizacao_estrategia.id', 'item.estrategia_id')
->leftJoin('imunizacao_dose', 'imunizacao_dose.id', 'item.dose_id')
->whereIn('item.vacinacao_paciente_id', $vacinacaoIds)
->get();
$porVacinacao = [];
foreach ($rows as $row) {
$porVacinacao[$row->vacinacao_paciente_id][] = $row;
}
return $porVacinacao;
}
}