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

1331 lines
53 KiB
PHP

<?php
namespace App\Services\Ambulatorio\AtendimentoEnfermagem;
use App\Enums\Ambulatorio\AgendamentoStatus;
use App\Enums\Ambulatorio\AgendamentoTipo;
use App\Enums\Ambulatorio\TesteRapido as TesteRapidoEnum;
use App\Enums\Ambulatorio\Desfecho;
use App\Enums\AtencaoBasica\AtendimentoIndividual\LocalAtendimento as LocalAtendimentoEnum;
use App\Enums\AtencaoBasica\Procedimento\ViaAdministracao as ProcedimentoViaAdministracao;
use App\Enums\Cadastro\SujeitoAtencao\Classificacao;
use App\Enums\Cadastro\SujeitoAtencao\TipoRegistroUsuario;
use App\Enums\Geral\Turno as TurnoEnum;
use App\Enums\PainelSenha\Status;
use App\Enums\Regulacao\StatusTipo as RegulacaoStatusTipo;
use App\Exceptions\Ambulatorio\NaoPodeCriarFichaAtencaoBasicaException;
use App\Models\Administracao\Funcionalidade;
use App\Models\Ambulatorio\AtendimentoPosConsulta;
use App\Models\Ambulatorio\AtendimentoSoapEncaminhamento;
use App\Models\Ambulatorio\AtendimentoSoapExameSolicitado;
use App\Models\Ambulatorio\AtendimentoSoapSolicitacaoExame;
use App\Models\Ambulatorio\AtendimentoSoapSolicitacaoProcedimentoCirurgico;
use App\Models\Ambulatorio\ColetaMaterial;
use App\Models\Ambulatorio\GlicemiaCapilarMomentoColeta;
use App\Models\Ambulatorio\Jornada;
use App\Models\Ambulatorio\OutroProcedimento;
use App\Models\Ambulatorio\ParametrizacaoInfraestrutura;
use App\Models\Ambulatorio\ParametrizacaoInfraestruturaEspecialidade;
use App\Models\Ambulatorio\ParametrizacaoInfraestruturaOcupacao;
use App\Models\Ambulatorio\Servico;
use App\Models\Ambulatorio\TesteRapido;
use App\Models\AtencaoBasica\MarcadorConsumoAlimentar\LocalAtendimento;
use App\Models\AtencaoBasica\Parametrizacao\Equipe;
use App\Models\AtencaoBasica\Procedimento\ViaAdministracao;
use App\Models\Cadastro\Especialidade;
use App\Models\Cadastro\Material\Material;
use App\Models\Cadastro\SujeitoAtencao\CidadaoTelefone;
use App\Models\Cadastro\SujeitoAtencao\Paciente;
use App\Models\Cadastro\SujeitoAtencao\Usuario;
use App\Models\Geral\Turno;
use App\Models\PainelSenha\Fila;
use App\Models\PainelSenha\OpcaoEntrada;
use App\Models\PainelSenha\Prioridade;
use App\Models\Sigtap\Ocupacao;
use App\Models\Sigtap\Procedimento as ProcedimentoSigtap;
use App\Rules\Sigtap\Procedimento\Ocupacao as OcupacaoSigtap;
use App\Rules\Sigtap\QuantidadeIsValidForProcedimento;
use App\Services\Almoxarifado\AlmoxarifadoService;
use App\Services\Ambulatorio\AtendimentoService;
use App\Services\Ambulatorio\FilaService;
use App\Services\Regulacao\SolicitacaoService as RegulacaoSolicitacaoService;
use App\Services\Service;
use App\Services\Sigtap\ProcedimentoValidationService;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class PosConsultaService extends Service
{
public static function list()
{
switch (request()->origem) {
case 'encaminhamento': {
$params = (object) request()->all();
switch (request()->listar) {
case 'centros-custo-encaminhamento': {
return [
'centros_custo_encaminhamento' => self::getCentrosCustoEncaminhamento($params),
'opcoes_entrada_encaminhamento' => [],
];
}
case 'opcoes-entrada-encaminhamento': {
return [
'opcoes_entrada_encaminhamento' => self::getOpcoesEntradaEncaminhamento($params),
];
}
}
break;
}
default: {
$params = (object) request()->all();
$atendimento = Fila::findOrFail($params->fila_id)->ambulatorioAtendimento;
$params->paciente_id = $atendimento->paciente->id;
$params->paciente_nao_municipe = $atendimento->paciente->classificacao_id !== Classificacao::MUNICIPE;
$params->infraestrutura_id = self::getCurrentCentroCusto()->infraestrutura_id;
$params->data = Carbon::today();
switch (request()->listar) {
case 'ocupacoes': {
return [
'ocupacoes' => self::getOcupacoesWithJornada($params),
'especialidades' => [],
];
}
case 'especialidades': {
return [
'especialidades' => self::getEspecialidadesWithJornada($params),
];
}
}
break;
}
}
}
public static function create()
{
$fila = Fila::findOrFail(request()->fila_id);
FilaService::answer($fila->id);
$data = [
'additionals' => self::getAdditionalsData($fila),
'form' => self::getFormData($fila),
'model' => self::getModelData($fila),
];
if ($data['form']['pos-consulta']['equipes']->count() === 1) {
$data['model']['pos-consulta']['equipe_id'] = $data['form']['pos-consulta']['equipes']->first()['id'];
}
return $data;
}
private static function getAdditionalsData($fila)
{
return [
'data_atual' => Carbon::today()->format('d/m/Y'),
'hora_inicio_atendimento' => Carbon::now()->format('H:i'),
'is_demanda_espontanea' => $fila->ambulatorioAtendimento->is_demanda_espontanea,
'fatura_procedimento_raas' => self::faturaProcedimentoRaas(),
'cria_ficha_atencao_basica' => self::criaFicha('procedimento'),
'atendimento_id' => $fila->ambulatorioAtendimento->id,
];
}
public static function criaFicha($funcionalidadeIdentificador)
{
$lotacaoLogada = self::getCurrentLotacao();
return ParametrizacaoInfraestruturaOcupacao::whereHas('parametrizacaoInfraestrutura', fn ($q) => $q
->where('infraestrutura_id', $lotacaoLogada->infraestrutura_id)
)
->where('ocupacao_id', $lotacaoLogada->ocupacao_id)
->whereHas('fichasAtb', fn ($q) => $q
->where('funcionalidade_id', Funcionalidade::whereHas('modulo', fn ($q) => $q
->where('identificador', 'atencao-basica')
)
->where('identificador', $funcionalidadeIdentificador)
->first('id')->id
)
)
->exists();
}
private static function getFormData($fila)
{
$especialidadeId = $fila->ambulatorioAtendimento->is_demanda_espontanea ? ($fila->ambulatorioAtendimento->especialidade->id ?? null) : null;
$demandaEspontaneaObservaVagaAtendimento = self::demandaEspontaneaObservaVagaAtendimento($especialidadeId);
$unidade = $fila->centroCusto->infraestrutura->unidade;
$paciente = $fila->ambulatorioAtendimento->paciente;
$atendimento = $fila->ambulatorioAtendimento;
$usuarios = [];
$ocupacoes = [];
$especialidades = [];
$jornadas = [];
if ($fila->ambulatorioAtendimento->is_demanda_espontanea) {
$desfechoParams = [
'paciente_id' => $paciente->id,
'paciente_nao_municipe' => $paciente->classificacao_id !== Classificacao::MUNICIPE,
'infraestrutura_id' => self::getCurrentCentroCusto()->infraestrutura_id,
'data' => Carbon::today(),
];
$usuarios = self::getUsuariosWithJornada((object) $desfechoParams);
if (!is_null($fila->ambulatorioAtendimento->usuario)) {
$ocupacoes = self::getOcupacoesWithJornada((object) array_merge($desfechoParams, [
'usuario_id' => $fila->ambulatorioAtendimento->usuario->id,
]));
}
if (!is_null($fila->ambulatorioAtendimento->ocupacao)) {
$especialidades = self::getEspecialidadesWithJornada((object) array_merge($desfechoParams, [
'usuario_id' => $fila->ambulatorioAtendimento->usuario->id,
'ocupacao_id' => $fila->ambulatorioAtendimento->ocupacao->id,
]));
}
if ($demandaEspontaneaObservaVagaAtendimento) {
if (!is_null($atendimento->usuario) && !is_null($atendimento->ocupacao)) {
$jornadas = self::getJornadas((object) [
'data' => $atendimento->created_at->format('Y-m-d'),
'usuario_id' => $atendimento->usuario->id,
'ocupacao_id' => $atendimento->ocupacao->id,
'infraestrutura_id' => $desfechoParams['infraestrutura_id'],
]);
}
}
}
return [
'unidade' => [
'cnes' => $unidade->cnes,
],
'paciente' => self::getPacienteData($paciente),
'usuario' => [
'nome' => $atendimento->usuario->nome ?? null,
'ocupacao_codigo' => $atendimento->ocupacao->codigo ?? null,
'especialidade_nome' => $atendimento->especialidade->nome ?? null,
],
'soap' => [
'plano' => self::getPlanoFormData($atendimento),
],
'pos-consulta' => [
'testes_rapidos' => self::getTestesRapidos($paciente),
'administracoes_medicamentos' => ViaAdministracao::whereIn('id', [
ProcedimentoViaAdministracao::ENDOVENOSA,
ProcedimentoViaAdministracao::INTRAMUSCULAR,
ProcedimentoViaAdministracao::ORAL,
ProcedimentoViaAdministracao::PENICILINA_PARA_TRATAMENTO_DE_SIFILIS,
ProcedimentoViaAdministracao::TOPICA,
ProcedimentoViaAdministracao::SUBCUTANEA,
])
->orderBy('descricao')
->get(['id', 'codigo_procedimento', 'descricao']),
'outros_procedimentos' => OutroProcedimento::orderBy('nome')->get(['id', 'codigo', 'nome']),
'coletas_materiais' => self::getColetasMateriais($paciente),
'equipes' => self::getEquipesUsuarioLogado(),
'locais_atendimento' => LocalAtendimento::orderBy('descricao')->get(['id', 'descricao']),
'turnos' => Turno::orderBy('id')->get(['id', 'nome']),
'desfecho' => [
'usuarios' => $usuarios,
'ocupacoes' => $ocupacoes,
'especialidades' => $especialidades,
'jornadas' => $jornadas,
'opcoes_entrada' => self::getOpcoesEntrada($fila),
'prioridades' => self::getPrioridades(),
'servicos' => self::getServicos(),
'modulos_encaminhamento' => self::getModulosEncaminhamento($fila),
'centros_custo_encaminhamento' => [],
'opcoes_entrada_encaminhamento' => [],
],
'glicemia_capilar' => [
'momentos_coleta' => self::getGlicemiaCapilarMomentosColeta(),
],
],
'historico' => AtendimentoService::getHistorico($paciente->id),
];
}
private static function getTestesRapidos($paciente)
{
return TesteRapido::orderBy('nome')
->whereNotIn(
'id',
[
TesteRapidoEnum::DETECCAO_DE_HEPATITE_C,
TesteRapidoEnum::SIFILIS_NA_GESTANTE_OU_PAI_PARCEIRO,
TesteRapidoEnum::DETECCAO_DE_HIV_NA_GESTANTE_OU_PAI_PARCEIRO,
TesteRapidoEnum::DETECCAO_DE_INFECCAO_PELO_HBV
]
)
->get(['id', 'codigo', 'nome'])
->filter(function ($testeRapido) use ($paciente) {
if (is_null($testeRapido->codigo) || is_null($paciente->cidadao->sexo)) {
return true;
}
$procedimento = ProcedimentoSigtap::where('codigo', $testeRapido->codigo)
->orderByDesc('competencia_id')
->first();
return (new ProcedimentoValidationService($procedimento))->isSexoValid($paciente->cidadao->sexo);
})
->values();
}
private static function getColetasMateriais($paciente)
{
return ColetaMaterial::orderBy('nome')
->get(['id', 'codigo', 'nome'])
->filter(function ($coletaMaterial) use ($paciente) {
if (is_null($coletaMaterial->codigo) || is_null($paciente->cidadao->sexo)) {
return true;
}
$procedimento = ProcedimentoSigtap::where('codigo', $coletaMaterial->codigo)
->orderByDesc('competencia_id')
->first();
return (new ProcedimentoValidationService($procedimento))->isSexoValid($paciente->cidadao->sexo);
})
->values();
}
private static function getGlicemiaCapilarMomentosColeta()
{
return GlicemiaCapilarMomentoColeta::orderBy('id')->get(['id', 'nome']);
}
private static function getEquipesUsuarioLogado()
{
$lotacao = self::getCurrentLotacao();
return Equipe::where('infraestrutura_id', $lotacao->infraestrutura_id)
->whereHas('usuarios', function ($q) use ($lotacao) {
$q->where('cadastro_usuario.id', $lotacao->usuario_id)
->where('atencao_basica_parametrizacao_equipe_usuario.ativo', 1);
})
->get()
->map(fn($equipe) => [
'id' => $equipe->id,
'descricao' => "INE: {$equipe->area->numero_ine} - Área: {$equipe->area->descricao}"
. (is_null($equipe->microarea_id) ? '' : " - Microárea: {$equipe->microarea->descricao}"),
])
->sortBy('descricao')
->values();
}
public static function getPacienteData($paciente)
{
$municipioResidencia = $paciente->cidadao->domicilio->endereco->logradouro->municipio ?? null;
return [
'id' => $paciente->id,
'nome' => $paciente->cidadao->nome,
'nome_social' => $paciente->cidadao->nome_social,
'preferencia_nome_id' => $paciente->cidadao->preferencia_nome_id,
'sexo_id' => $paciente->cidadao->sexo_id,
'sexo_identificador' => $paciente->cidadao->sexo->identificador,
'sexo_descricao' => $paciente->cidadao->sexo->descricao,
'data_nascimento' => is_null($paciente->cidadao->data_nascimento)
? null
: (new Carbon($paciente->cidadao->data_nascimento))->format('d/m/Y'),
'idade' => $paciente->cidadao->idade_formatada,
'nome_mae' => $paciente->cidadao->nome_mae,
'prontuario' => $paciente->prontuario,
'cpf' => MaskUtil::getCpfMasked($paciente->cidadao->cpf),
'cns' => MaskUtil::getCnsMasked($paciente->cidadao->cns),
'municipio_uf' => is_null($municipioResidencia)
? null
: "{$municipioResidencia->nome} / {$municipioResidencia->estado->uf}",
'telefone_id' => $paciente->cidadao->telefone_principal->id ?? null,
'telefone_numero' => MaskUtil::getPhoneMasked($paciente->cidadao->telefone_principal->numero ?? null),
'telefone_autoriza_sms' => $paciente->cidadao->telefone_principal->autoriza_sms ?? false,
'unidade_referencia' => $paciente->unidade->nome_fantasia ?? null,
'cep' => $paciente->cidadao->domicilio->endereco->logradouro->cep ?? null,
'ibge' => $paciente->cidadao->domicilio->endereco->logradouro->municipio->ibge ?? null,
'raca_cor_id' => $paciente->cidadao->racaCorId,
];
}
private static function getOpcoesEntrada($fila)
{
return OpcaoEntrada::where('id', $fila->opcao_entrada_id)
->get(['id', 'nome', 'prioridade_obrigatoria']);
}
private static function getPrioridades()
{
return Prioridade::orderBy('nome')->get(['id', 'nome']);
}
private static function getServicos()
{
return Servico::orderBy('nome')
->whereHas('parametrizacoesInfraestrutura', fn ($q) => $q
->where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
)
->get(['id', 'nome']);
}
private static function getModulosEncaminhamento($fila)
{
return DB::table('administracao_modulo AS modulo')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('painel_senha_opcao_entrada AS opcao_entrada')
->join(
'painel_senha_opcao_entrada_destino AS opcao_entrada_destino',
'opcao_entrada_destino.opcao_entrada_destino_id',
'opcao_entrada.id'
)
->whereColumn('opcao_entrada.modulo_id', 'modulo.id')
->where('opcao_entrada_destino.opcao_entrada_origem_id', $fila->opcao_entrada_id)
)
->select(
'modulo.id',
'modulo.nome'
)
->orderBy('modulo.nome')
->get();
}
private static function getCentrosCustoEncaminhamento($params)
{
return DB::table('cadastro_centro_custo AS centro_custo')
->join('cadastro_setor AS setor', 'setor.id', 'centro_custo.setor_id')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('painel_senha_opcao_entrada AS opcao_entrada')
->join(
'painel_senha_opcao_entrada_destino AS opcao_entrada_destino',
'opcao_entrada_destino.opcao_entrada_destino_id',
'opcao_entrada.id'
)
->whereColumn('opcao_entrada.centro_custo_id', 'centro_custo.id')
->where('opcao_entrada_destino.opcao_entrada_origem_id', $params->opcao_entrada_origem_id)
->where('opcao_entrada.modulo_id', $params->modulo_id)
)
->select(
'centro_custo.id',
'setor.nome AS setor_nome'
)
->orderBy('setor.nome')
->get();
}
private static function getOpcoesEntradaEncaminhamento($params)
{
return DB::table('painel_senha_opcao_entrada AS opcao_entrada')
->join(
'painel_senha_opcao_entrada_destino AS opcao_entrada_destino',
'opcao_entrada_destino.opcao_entrada_destino_id',
'opcao_entrada.id'
)
->where('opcao_entrada_destino.opcao_entrada_origem_id', $params->opcao_entrada_origem_id)
->where('opcao_entrada.modulo_id', $params->modulo_id)
->where('opcao_entrada.centro_custo_id', $params->centro_custo_id)
->select(
'opcao_entrada.id',
'opcao_entrada.nome',
'opcao_entrada.prioridade_obrigatoria'
)
->orderBy('opcao_entrada.nome')
->get();
}
private static function getUsuariosWithJornada($params)
{
return Usuario::setEagerLoads([])
->whereHas('lotacoes', fn ($q) => $q
->where('infraestrutura_id', $params->infraestrutura_id)
->whereHas('ambulatorioJornadas', fn ($q) => $q
->whereNotNull('quantidade_consulta')
->whereNull('situacao_id')
->whereDate('data', $params->data)
)
)
->get(['id', 'cidadao_id'])
->map(fn ($usuario) => [
'id' => $usuario->id,
'nome' => $usuario->cidadao()->setEagerLoads([])->first(['nome'])->nome,
])
->sortBy('nome')
->values();
}
private static function getOcupacoesWithJornada($params)
{
return DB::table('sigtap.ocupacao as ocupacao')
->whereExists(fn ($q) => $q
->select(DB::raw(1))
->from('cadastro_lotacao as lotacao')
->whereColumn('lotacao.ocupacao_id', 'ocupacao.id')
->where('lotacao.usuario_id', $params->usuario_id)
->where('lotacao.infraestrutura_id', $params->infraestrutura_id)
->whereExists(fn ($q) => $q
->select(DB::raw(1))
->from('ambulatorio_jornada as jornada')
->join(
'cadastro_especialidade as especialidade',
'especialidade.id',
'jornada.especialidade_id'
)
->whereColumn('jornada.lotacao_id', 'lotacao.id')
->whereNotNull('jornada.quantidade_consulta')
->whereNull('jornada.situacao_id')
->whereDate('jornada.data', $params->data)
->where(fn ($query) => self::setCadastroWhereEspecialidadePaciente(
$query,
$params->paciente_id,
'especialidade'
))
->when($params->paciente_nao_municipe, fn ($q) => $q
->where('especialidade.permite_agendamento_nao_municipe', true)
)
)
)
->orderByRaw("CONCAT(ocupacao.codigo, ' - ', ocupacao.nome)")
->select(DB::raw("
ocupacao.id,
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as descricao
"))
->get();
}
private static function getEspecialidadesWithJornada($params)
{
return Especialidade::where(fn ($q) => self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id))
->whereHas('ambulatorioJornadas', fn ($q) => $q
->whereNotNull('quantidade_consulta')
->whereNull('situacao_id')
->whereDate('data', $params->data)
->whereHas('lotacao', fn ($q) => $q
->where('infraestrutura_id', $params->infraestrutura_id)
->where('usuario_id', $params->usuario_id)
->where('ocupacao_id', $params->ocupacao_id)
)
)
->when($params->paciente_nao_municipe, fn ($q) => $q
->where('permite_agendamento_nao_municipe', true)
)
->orderBy('nome')
->get()
->map(fn ($q) => [
'id' => $q->id,
'nome' => $q->nome,
'demanda_espontanea_observa_vaga_atendimento' => $q->ambulatorioParametrizacoesInfraestruturaEspecialidade()
->whereHas('parametrizacaoInfraestrutura', fn ($q) => $q->where('infraestrutura_id', $params->infraestrutura_id))
->first()->demanda_espontanea_observa_vaga_atendimento ?? false,
]);
}
private static function setCadastroWhereEspecialidadePaciente($query, $pacienteId, $tableAlias = '')
{
if (!empty($tableAlias)) {
$tableAlias .= '.';
}
$paciente = Paciente::find($pacienteId);
$idade = $paciente->cidadao->idade;
return $query->where(fn ($q) => $q
->when($idade, fn ($q) => $q
->where(fn ($q) => $q
->whereNull("{$tableAlias}idade_minima")
->orWhere("{$tableAlias}idade_minima", '<=', $idade['anos'])
)
->where(fn ($q) => $q
->whereNull("{$tableAlias}idade_maxima")
->orWhere("{$tableAlias}idade_maxima", '>=', $idade['anos'])
)
)
->where(fn ($q) => $q
->whereNull("{$tableAlias}sexo_id")
->orWhere("{$tableAlias}sexo_id", $paciente->cidadao->sexo_id)
)
);
}
private static function getModelData($fila)
{
return [
'pos-consulta' => [
'observacoes' => null,
'procedimentos' => [],
'testes_rapidos' => [],
'administracoes_medicamentos' => [],
'outros_procedimentos' => [],
'coletas_materiais' => [],
'equipe_id' => null,
'atencao_basica_local_atendimento_id' => LocalAtendimentoEnum::UBS,
'turno_id' => self::getTurnoMomento(),
'orientacao_individual_em_saude' => false,
'desfecho' => [
'finalizado' => null,
'ocupacao_id' => $fila->ambulatorioAtendimento->is_demanda_espontanea
? ($fila->ambulatorioAtendimento->ocupacao->id ?? null)
: null,
'especialidade_id' => $fila->ambulatorioAtendimento->is_demanda_espontanea
? ($fila->ambulatorioAtendimento->especialidade->id ?? null)
: null,
'usuario_id' => $fila->ambulatorioAtendimento->is_demanda_espontanea
? ($fila->ambulatorioAtendimento->usuario->id ?? null)
: null,
'jornada_id' => $fila->ambulatorioAtendimento->demandaEspontanea->jornada_id ?? null,
'opcao_entrada_id' => $fila->opcao_entrada_id ?? null,
'prioridade_id' => $fila->prioridade_id ?? null,
'servicos' => $fila->ambulatorioAtendimento->servicos->pluck('id'),
'modulo_encaminhamento_id' => null,
'centro_custo_encaminhamento_id' => null,
'opcao_entrada_encaminhamento_id' => null,
],
'antropometria' => [
'peso' => null,
'altura' => null,
'imc' => [
'imc' => null,
'classificacao' => null,
'grau_obesidade' => null,
],
'perimetro_cefalico' => null,
'circunferencia_abdominal' => null,
'perimetro_panturrilha' => null,
],
'sinal_vital' => [
'pressao_arterial' => null,
'frequencia_respiratoria' => null,
'frequencia_cardiaca' => null,
'temperatura' => null,
'saturacao_o2' => null,
],
'glicemia_capilar' => [
'valor' => null,
'momento_coleta_id' => null,
],
],
];
}
private static function getTurnoMomento()
{
$now = Carbon::now();
$isManha = fn () => $now->hour >= 6 && $now->hour <= 11;
$isTarde = fn () => $now->hour >= 12 && $now->hour <= 17;
if ($isManha()) {
return TurnoEnum::MANHA;
}
else if ($isTarde()) {
return TurnoEnum::TARDE;
}
else {
return TurnoEnum::NOITE;
}
}
public static function store()
{
$fila = Fila::find(request()->fila_id);
self::validateStore($fila);
$posConsulta = new AtendimentoPosConsulta();
DB::transaction(function () use ($posConsulta, $fila) {
$atendimento = $fila->ambulatorioAtendimento;
self::savePaciente();
$posConsulta->fill([
'atendimento_id' => $atendimento->id,
'observacoes' => request()->observacoes,
'equipe_id' => request()->equipe_id,
'atencao_basica_local_atendimento_id' => request()->atencao_basica_local_atendimento_id,
'turno_id' => request()->turno_id,
'orientacao_individual_em_saude' => request()->orientacao_individual_em_saude,
'paciente_liberado' => request()->desfecho['finalizado'],
]);
$posConsulta->save();
$posConsulta->administracoesMedicamentos()->sync(request()->administracoes_medicamentos);
$posConsulta->outrosProcedimentos()->sync(request()->outros_procedimentos);
$posConsulta->coletasMateriais()->sync(request()->coletas_materiais);
self::saveTestesRapidos($posConsulta);
self::saveAvaliacaoAntropometrica($posConsulta);
self::saveSinaisVitais($posConsulta);
self::saveGlicemiaCapilar($posConsulta);
self::saveProcedimentos($posConsulta);
$existeProcedimentos = request()->procedimentos ? true : false;
if (request()->desfecho['finalizado']) {
$atendimento->update([
'finalizado_em' => Carbon::now(),
'finalizado_lotacao_id' => self::getCurrentLotacao()->id,
]);
$atendimento->fila->update(['finalizado' => true]);
if (!$atendimento->is_demanda_espontanea) {
$atendimento->agendamento->update(['status_id' => AgendamentoStatus::REALIZADO]);
if (!is_null($atendimento->agendamento->regulacao_solicitacao_id)) {
RegulacaoSolicitacaoService::updateStatus(
$atendimento->agendamento->regulacao_solicitacao_id,
RegulacaoStatusTipo::REALIZADO
);
}
}
if($existeProcedimentos){
self::storeFichaAtencaoBasica($posConsulta);
}
}
else {
if ($atendimento->is_demanda_espontanea) {
$atendimento->demandaEspontanea()->update([
'ocupacao_id' => request()->desfecho['ocupacao_id'],
'especialidade_id' => request()->desfecho['especialidade_id'],
'usuario_id' => request()->desfecho['usuario_id'],
]);
}
$fila->update([
'opcao_entrada_destino_id' => request()->desfecho['opcao_entrada_encaminhamento_id'],
'prioridade_id' => request()->desfecho['prioridade_id'],
'status_id' => Status::EM_ESPERA,
]);
$atendimento->servicos()->sync(request()->desfecho['servicos']);
if($existeProcedimentos){
self::storeFichaAtencaoBasica($posConsulta);
}
}
if (request()->desfecho['opcao_entrada_encaminhamento_id']) {
$atendimento->update([
'finalizado_em' => Carbon::now(),
'finalizado_lotacao_id' => self::getCurrentLotacao()->id,
]);
if(!$atendimento->is_demanda_espontanea) {
$atendimento->agendamento->update(['status_id' => AgendamentoStatus::REALIZADO]);
}
FilaService::forward(
$fila->id,
OpcaoEntrada::findOrFail(request()->desfecho['opcao_entrada_encaminhamento_id'])->centro_custo_id
);
}
else {
FilaService::dispatch($atendimento->fila->centro_custo_id);
}
});
return $posConsulta->fresh();
}
private static function validateStore($fila)
{
$prioridadeObrigatoria = isset(request()->desfecho['opcao_entrada_encaminhamento_id'])
? (OpcaoEntrada::find(request()->desfecho['opcao_entrada_encaminhamento_id'])->prioridade_obrigatoria ?? false)
: ($fila->opcaoEntrada->prioridade_obrigatoria ?? false);
$rules = [
'paciente.telefone_principal.id' => [
'nullable',
'integer',
Rule::exists(CidadaoTelefone::class, 'id'),
],
'paciente.telefone_principal.numero' => [
'nullable',
'required_with:paciente.telefone_principal.id',
'digits_between:10,11',
],
'paciente.telefone_principal.autoriza_sms' => [
'nullable',
'required_with:paciente.telefone_principal.id',
'boolean',
],
'fila_id' => [
'required',
'integer',
Rule::exists(Fila::class, 'id'),
],
'testes_rapidos' => [
'present',
'array'
],
'testes_rapidos.*.id' => [
'required',
'integer',
Rule::exists(TesteRapido::class, 'id'),
],
'testes_rapidos.*.resultado' => [
'nullable',
'string',
'max:500',
],
'administracoes_medicamentos' => [
'present',
'array'
],
'administracoes_medicamentos.*' => [
'required',
'integer',
Rule::exists(ViaAdministracao::class, 'id'),
],
'outros_procedimentos' => [
'present',
'array'
],
'outros_procedimentos.*' => [
'required',
'integer',
Rule::exists(OutroProcedimento::class, 'id'),
],
'coletas_materiais' => [
'present',
'array'
],
'coletas_materiais.*' => [
'required',
'integer',
Rule::exists(ColetaMaterial::class, 'id'),
],
'observacoes' => [
'nullable',
'string',
'max:5000',
],
'equipe_id' => [
'nullable',
'integer',
Rule::exists(Equipe::class, 'id'),
],
'atencao_basica_local_atendimento_id' => [
'required_with:equipe_id',
'integer',
Rule::exists(LocalAtendimento::class, 'id'),
],
'turno_id' => [
'required_with:equipe_id',
'integer',
Rule::exists(Turno::class, 'id'),
],
'desfecho.usuario_id' => [
'nullable',
'required_with:desfecho.ocupacao_id',
'integer',
Rule::exists(Usuario::class, 'id'),
],
'desfecho.ocupacao_id' => [
'nullable',
'required_with:desfecho.especialidade_id',
'integer',
Rule::exists(Ocupacao::class, 'id'),
],
'desfecho.especialidade_id' => [
'nullable',
'integer',
Rule::exists(Especialidade::class, 'id'),
],
'desfecho.prioridade_id' => [
'nullable',
Rule::requiredIf(fn () => $prioridadeObrigatoria),
Rule::exists(Prioridade::class, 'id'),
],
'desfecho.servicos' => [
'array'
],
'desfecho.servicos.*' => [
'required',
'integer',
Rule::exists(Servico::class, 'id'),
],
'desfecho.finalizado' => [
'required',
'boolean',
],
'desfecho.opcao_entrada_encaminhamento_id' => [
'nullable',
'integer',
Rule::exists(OpcaoEntrada::class, 'id'),
],
'orientacao_individual_em_saude' => [
'required',
'boolean',
],
'procedimentos' => [
'present',
'array',
],
];
foreach (request()->procedimentos as $i => $procedimento) {
$procedimentoModel = ProcedimentoSigtap::find($procedimento['procedimento_id']);
$rules["procedimentos.{$i}.procedimento_id"] = [
'required',
'integer',
'distinct',
Rule::exists(ProcedimentoSigtap::class, 'id'),
new OcupacaoSigtap($procedimentoModel,self::getCurrentLotacao()->ocupacao),
];
$rules["procedimentos.{$i}.material_id"] = [
'nullable',
'integer',
Rule::exists(Material::class, 'id'),
];
$rules["procedimentos.{$i}.automatico"] = [
'required',
'boolean',
];
$rules["procedimentos.{$i}.quantidade"] = [
'required',
'integer',
new QuantidadeIsValidForProcedimento($procedimento['procedimento_id']),
];
$rules["procedimentos.{$i}.material_quantidade"] = [
'nullable',
'integer',
];
$rules["procedimentos.{$i}.local_curativo"] = [
'nullable',
'string',
'max:500',
];
}
request()->validate($rules);
}
private static function storeFichaAtencaoBasica($posConsulta)
{
try {
PosConsultaAtencaoBasicaFichaService::store($posConsulta);
}
catch (Exception $e) {
throw new NaoPodeCriarFichaAtencaoBasicaException();
}
}
private static function savePaciente()
{
if (!is_null(request()->paciente['telefone_principal']['id'])) {
CidadaoTelefone::find(request()->paciente['telefone_principal']['id'])
->update(request()->paciente['telefone_principal']);
}
}
private static function saveProcedimentos($posConsulta)
{
$procedimentos = collect();
foreach (request()->procedimentos as $procedimento) {
$procedimentoCriado = $posConsulta->procedimentos()->create([
'atendimento_id' => $posConsulta->atendimento_id,
'procedimento_id' => $procedimento['procedimento_id'],
'quantidade' => $procedimento['quantidade'],
'automatico' => $procedimento['automatico'],
'ocupacao_id' => $posConsulta->createdLotacao->ocupacao_id,
'especialidade_id' => null,
'usuario_id' => $posConsulta->createdLotacao->usuario_id,
'local_curativo' => $procedimento['local_curativo'] ?? null,
]);
if (!empty($procedimento['materiais']) && is_array($procedimento['materiais'])) {
foreach ($procedimento['materiais'] as $material) {
if (!empty($material['material_id'])) {
$itemData = [
'material_id' => $material['material_id'],
'quantidade' => $material['material_quantidade'],
'escolheu_entrada_item_manualmente' => $material['material_escolheu_entrada_item_manualmente'] ?? false,
'entrada_itens' => $material['material_entrada_itens'] ?? [],
];
$saidaItem = AlmoxarifadoService::saveSaidaDeDispensacaoDoAmbulatorio($itemData);
DB::table('ambulatorio_procedimento_material')->insert([
'ambulatorio_atendimento_procedimento_id' => $procedimentoCriado->id,
'saida_item_id' => $saidaItem->id,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
}
$procedimentos->push($procedimentoCriado);
}
}
private static function saveTestesRapidos($posConsulta)
{
$testesRapidos = [];
foreach (request()->testes_rapidos as $testeRapido) {
$testesRapidos[$testeRapido['id']] = [
'resultado' => $testeRapido['resultado']
];
}
$posConsulta->testesRapidos()->sync($testesRapidos);
}
private static function saveAvaliacaoAntropometrica($posConsulta)
{
if (self::hasData(collect(request()->antropometria))) {
$posConsulta->antropometria()->create(array_merge([
'atendimento_id' => $posConsulta->atendimento_id,
], request()->antropometria));
}
}
private static function saveSinaisVitais($posConsulta)
{
if (self::hasData(collect(request()->sinal_vital))) {
$posConsulta->sinalVital()->create(array_merge([
'atendimento_id' => $posConsulta->atendimento_id,
], request()->sinal_vital));
}
}
private static function saveGlicemiaCapilar($posConsulta)
{
if (self::hasData(collect(request()->glicemia_capilar))) {
$posConsulta->glicemiaCapilar()->create(array_merge([
'atendimento_id' => $posConsulta->atendimento_id,
], request()->glicemia_capilar));
}
}
private static function hasData($items)
{
$has = false;
$items->each(function ($value) use (&$has) {
if (!is_null($value)) {
$has = true;
return false;
}
});
return $has;
}
public static function getPrintData($id)
{
$posConsulta = AtendimentoPosConsulta::findOrFail($id);
return [
'paciente' => (object) self::getPacienteData($posConsulta->atendimento->paciente),
'procedimentos' => $posConsulta->procedimentos->map(fn ($procedimento) => (object) [
'codigo' => $procedimento->procedimento->codigo,
'nome' => $procedimento->procedimento->nome,
'quantidade' => $procedimento->quantidade,
'automatico' => $procedimento->automatico,
'local_curativo' => $procedimento->local_curativo,
'material_descricao_completa' => $procedimento->almoxarifadoSaidaItem->material->descricaoCompleta ?? null,
'material_quantidade' => $procedimento->almoxarifadoSaidaItem->quantidade ?? null,
]),
'observacoes' => $posConsulta->observacoes,
'desfecho' => $posConsulta->paciente_liberado
? Desfecho::PACIENTE_LIBERADO
: Desfecho::MANTER_NA_FILA,
'informacoesAdministrativas' => (object) [
'usuario_nome' => $posConsulta->createdLotacao->usuario->cidadao->nome,
'ocupacao_descricao' => $posConsulta->createdLotacao->ocupacao->codigo . ' - '
. $posConsulta->createdLotacao->ocupacao->nome,
'documento' => $posConsulta->createdLotacao->usuario->registro_tipo_id
? ($posConsulta->createdLotacao->usuario->registro_tipo_id === TipoRegistroUsuario::OUTRO
? $posConsulta->createdLotacao->usuario->registro_tipo_outro
: $posConsulta->createdLotacao->usuario->registroTipo->sigla
) . ": {$posConsulta->createdLotacao->usuario->registro_numero}"
: 'Conselho profissional: NÃO INFORMADO',
],
];
}
private static function faturaProcedimentoRaas()
{
return ParametrizacaoInfraestrutura::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->pluck('fatura_procedimento_raas')
->first();
}
private static function demandaEspontaneaObservaVagaAtendimento($especialidadeId)
{
$response = false;
if (isset($especialidadeId)) {
$currentCentroCusto = self::getCurrentCentroCusto();
$response = ParametrizacaoInfraestruturaEspecialidade::where('especialidade_id', $especialidadeId)
->whereHas('parametrizacaoInfraestrutura', fn ($q) => $q->where('infraestrutura_id', $currentCentroCusto->infraestrutura_id))
->first()->demanda_espontanea_observa_vaga_atendimento ?? false;
}
return $response;
}
private static function getStatusLiberamHorario()
{
return [
AgendamentoStatus::REAGENDADO_PELO_PACIENTE,
AgendamentoStatus::REAGENDADO_PELO_MEDICO,
AgendamentoStatus::CANCELADO_PELO_PACIENTE,
AgendamentoStatus::CANCELADO_PELO_MEDICO,
];
}
private static function getJornadas($params)
{
return Jornada::setEagerLoads([])
->whereHas('lotacao', fn ($q) => $q
->where('usuario_id', $params->usuario_id)
->where('ocupacao_id', $params->ocupacao_id)
->where('infraestrutura_id', $params->infraestrutura_id)
)
->whereNotNull('quantidade_consulta')
->whereNull('situacao_id')
->whereDate('data', $params->data)
->orderBy('inicio')
->get()
->map(function ($jornada) {
$quantidadeAgendamentos = $jornada->agendamentos()
->whereNotIn('status_id', self::getStatusLiberamHorario())
->where('tipo_id', AgendamentoTipo::CONSULTA)
->count();
$quantidadeDemandasEspontaneas = $jornada->demandasEspontaneas()->count();
$quantidadeUtilizada = $quantidadeAgendamentos + $quantidadeDemandasEspontaneas;
$quantidadeConsulta = $jornada->quantidade_consulta;
return [
'id' => $jornada->id,
'quantidade_utilizada' => $quantidadeUtilizada,
'quantidade_consulta' => $quantidadeConsulta,
'inicio' => $jornada->inicio->format('H:i'),
'fim' => $jornada->fim->format('H:i'),
'descricao' => $jornada->inicio->format('d/m/Y H:i') . ' - ' . $quantidadeUtilizada . '/' . $quantidadeConsulta,
];
});
}
private static function getPlanoFormData($atendimento)
{
return [
'solicitacoes_exames_comuns' => self::getSolicitacaoExamesComuns($atendimento),
'solicitacoes_exames_alto_custo' => self::getSolicitacaoExamesAltoCusto($atendimento),
'solicitacoes_procedimentos_cirurgicos' => self::getSolicitacaoProcedimentosCirurgicos($atendimento),
'encaminhamentos' => self::getEncaminhamentos($atendimento),
];
}
private static function getSolicitacaoExamesComuns($atendimento)
{
return AtendimentoSoapSolicitacaoExame::where('alto_custo', false)
->whereHas('soap', fn ($q) => $q
->where('atendimento_id', $atendimento->id)
->where('is_rascunho', false)
)
->get()
->map(fn ($solicitacao) => array_merge(self::getLogData($solicitacao), [
'cid_descricao' => is_null($solicitacao->cid_id)
? null : "{$solicitacao->cid->codigo} - {$solicitacao->cid->nome}",
'cid' => is_null($solicitacao->cid_id) ? null : [
'id' => $solicitacao->cid->id,
'codigo' => $solicitacao->cid->codigo,
'nome' => $solicitacao->cid->nome,
],
'ciap_descricao' => is_null($solicitacao->ciap_id)
? null : "{$solicitacao->ciap->codigo} - {$solicitacao->ciap->descricao}",
'classificacao_id' => $solicitacao->classificacao_id,
'classificacao_nome' => $solicitacao->classificacao->nome ?? null,
'justificativa' => $solicitacao->justificativa,
'observacao' => $solicitacao->observacao,
'exames' => $solicitacao->itens->map(fn ($item) => [
'descricao' => MaskUtil::getProcedimentoMasked($item->exame->codigo) . " - {$item->exame->nome}",
]),
]));
}
private static function getSolicitacaoExamesAltoCusto($atendimento)
{
return AtendimentoSoapSolicitacaoExame::where('alto_custo', true)
->whereHas('soap', fn ($q) => $q
->where('atendimento_id', $atendimento->id)
->where('is_rascunho', false)
)
->get()
->map(fn ($solicitacao) => array_merge(self::getLogData($solicitacao), [
'cid_descricao' => is_null($solicitacao->cid_id)
? null : "{$solicitacao->cid->codigo} - {$solicitacao->cid->nome}",
'cid' => is_null($solicitacao->cid_id) ? null : [
'id' => $solicitacao->cid->id,
'codigo' => $solicitacao->cid->codigo,
'nome' => $solicitacao->cid->nome,
],
'ciap_descricao' => is_null($solicitacao->ciap_id)
? null : "{$solicitacao->ciap->codigo} - {$solicitacao->ciap->descricao}",
'justificativa' => $solicitacao->justificativa,
'observacao' => $solicitacao->observacao,
'exames' => $solicitacao->itens->map(fn ($item) => [
'descricao' => MaskUtil::getProcedimentoMasked($item->exame->codigo) . " - {$item->exame->nome}",
]),
]));
}
private static function getEncaminhamentos($atendimento)
{
return AtendimentoSoapEncaminhamento::whereHas('soap', fn ($q) => $q
->where('atendimento_id', $atendimento->id)
->where('is_rascunho', false)
)
->get()
->map(fn ($orientacao) => array_merge(self::getLogData($orientacao), [
'tipo_id' => $orientacao->tipo_id,
'tipo_descricao' => $orientacao->tipo->descricao,
'servico_especializado_especialidade_nome' => $orientacao->servicoEspecializadoEspecialidade
->nome ?? null,
'servico_especializado_complemento' => $orientacao->servico_especializado_complemento ?? ' - ',
'servico_especializado_cid_descricao' => is_null($orientacao->servico_especializado_cid_id)
? ' - '
: MaskUtil::getCidMasked($orientacao->servicoEspecializadoCid->codigo)
. ' - ' . $orientacao->servicoEspecializadoCid->nome,
'cid' => is_null($orientacao->servicoEspecializadoCid) ? null : [
'id' => $orientacao->servicoEspecializadoCid->id,
'codigo' => $orientacao->servicoEspecializadoCid->codigo,
'nome' => $orientacao->servicoEspecializadoCid->nome,
],
'servico_especializado_ciap_descricao' => is_null($orientacao->servico_especializado_ciap_id)
? ' - '
: $orientacao->servicoEspecializadoCiap->codigo . ' - ' . $orientacao->servicoEspecializadoCiap->descricao,
'servico_especializado_classificacao_risco_nome' => $orientacao->servicoEspecializadoClassificacaoRisco
->nome ?? null,
'servico_especializado_motivo' => $orientacao->servico_especializado_motivo,
'servico_especializado_observacao' => $orientacao->servico_especializado_observacao,
'intersetorial_unidade_nome_fantasia' => is_null($orientacao->intersetorial_infraestrutura_id)
? null
: $orientacao->intersetorialInfraestrutura->unidade->nome_fantasia,
'intersetorial_infraestrutura_nome' => is_null($orientacao->intersetorial_infraestrutura_id)
? null
: $orientacao->intersetorialInfraestrutura->nome,
]));
}
private static function getSolicitacaoProcedimentosCirurgicos($atendimento)
{
return AtendimentoSoapSolicitacaoProcedimentoCirurgico::whereHas('soap', fn ($q) => $q
->where('atendimento_id', $atendimento->id)
->where('is_rascunho', false)
)
->get()
->map(fn ($solicitacao) => array_merge(self::getLogData($solicitacao), [
'cid_descricao' => is_null($solicitacao->cid_id)
? null : "{$solicitacao->cid->codigo} - {$solicitacao->cid->nome}",
'ciap_descricao' => is_null($solicitacao->ciap_id)
? null : "{$solicitacao->ciap->codigo} - {$solicitacao->ciap->descricao}",
'justificativa' => $solicitacao->justificativa,
'observacao' => $solicitacao->observacao,
'procedimentos_cirurgicos' => $solicitacao->itens->map(fn ($item) => [
'descricao' => MaskUtil::getProcedimentoMasked($item->procedimentoCirurgico->procedimento_codigo)
. " - {$item->procedimentoCirurgico->nome}",
]),
]));
}
private static function getLogData($model)
{
return [
'lotacao' => [
'ocupacao' => [
'id' => $model->createdLotacao->ocupacao->id ?? null,
'codigo' => $model->createdLotacao->ocupacao->codigo ?? null,
'nome' => $model->createdLotacao->ocupacao->nome ?? null,
],
'profissional' => [
'nome' => $model->createdLotacao->usuario->cidadao->nome ?? null,
],
],
'centro_custo' => [
'setor' => [
'nome' => $model->createdCentroCusto->setor->nome ?? null,
],
],
'data_hora' => $model->created_at->format('d/m/Y \à\s H:i'),
];
}
}