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,438 @@
<?php
namespace App\Services\AtencaoBasica\RelatorioInconsistencia;
use App\Enums\AtencaoBasica\Exportacao\Inconsistencia;
use App\Enums\AtencaoBasica\Parametrizacao\Permissao;
use App\Rules\AtencaoBasica\Exportacao\CnesIsValid;
use App\Rules\AtencaoBasica\Exportacao\CnsPaciente;
use App\Rules\AtencaoBasica\Exportacao\CondicaoAvaliacaoDomiciliarIsValidForFicha;
use App\Rules\AtencaoBasica\Exportacao\CondutaDesfechoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\DataAtendimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\DataNascimentoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\DataNascimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\IbgeIsValid;
use App\Rules\AtencaoBasica\Exportacao\LocalAtendimentoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\LocalAtendimentoIsValid;
use App\Rules\AtencaoBasica\Exportacao\OcupacaoIsAllowed;
use App\Rules\AtencaoBasica\Exportacao\ProblemaCondicaoCiapIsDuplicated;
use App\Rules\AtencaoBasica\Exportacao\ProblemaCondicaoCiapIsValid;
use App\Rules\AtencaoBasica\Exportacao\ProblemaCondicaoCidIsDuplicated;
use App\Rules\AtencaoBasica\Exportacao\ProblemaCondicaoCidIsValid;
use App\Rules\AtencaoBasica\Exportacao\ProblemaCondicaoCidOuCiapIsRequired;
use App\Rules\AtencaoBasica\Exportacao\ProblemaCondicaoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\ProcedimentoLimitIsValid;
use App\Rules\AtencaoBasica\Exportacao\SexoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\TipoAtendimentoDomiciliarIsValid;
use App\Rules\AtencaoBasica\Exportacao\TipoAtendimentoIsRequired;
use App\Rules\AtencaoBasica\Exportacao\TipoModalidadeIsRequired;
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 FichaAtendimentoDomiciliarService 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,
LocalAtendimentoIsRequired::class => Inconsistencia::LOCAL_DE_ATENDIMENTO_SEM_PREENCHIMENTO,
LocalAtendimentoIsValid::class => Inconsistencia::LOCAL_DE_ATENDIMENTO_INVALIDO,
TurnoIsRequired::class => Inconsistencia::TURNO_SEM_PREENCHIMENTO,
CondutaDesfechoIsRequired::class => Inconsistencia::CONDUTA_DESFECHO_SEM_PREENCHIMENTO,
SexoIsRequired::class => Inconsistencia::SEXO_DO_PACIENTE_SEM_PREENCHIMENTO,
ProcedimentoLimitIsValid::class => Inconsistencia::PACIENTE_COM_MAIS_DE_20_PROCEDIMENTOS_INSERIDOS,
TipoAtendimentoIsRequired::class => Inconsistencia::TIPO_DE_ATENDIMENTO_SEM_PREENCHIMENTO,
TipoAtendimentoDomiciliarIsValid::class => Inconsistencia::MODALIDADE_INVALIDA,
TipoModalidadeIsRequired::class => Inconsistencia::MODALIDADE_SEM_PREENCHIMENTO,
CondicaoAvaliacaoDomiciliarIsValidForFicha::class => Inconsistencia::CONDICAO_AVALIADA_INVALIDA,
ProblemaCondicaoIsRequired::class => Inconsistencia::PROBLEMA_OU_CONDICAO_SEM_PREENCHIMENTO,
ProblemaCondicaoCidOuCiapIsRequired::class => Inconsistencia::PROBLEMA_E_CONDICAO_SEM_CIAP2_E_SEM_CID10,
ProblemaCondicaoCiapIsDuplicated::class => Inconsistencia::CIAP2_EM_DUPLICIDADE,
ProblemaCondicaoCiapIsValid::class => Inconsistencia::PROBLEMA_E_CONDICAO_COM_CIAP2_INVALIDO,
ProblemaCondicaoCidIsDuplicated::class => Inconsistencia::CID_EM_DUPLICIDADE,
ProblemaCondicaoCidIsValid::class => Inconsistencia::PROBLEMA_E_CONDICAO_COM_CID10_INVALIDO,
];
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');
$fichasAtendimentoDomiciliar = DB::table('atencao_basica_atendimento_domiciliar')
->select([
'atencao_basica_atendimento_domiciliar.id as id',
'atencao_basica_atendimento_domiciliar.usuario_id as usuario_id',
'atencao_basica_atendimento_domiciliar.data 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',
])
->join('atencao_basica_parametrizacao_equipe', 'atencao_basica_parametrizacao_equipe.id', 'atencao_basica_atendimento_domiciliar.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_atendimento_domiciliar.usuario_id')
->join('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_usuario.cidadao_id')
->join('sigtap.ocupacao', 'sigtap.ocupacao.id', 'atencao_basica_atendimento_domiciliar.ocupacao_id')
->whereBetween('atencao_basica_atendimento_domiciliar.data', [$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_atendimento_domiciliar.usuario_id', request()->usuario_id))
->get();
if ($fichasAtendimentoDomiciliar->isEmpty()) {
return [];
}
$atendimentosPorFicha = self::loadAtendimentos($fichasAtendimentoDomiciliar->pluck('id')->all());
$allAtendimentoIds = [];
foreach ($atendimentosPorFicha as $atendimentos) {
foreach ($atendimentos as $atendimento) {
$allAtendimentoIds[] = $atendimento->id;
}
}
$problemasCondicoesPorAtendimento = self::loadProblemasCondicoes($allAtendimentoIds);
$groupedList = [];
foreach ($fichasAtendimentoDomiciliar as $ficha) {
$errosHeader = RelatorioInconsistenciaService::validHeader($ficha, Permissao::ATENDIMENTO_DOMICILIAR);
foreach ($atendimentosPorFicha[$ficha->id] ?? [] as $atendimento) {
$problemasCondicoes = $problemasCondicoesPorAtendimento[$atendimento->id] ?? collect();
$errors = $errosHeader->merge(self::validAtendimento($atendimento, $ficha, $problemasCondicoes));
$errorDescriptions = self::mapErrorsToDescriptions($errors, $inconsistencias);
if ($errorDescriptions->isEmpty()) {
continue;
}
$key = $ficha->data_atendimento . '|' . $atendimento->paciente_id . '|' . $ficha->usuario_id;
if (!isset($groupedList[$key])) {
$groupedList[$key] = [
'data' => (new Carbon($ficha->data_atendimento))->format('d/m/Y'),
'ficha' => 'Atendimento domiciliar',
'paciente_nome' => $atendimento->paciente_nome,
'paciente_nome_social' => $atendimento->paciente_nome_social,
'paciente_preferencia_nome_id' => $atendimento->paciente_preferencia_nome_id,
'paciente_prontuario' => $atendimento->paciente_prontuario,
'paciente_cns' => $atendimento->paciente_cns ? MaskUtil::getCnsMasked($atendimento->paciente_cns) : '-',
'paciente_cpf' => $atendimento->paciente_cpf ? MaskUtil::getCpfMasked($atendimento->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($atendimento, $fichaAtendimentoDomiciliar, Collection $problemasCondicoes): Collection
{
$errors = collect();
if (!Cns::isValid($atendimento->paciente_cns) && !Cpf::isValid($atendimento->paciente_cpf)) {
$errors->push(CnsPaciente::class);
$errors->push(Cpf::class);
}
if (!DataNascimentoIsRequired::isValid($atendimento->paciente_data_nascimento)) {
$errors->push(DataNascimentoIsRequired::class);
}
if (!DataNascimentoIsValid::isValid([
'data_nascimento' => $atendimento->paciente_data_nascimento,
'data_atendimento' => $fichaAtendimentoDomiciliar->data_atendimento
])) {
$errors->push(DataNascimentoIsValid::class);
}
if (!LocalAtendimentoIsRequired::isValid($atendimento->local_atendimento_id)) {
$errors->push(LocalAtendimentoIsRequired::class);
}
if (!TipoAtendimentoIsRequired::isValid($atendimento->tipo_atendimento_id)) {
$errors->push(TipoAtendimentoIsRequired::class);
}
if (!TipoAtendimentoDomiciliarIsValid::isValid($atendimento->tipo_atendimento_id)) {
$errors->push(TipoAtendimentoDomiciliarIsValid::class);
}
if (!TipoModalidadeIsRequired::isValid($atendimento)) {
$errors->push(TipoModalidadeIsRequired::class);
}
if (!CondicaoAvaliacaoDomiciliarIsValidForFicha::isValid($atendimento)) {
$errors->push(CondicaoAvaliacaoDomiciliarIsValidForFicha::class);
}
if (!TurnoIsRequired::isValid($atendimento->turno_id)) {
$errors->push(TurnoIsRequired::class);
}
if (!CondutaDesfechoIsRequired::isValid($atendimento->conduta_desfecho_id)) {
$errors->push(CondutaDesfechoIsRequired::class);
}
if (!SexoIsRequired::isValid($atendimento->paciente_sexo_id)) {
$errors->push(SexoIsRequired::class);
}
if (!ProblemaCondicaoIsRequired::isValid($problemasCondicoes)) {
$errors->push(ProblemaCondicaoIsRequired::class);
}
if (!ProblemaCondicaoCidOuCiapIsRequired::isValid($problemasCondicoes)) {
$errors->push(ProblemaCondicaoCidOuCiapIsRequired::class);
}
if (!ProblemaCondicaoCiapIsDuplicated::isValid($problemasCondicoes)) {
$errors->push(ProblemaCondicaoCiapIsDuplicated::class);
}
if (!ProblemaCondicaoCiapIsValid::isValid($problemasCondicoes, $atendimento->paciente_idade)) {
$errors->push(ProblemaCondicaoCiapIsValid::class);
}
if (!ProblemaCondicaoCidIsDuplicated::isValid($problemasCondicoes)) {
$errors->push(ProblemaCondicaoCidIsDuplicated::class);
}
if (!ProblemaCondicaoCidIsValid::isValid($problemasCondicoes)) {
$errors->push(ProblemaCondicaoCidIsValid::class);
}
return $errors;
}
private static function loadAtendimentos(array $fichaIds): array
{
if (empty($fichaIds)) {
return [];
}
$rows = DB::table('atencao_basica_atendimento_domiciliar_atendimento as ad')
->select([
'ad.id as id',
'ad.atendimento_domiciliar_id',
'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'),
'ad.local_atendimento_id',
'ad.turno_id',
'ad.tipo_atendimento_id',
'ad.modalidade_id',
'ad.conduta_desfecho_id',
'ad.paciente_id',
DB::raw('TIMESTAMPDIFF(YEAR, paciente_cidadao.data_nascimento, NOW()) AS paciente_idade'),
])
->join('cadastro_paciente', 'cadastro_paciente.id', 'ad.paciente_id')
->join('cadastro_cidadao as paciente_cidadao', 'paciente_cidadao.id', 'cadastro_paciente.cidadao_id')
->whereIn('ad.atendimento_domiciliar_id', $fichaIds)
->get();
$porFicha = [];
foreach ($rows as $row) {
$porFicha[$row->atendimento_domiciliar_id][] = $row;
}
return $porFicha;
}
private static function loadProblemasCondicoes(array $atendimentoIds): array
{
if (empty($atendimentoIds)) {
return [];
}
$problemasCondicoesRaw = DB::table('atencao_basica_atendimento_domiciliar_atend_problema_condicao as pc')
->select([
'pc.atendimento_domiciliar_atendimento_id',
'pc.ciap_id',
'pc.cid_id',
'geral_ciap.codigo as ciap_codigo',
'geral_ciap.grupo_id as ciap_grupo_id',
'cid.codigo as cid_codigo',
DB::raw("IF (cid.codigo LIKE 'Z34%', 1, 0) as is_cid_familia_Z34"),
])
->leftJoin('geral_ciap', 'geral_ciap.id', 'pc.ciap_id')
->leftJoin('sigtap.cid', 'cid.id', 'pc.cid_id')
->whereIn('pc.atendimento_domiciliar_atendimento_id', $atendimentoIds)
->get()
->groupBy('atendimento_domiciliar_atendimento_id');
$codigosEsusPorAtendimento = self::loadCodigosEsus($atendimentoIds);
$todosCodigos = collect($codigosEsusPorAtendimento)->flatten()->unique()->values()->all();
$ciapsPorCodigoEsus = self::loadCiapsPorCodigoEsus($todosCodigos);
$resultado = [];
foreach ($atendimentoIds as $id) {
$problemasCondicoes = collect($problemasCondicoesRaw[$id] ?? [])
->map(function ($pc) {
$pc->atendimento_domiciliar_atendimento_id = null;
$pc->is_cid_familia_Z34 = (bool) $pc->is_cid_familia_Z34;
return $pc;
})
->values();
$ciapsAdicionais = collect();
$vistos = [];
foreach ($codigosEsusPorAtendimento[$id] ?? [] as $codigo) {
foreach ($ciapsPorCodigoEsus[$codigo] ?? [] as $ciap) {
if (!isset($vistos[$ciap->ciap_id])) {
$ciapsAdicionais->push($ciap);
$vistos[$ciap->ciap_id] = true;
}
}
}
$resultado[$id] = $problemasCondicoes->concat($ciapsAdicionais)->values();
}
return $resultado;
}
private static function loadCodigosEsus(array $atendimentoIds): array
{
$fontes = [
['atencao_basica_atendimento_domiciliar_atend_condicao_avaliada', 'atencao_basica_cadastro_condicao_avaliada', 'condicao_avaliada_id'],
['atencao_basica_atendimento_domiciliar_atend_doenca_transmissivel', 'atencao_basica_cadastro_doenca_transmissivel', 'doenca_transmissivel_id'],
['atencao_basica_atendimento_domiciliar_atend_rastreamento', 'atencao_basica_cadastro_rastreamento', 'rastreamento_id'],
];
$codigos = [];
foreach ($fontes as [$tabelaLink, $tabelaCadastro, $fk]) {
$rows = DB::table($tabelaLink)
->join($tabelaCadastro, "{$tabelaCadastro}.id", "{$tabelaLink}.{$fk}")
->whereIn("{$tabelaLink}.atendimento_domiciliar_atendimento_id", $atendimentoIds)
->select(
"{$tabelaLink}.atendimento_domiciliar_atendimento_id",
"{$tabelaCadastro}.codigo_esus"
)
->get();
foreach ($rows as $row) {
$codigos[$row->atendimento_domiciliar_atendimento_id][] = $row->codigo_esus;
}
}
return $codigos;
}
private static function loadCiapsPorCodigoEsus(array $codigos): array
{
if (empty($codigos)) {
return [];
}
$rows = DB::table('geral_ciap_codigo_esus')
->join('geral_ciap', 'geral_ciap.id', 'geral_ciap_codigo_esus.ciap_id')
->whereIn('geral_ciap_codigo_esus.codigo', $codigos)
->select(
'geral_ciap_codigo_esus.codigo as esus_codigo',
'geral_ciap.id',
'geral_ciap.codigo',
'geral_ciap.grupo_id'
)
->get();
$ciapsPorCodigo = [];
foreach ($rows as $row) {
$ciapsPorCodigo[$row->esus_codigo][] = (object) [
'ciap_id' => $row->id,
'cid_id' => null,
'ciap_codigo' => $row->codigo,
'ciap_grupo_id' => $row->grupo_id,
'cid_codigo' => null,
'is_cid_familia_Z34' => false,
];
}
return $ciapsPorCodigo;
}
}