Files
rkm-conectasus-ci-sandbox/api/app/Services/Regulacao/SolicitacaoService.php
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

2742 lines
121 KiB
PHP

<?php
namespace App\Services\Regulacao;
use App\Enums\Cadastro\SujeitoAtencao\Sexo;
use App\Enums\Cadastro\SujeitoAtencao\TipoRegistroUsuario;
use App\Enums\ExameLaboratorial\Acao;
use App\Enums\ExameLaboratorial\StatusAgendamento as ExameLaboratorialAgendamentoStatus;
use App\Enums\ExameLaboratorial\StatusAgendamento as StatusAgendamentoLaboratorio;
use App\Enums\ExameLaboratorial\TipoCota;
use App\Enums\ExameLaboratorial\TipoUnidade;
use App\Enums\Parametrizacao\Exame\Status as StatusExame;
use App\Enums\Parametrizacao\Exame\Tipo as TipoExame;
use App\Enums\Parametrizacao\Exame\Tipo;
use App\Enums\Regulacao\ReguladorTipo;
use App\Enums\Regulacao\SolicitacaoPrioridade as SolicitacaoPrioridadeEnum;
use App\Enums\Regulacao\StatusTipo;
use App\Enums\Regulacao\TipoAgendamento;
use App\Enums\Regulacao\TipoAgendamentoModulo;
use App\Exceptions\Regulacao\CannotCancelSolicitacaoException;
use App\Exceptions\Regulacao\CannotCreateSolicitacaoException;
use App\Exceptions\Regulacao\CannotStoreSolicitacaoException;
use App\Exceptions\Regulacao\CannotUpdateSolicitacaoException;
use App\Models\Ambulatorio\Agendamento as AgendamentoAmbulatorio;
use App\Models\Cadastro\Especialidade;
use App\Models\Cadastro\Estabelecimento\Infraestrutura;
use App\Models\Cadastro\Estabelecimento\Unidade;
use App\Models\Cadastro\Parametrizacao\Parametrizacao as CadastroParametrizacao;
use App\Models\Cadastro\SujeitoAtencao\Lotacao;
use App\Models\Cadastro\SujeitoAtencao\Paciente;
use App\Models\Cadastro\SujeitoAtencao\Usuario;
use App\Models\ExameImagem\Agendamento\Agendamento as AgendamentoExameImagem;
use App\Models\ExameImagem\Agendamento\AgendamentoExame as ExameImagemAgendamentoExame;
use App\Models\ExameLaboratorial\AgendamentoExame\Agendamento as AgendamentoExame;
use App\Models\ExameLaboratorial\AgendamentoExame\AgendamentoExame as AgendamentoExameExame;
use App\Models\ExameLaboratorial\AgendamentoExame\AgendamentoExame as ExameLaboratorialAgendamentoExame;
use App\Models\ExameLaboratorial\Parametrizacao\Cota;
use App\Models\ExameLaboratorial\Parametrizacao\CotaExamePeriodo;
use App\Models\ExameLaboratorial\Parametrizacao\CotaTransferencia;
use App\Models\Geral\Ciap;
use App\Models\Parametrizacao\Exame\Exame;
use App\Models\Parametrizacao\ProcedimentoCirurgico;
use App\Models\Regulacao\Parametrizacao;
use App\Models\Regulacao\ParametrizacaoRegulador;
use App\Models\Regulacao\ParametrizacaoSolicitante;
use App\Models\Regulacao\ParametrizacaoSupervisor;
use App\Models\Regulacao\Solicitacao;
use App\Models\Regulacao\SolicitacaoHistorico;
use App\Models\Regulacao\SolicitacaoItem;
use App\Models\Regulacao\SolicitacaoMovimentacao;
use App\Models\Regulacao\SolicitacaoPrioridade;
use App\Models\Regulacao\Status;
use App\Models\Sigtap\Cid;
use App\Models\Sigtap\Ocupacao;
use App\Rules\Cns;
use App\Rules\Cpf;
use App\Services\Ambulatorio\AgendamentoService as AmbulatorioAgendamentoService;
use App\Services\Ambulatorio\AtendimentoHistoricoService as historicoAmbulatorioSoap;
use App\Services\Ambulatorio\HistoricoAtendimentoService as historicoAtendimento;
use App\Services\ExameImagem\ImpressaoService as ImpressaoExameImagemService;
use App\Services\ExameLaboratorial\AgendamentoExameHistoricoService;
use App\Services\ExameLaboratorial\ImpressaoService as ImpressaoExameLaboratorialService;
use App\Services\Service;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use DateTimeImmutable;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class SolicitacaoService extends Service
{
public static function datatable()
{
$parametrizacao = CadastroParametrizacao::first();
$quantidadeDias = $parametrizacao->cadastro_paciente_desatualizado_quantidade_dias ?? 0;
$isPpi = ParametrizacaoSolicitante::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)->value('is_ppi') ?? false;
return DB::table('cadastro_paciente as paciente')
->join(
'cadastro_paciente_classificacao as classificacao',
'classificacao.id',
'paciente.classificacao_id'
)
->leftJoin(
'cadastro_cidadao as cidadao',
'cidadao.id',
'paciente.cidadao_id'
)
->leftJoin(
'cadastro_domicilio as domicilio',
'domicilio.id',
'cidadao.domicilio_id'
)
->leftJoin(
'cadastro_endereco as endereco',
'endereco.id',
'domicilio.endereco_id'
)
->leftJoin(
'cadastro_logradouro as logradouro',
'logradouro.id',
'endereco.logradouro_id'
)
->leftJoin(
'intranet.cadastro_municipio as municipio',
'municipio.id',
'logradouro.municipio_id'
)
->leftJoin(
'intranet.cadastro_estado as estado',
'estado.id',
'municipio.estado_id'
)
->leftJoin('cadastro_obito as obito', function ($join) {
$join->on('obito.cidadao_id', '=', 'cidadao.id')
->whereNull('obito.deleted_at');
})
->whereNull('paciente.deleted_at')
->whereNull('paciente.sequencial_desconhecido_em')
->whereNull('obito.id')
->when($isPpi, function ($query) {
return $query->where('paciente.unidade_id', self::getCurrentCentroCusto()->unidade_id);
})
->select(DB::raw("
paciente.id,
paciente.classificacao_id,
cidadao.nome,
cidadao.nome_social,
cidadao.preferencia_nome_id,
DATE_FORMAT(cidadao.data_nascimento, '%d/%m/%Y') as data_nascimento,
cidadao.nome_mae,
LPAD(paciente.prontuario, 7, '0') as prontuario,
CONCAT(
SUBSTR(cidadao.cpf, 1, 3),
'.',
SUBSTR(cidadao.cpf, 4, 3),
'.',
SUBSTR(cidadao.cpf, 7, 3),
'-',
SUBSTR(cidadao.cpf, 10, 2)
) as cpf,
CONCAT(
SUBSTR(cidadao.cns, 1, 3),
' ',
SUBSTR(cidadao.cns, 4, 4),
' ',
SUBSTR(cidadao.cns, 8, 4),
' ',
SUBSTR(cidadao.cns, 12, 4)
) as cns,
classificacao.descricao as classificacao_descricao,
IF(paciente.validade_fim IS NULL,
'INDETERMINADO',
DATE_FORMAT(paciente.validade_fim, '%d/%m/%Y')
) as validade_fim,
(
CASE
WHEN paciente.updated_at IS NULL THEN 1
WHEN " . ($quantidadeDias > 0
? "DATE_ADD(paciente.updated_at, INTERVAL {$quantidadeDias} DAY) < NOW()"
: 'false') . "
THEN DATEDIFF(NOW(), DATE_ADD(paciente.updated_at, INTERVAL {$quantidadeDias} DAY))
ELSE 0
END
) as dias_cadastro_desatualizado
"));
}
public static function autocompleteExame()
{
$isPpi = ParametrizacaoSolicitante::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)->value('is_ppi') ?? false;
$parametrizacao = Parametrizacao::first();
$exames = DB::table('parametrizacao_exame as exame')
->whereNull('exame.deleted_at')
->where('exame.ativo', true)
->when($isPpi, function ($query) {
return $query->where('exame.is_ppi', true);
})
->leftjoin(
DB::raw('
(
SELECT *
FROM sigtap.procedimento
WHERE competencia_id = (SELECT MAX(competencia_id) FROM sigtap.procedimento)
) as procedimento'
),
'procedimento.codigo',
'exame.codigo'
)
->where(function($query) {
$query->whereNull('procedimento.codigo')
->orWhere(function($subQuery) {
$subQuery->whereNotNull('procedimento.codigo')
->whereIn('procedimento.sexo', [request()->sexo_paciente, 'I', 'N']);
});
})
->whereExists(function ($query) use ($parametrizacao) {
$query->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador_exame as parametrizacao_exame')
->join(
'regulacao_parametrizacao_solicitante_regulador as solicitante_regulador',
'solicitante_regulador.id',
'parametrizacao_exame.solicitante_regulador_id'
)
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->whereColumn('parametrizacao_exame.exame_id', 'exame.id')
->where('solicitante.infraestrutura_id', request()->infraestrutura_solicitante_id)
->where('solicitante_regulador.regulador_id', request()->regulador_id);
if (!$parametrizacao->exames_nao_regulados) {
$query->where('exame.regulacao_tipo_id', '!=', null);
}
})
->leftJoin(
'regulacao_parametrizacao_regulador_exame as regulador_exame',
function($join) {
$join->on('regulador_exame.exame_id', 'exame.id')
->where('regulador_exame.regulador_id', request()->regulador_id);
}
)
->when(request()->grupo_id, fn ($q, $id) => $q->where('exame.grupo_tipo_id', $id))
->when(is_array(request()->not_id), fn ($q) => $q->whereNotIn('exame.id', request()->not_id))
->when(request()->regulacao_tipo_id, fn ($q, $id) => $q->where('exame.regulacao_tipo_id', $id))
->distinct()
->selectRaw("
exame.id,
exame.tipo_id,
exame.codigo,
exame.nome,
exame.regulacao_tipo_id,
regulador_exame.exige_documento_anexo
");
if ($parametrizacao->exames_nao_regulados) {
$cotaUnidadeQuant = self::getCotaUnidadeQuantidade();
$cotaUnidadeValor = self::getCotaUnidadeValor();
$cotaExameQuant = self::getCotaExamePeriodoQuantidade($exames);
$cotaExameValor = self::getCotaExamePeriodoValor($exames);
if (count($cotaExameQuant) > 0) {
$exames = $exames->whereIn('exame.id', $cotaExameQuant);
}
if (count($cotaExameValor) > 0) {
$exames = $exames->whereIn('exame.id', $cotaExameValor);
}
if (!count($cotaExameQuant) > 0 || !count($cotaExameValor) > 0 && (!$cotaUnidadeQuant || !$cotaUnidadeValor)) {
$exames = $exames->where('exame.regulacao_tipo_id', '!=', null);
}
}
return $exames;
}
public static function autocompleteProcedimentoCirurgico()
{
return DB::table('parametrizacao_procedimento_cirurgico as procedimento_cirurgico')
->where('procedimento_cirurgico.status', true)
->join(
DB::raw('
(
SELECT *
FROM sigtap.procedimento
WHERE competencia_id = (SELECT MAX(competencia_id) FROM sigtap.procedimento)
) as procedimento'
),
'procedimento.codigo',
'procedimento_cirurgico.procedimento_codigo'
)
->whereIn('procedimento.sexo', [request()->sexo_paciente, 'I', 'N'])
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador_proced_cirurgico as parametrizacao_procedimento_cirurgico')
->join(
'regulacao_parametrizacao_solicitante_regulador as solicitante_regulador',
'solicitante_regulador.id',
'parametrizacao_procedimento_cirurgico.solicitante_regulador_id'
)
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->whereColumn('parametrizacao_procedimento_cirurgico.procedimento_cirurgico_id', 'procedimento_cirurgico.id')
->where('solicitante.infraestrutura_id', request()->infraestrutura_solicitante_id)
->where('solicitante_regulador.regulador_id', request()->regulador_id)
)
->leftJoin(
'regulacao_parametrizacao_regulador_procedimento_cirurgico as regulador_procedimento_cirurgico',
function($join) {
$join->on('regulador_procedimento_cirurgico.procedimento_cirurgico_id', '=', 'procedimento_cirurgico.id')
->where('regulador_procedimento_cirurgico.regulador_id', '=', request()->regulador_id);
}
)
->when(request()->grupo_id, fn ($q, $id) => $q->where('procedimento_cirurgico.grupo_exame_id', $id))
->when(is_array(request()->not_id), fn ($q) => $q->whereNotIn('procedimento_cirurgico.id', request()->not_id))
->distinct()
->selectRaw("
procedimento_cirurgico.id,
procedimento_cirurgico.procedimento_codigo as codigo,
procedimento_cirurgico.nome,
regulador_procedimento_cirurgico.exige_documento_anexo
");
}
public static function autocompleteEspecialidade()
{
$sexoPaciente = request()->sexo_paciente === 'M' ? sexo::MASCULINO : sexo::FEMININO;
return DB::table('cadastro_especialidade as especialidade')
->join('sigtap.ocupacao as ocupacao', 'ocupacao.id', 'especialidade.ocupacao_id')
->where('especialidade.ativo', true)
->where(function ($query) use ($sexoPaciente) {
$query->where('especialidade.sexo_id', $sexoPaciente)
->orWhereNull('especialidade.sexo_id');
})
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador_especialidade as parametrizacao_especialidade')
->join(
'regulacao_parametrizacao_solicitante_regulador as solicitante_regulador',
'solicitante_regulador.id',
'parametrizacao_especialidade.solicitante_regulador_id'
)
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->join(
'regulacao_parametrizacao_regulador as regulador',
'regulador.id',
'solicitante_regulador.regulador_id'
)
->whereColumn('parametrizacao_especialidade.especialidade_id', 'especialidade.id')
->where('solicitante.infraestrutura_id', request()->infraestrutura_solicitante_id)
->where('solicitante_regulador.regulador_id', request()->regulador_id)
)
->leftJoin(
'regulacao_parametrizacao_regulador_especialidade as regulador_especialidade',
function($join) {
$join->on('regulador_especialidade.especialidade_id', 'especialidade.id')
->where('regulador_especialidade.regulador_id', request()->regulador_id);
}
)
->when(is_array(request()->not_id), fn ($q) => $q->whereNotIn('especialidade.id', request()->not_id))
->selectRaw("
especialidade.id,
ocupacao.codigo,
especialidade.nome,
regulador_especialidade.exige_documento_anexo
");
}
public static function index($pacienteId)
{
$parametrizacao = Parametrizacao::first();
$atendeOutroMunicipio = ParametrizacaoSolicitante::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)->value('atende_outro_municipio') ?? false;
$solicitacoes = DB::table('regulacao_solicitacao as solicitacao')
->join('regulacao_status as status', 'status.id', 'solicitacao.status_id')
->join('regulacao_status_tipo as status_tipo', 'status_tipo.id', 'status.tipo_id')
->join(DB::raw('(
SELECT h1.*
FROM regulacao_solicitacao_historico h1
INNER JOIN (
SELECT solicitacao_id, MAX(data) as max_data
FROM regulacao_solicitacao_historico
GROUP BY solicitacao_id
) h2 ON h1.solicitacao_id = h2.solicitacao_id AND h1.data = h2.max_data
) as historico'), 'historico.solicitacao_id', 'solicitacao.id')
->join('cadastro_usuario as usuario', 'usuario.id', 'solicitacao.usuario_solicitante_id')
->join('cadastro_cidadao as cidadao', 'cidadao.id', 'usuario.cidadao_id')
->join('regulacao_parametrizacao_regulador as regulador', 'regulador.id', 'solicitacao.regulador_id')
->join('cadastro_infraestrutura as infraestrutura', 'infraestrutura.id', 'regulador.infraestrutura_id')
->join('cadastro_unidade as unidade', 'unidade.id', 'infraestrutura.unidade_id')
->join('regulacao_solicitacao_prioridade as prioridade', 'prioridade.id', 'solicitacao.prioridade_id')
->join('cadastro_paciente as paciente', 'paciente.id', 'solicitacao.paciente_id')
->join('cadastro_cidadao as paciente_cidadao', 'paciente_cidadao.id', 'paciente.cidadao_id')
->join('cadastro_infraestrutura as infraestrutura_solicitante', 'infraestrutura_solicitante.id', 'solicitacao.infraestrutura_solicitante_id')
->join('cadastro_unidade as unidade_solicitante', 'unidade_solicitante.id', 'infraestrutura_solicitante.unidade_id')
->leftJoin('ambulatorio_atendimento_soap as soap', 'soap.id', 'solicitacao.soap_id')
->leftJoin(
'regulacao_parametrizacao_prestador_externo as prestador_externo',
'prestador_externo.id',
'solicitacao.prestador_externo_id'
)
->leftJoin(
'transporte_paciente_destino as prestador_externo_destino',
'prestador_externo_destino.id',
'prestador_externo.destino_id'
)
->where('solicitacao.paciente_id', $pacienteId)
->selectRaw("
solicitacao.id,
solicitacao.data,
solicitacao.status_id,
status.nome as status_nome,
cidadao.nome as usuario_solicitante_nome,
unidade.nome_fantasia as unidade_reguladora_nome_fantasia,
unidade.nome_fantasia as prestador_descricao,
COALESCE(infraestrutura.nome, unidade.nome_fantasia) as infraestrutura_reguladora_nome,
prioridade.nome as prioridade_nome,
solicitacao.prioridade_id,
paciente.classificacao_id,
paciente.id as paciente_id,
CONCAT(
paciente_cidadao.nome,
IF(paciente_cidadao.nome_social IS NULL,
'',
CONCAT(' (', paciente_cidadao.nome_social, ')')
)
) as paciente_nome,
paciente_cidadao.data_nascimento as paciente_data_nascimento,
paciente.protocolo_cross as paciente_protocolo_cross,
CONCAT(TIMESTAMPDIFF(YEAR, paciente_cidadao.data_nascimento, CURDATE()), ' anos') as paciente_idade,
LPAD(paciente.prontuario, 7, '0') as prontuario,
IF(solicitacao.confirmado_em IS NULL, 0, 1) as confirmado,
IF(" . ($atendeOutroMunicipio ? 1 : 0) . " = 1, 1, 0) unidade_atende_outro_municipio,
COALESCE(infraestrutura_solicitante.nome, unidade_solicitante.nome_fantasia) as infraestrutura_solicitante_nome,
COALESCE(infraestrutura_solicitante.nome, unidade_solicitante.nome_fantasia) as unidade_solicitante_nome_fantasia,
(
SELECT is_ppi
FROM regulacao_parametrizacao_solicitante
WHERE infraestrutura_id = " . self::getCurrentCentroCusto()->infraestrutura_id . "
) is_ppi,
IF(
" . ($parametrizacao->solicitacao_automatica_ambulatorio ? 1 : 0) . " = 0,
1,
0
) allow_confirma,
(
status.tipo_id <> " . StatusTipo::CANCELADO . "
AND EXISTS (
SELECT 1
FROM regulacao_status_status as status_status
JOIN regulacao_status as status_para
ON status_para.id = status_status.status_para_id
WHERE status_status.status_de_id = status.id
AND status_para.ativo = 1
AND status_para.tipo_id = " . StatusTipo::CANCELADO . "
)
AND (
solicitacao.infraestrutura_solicitante_id = " . self::getCurrentCentroCusto()->infraestrutura_id . "
)
) as allow_cancel,
(
status.tipo_id <> " . StatusTipo::CANCELADO . "
AND (
solicitacao.confirmado_em IS NULL
OR (
status.tipo_id = " . StatusTipo::DEVOLVIDO . "
AND EXISTS (
SELECT 1
FROM regulacao_status_status as status_status
JOIN regulacao_status as status_para
ON status_para.id = status_status.status_para_id
WHERE status_status.status_de_id = status.id
AND status_para.ativo = 1
AND status_para.tipo_id = " . StatusTipo::REENVIADA . "
)
)
OR (
solicitacao.infraestrutura_solicitante_id = " . self::getCurrentCentroCusto()->infraestrutura_id . "
AND (
SELECT COUNT(*)
FROM regulacao_solicitacao_historico as historico
WHERE historico.solicitacao_id = solicitacao.id
) = 1
)
)
) as allow_update,
solicitacao.soap_id,
(status_tipo.id IN (" . StatusTipo::AGENDADO . ", " . StatusTipo::REAGENDADO . ")) as is_agendado,
(solicitacao.prioridade_id = " . SolicitacaoPrioridadeEnum::URGENCIA . ") as urgente,
solicitacao.prestador_externo_id,
soap.atendimento_id as ambulatorio_atendimento_id,
CONCAT(
DATE_FORMAT(solicitacao.data_agendada, '%d/%m/%Y'),
' às ',
DATE_FORMAT(solicitacao.hora_agendada, '%H:%i')
) as data_completa_agendamento,
prestador_externo_destino.descricao_destino
")
->distinct()
->get();
$solicitacoes->each(function ($solicitacao) {
$solicitacao->confirmado = (bool) $solicitacao->confirmado;
$solicitacao->allow_cancel = (bool) $solicitacao->allow_cancel;
$solicitacao->allow_update = (bool) $solicitacao->allow_update;
$solicitacao->allow_confirma = (bool) $solicitacao->allow_confirma;
$solicitacao->unidade_atende_outro_municipio = (bool) $solicitacao->unidade_atende_outro_municipio;
$solicitacao->is_ppi = (bool) $solicitacao->is_ppi;
$solicitacao->is_regulador = DB::table('regulacao_parametrizacao_regulador')
->where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->exists();
$solicitacao->itens = DB::table('regulacao_solicitacao_item as item')
->leftJoin('parametrizacao_exame as exame', 'exame.id', 'item.exame_id')
->leftJoin(
'parametrizacao_procedimento_cirurgico as procedimento_cirurgico',
'procedimento_cirurgico.id',
'item.procedimento_cirurgico_id'
)
->leftJoin('cadastro_especialidade as especialidade', 'especialidade.id', 'item.especialidade_id')
->leftJoin('sigtap.ocupacao as ocupacao', 'ocupacao.id', 'especialidade.ocupacao_id')
->where('item.solicitacao_id', $solicitacao->id)
->selectRaw("
item.exame_id,
exame.codigo as exame_codigo,
exame.nome as exame_nome,
procedimento_cirurgico.id as procedimento_cirurgico_id,
procedimento_cirurgico.procedimento_codigo as procedimento_cirurgico_codigo,
procedimento_cirurgico.nome as procedimento_cirurgico_nome,
especialidade.id as especialidade_id,
ocupacao.codigo as especialidade_codigo,
especialidade.nome as especialidade_nome
")
->get()
->map(function ($item) {
$descricao = null;
if (!is_null($item->exame_id)) {
$descricao = (empty($item->exame_codigo)
? ''
: MaskUtil::getProcedimentoMasked($item->exame_codigo) . ' - '
) . $item->exame_nome;
}
else if (!is_null($item->procedimento_cirurgico_id)) {
$descricao = MaskUtil::getProcedimentoMasked($item->procedimento_cirurgico_codigo)
. " - {$item->procedimento_cirurgico_nome}";
}
else if (!is_null($item->especialidade_id)) {
$descricao = "{$item->especialidade_codigo} - {$item->especialidade_nome}";
}
return $descricao;
})
->sort()
->values();
if ($solicitacao->is_agendado) {
$item = SolicitacaoItem::where('solicitacao_id', $solicitacao->id)->first();
if ($item->exame_id) {
if ($item->exame->tipo_id === TipoExame::LABORATORIAL && !$solicitacao->prestador_externo_id) {
$agendamentoId = AgendamentoExame::where('regulacao_solicitacao_id', $solicitacao->id)->value('id');
$agendamentoNumero = AgendamentoExame::where('regulacao_solicitacao_id', $solicitacao->id)->value('agendamento_numero');
$solicitacao->agendamento = [
'agendamento_id' => $agendamentoId,
'tipo_agendamento_interno_externo' => $solicitacao->tipo_agendamento_impressao_interno_externo = TipoAgendamento::INTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::LABORATORIO,
];
$request = new Request([
'agendamento_numero' => $agendamentoNumero
]);
$impressaoExameService = new ImpressaoExameLaboratorialService();
$solicitacao->agendamento_data = $impressaoExameService->list($request);
} else if ($item->exame->tipo_id === TipoExame::LABORATORIAL && $solicitacao->prestador_externo_id) {
$solicitacao->agendamento = [
'agendamento_id' => null,
'tipos_agendamento_interno_externo' => TipoAgendamento::EXTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::LABORATORIO,
];
} else if ($item->exame->tipo_id === TipoExame::IMAGEM && !$solicitacao->prestador_externo_id) {
$solicitacao->agendamento = [
'agendamento_id' => AgendamentoExameImagem::where('regulacao_solicitacao_id', $solicitacao->id)->value('id'),
'tipo_agendamento_interno_externo' => $solicitacao->tipo_agendamento_impressao_interno_externo = TipoAgendamento::INTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::IMAGEM,
];
$request = new Request([
'id' => $solicitacao->agendamento['agendamento_id']
]);
$ImpressaoExameImagemService = new ImpressaoExameImagemService();
$solicitacao->agendamento_data = $request->id ? $ImpressaoExameImagemService->datatable($request) : [];
} else if ($item->exame->tipo_id === TipoExame::IMAGEM && $solicitacao->prestador_externo_id) {
$solicitacao->agendamento = [
'agendamento_id' => null,
'tipos_agendamento_interno_externo' => TipoAgendamento::EXTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::IMAGEM,
];
// não existe impressão para agendamento externo
}
} else if ($item->procedimento_cirurgico_id) {
$solicitacao->agendamento = [
'agendamento_id' => AgendamentoExame::where('regulacao_solicitacao_id', $solicitacao->id)->value('id'),
'tipo_agendamento_interno_externo' => $solicitacao->tipo_agendamento_impressao_interno_externo = TipoAgendamento::EXTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::PROCEDIMENTO_CIRURGICO,
];
} else if ($item->especialidade_id) {
if (!$solicitacao->prestador_externo_id) {
$solicitacao->agendamento = [
'agendamento_id' => AgendamentoAmbulatorio::where('regulacao_solicitacao_id', $solicitacao->id)->value('id'),
'tipo_agendamento_interno_externo' => $solicitacao->tipo_agendamento_impressao_interno_externo = TipoAgendamento::INTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::CONSULTA,
];
} else if ($solicitacao->prestador_externo_id) {
$solicitacao->agendamento = [
'agendamento_id' => null,
'tipos_agendamento_interno_externo' => TipoAgendamento::EXTERNO,
'tipo_agendamento_modulo' => $solicitacao->tipo_agendamento_modulo = TipoAgendamentoModulo::CONSULTA,
];
}
}
}
});
if ($solicitacoes->isEmpty()) {
$infraestruturaIdLogada = self::getCurrentCentroCusto()->infraestrutura_id;
$paciente = Paciente::findOrFail($pacienteId);
$pacienteClassificacao = $paciente->classificacao_id;
$unidadeSolicitante = ParametrizacaoSolicitante::where('infraestrutura_id', $infraestruturaIdLogada)->first();
$unidadeSolicitanteAtendeOutroMunicipio = $unidadeSolicitante->atende_outro_municipio ?? false;
$solicitacoes = [
'classificacao_id' => $pacienteClassificacao,
'unidade_atende_outro_municipio' => $unidadeSolicitanteAtendeOutroMunicipio,
'is_ppi' => $unidadeSolicitante->is_ppi ?? false,
'agendamento' => null,
];
}
return $solicitacoes;
}
public static function list()
{
$params = request()->except('listar');
switch (request()->listar) {
case 'infraestruturas-solicitantes': {
return self::getInfraestruturasSolicitantes($params);
}
case 'unidades-reguladoras': {
return self::getUnidadesReguladoras($params);
}
case 'reguladores': {
return self::getReguladores($params);
}
case 'grupos-exames': {
return self::getGruposExames();
}
case 'grupos-procedimentos-cirurgicos': {
return self::getGruposProcedimentosCirurgicos();
}
}
}
public static function create($pacienteId)
{
$paciente = Paciente::findOrFail($pacienteId);
$lotacaoLogada = self::getCurrentLotacao();
$unidadesSolicitantes = self::getUnidadesSolicitantes();
$infraestruturasSolicitantes = self::getInfraestruturasSolicitantes([
'unidade_solicitante_id' => $lotacaoLogada->infraestrutura->unidade_id
]);
$unidadesReguladoras = self::getUnidadesReguladoras([
'infraestrutura_solicitante_id' => $lotacaoLogada->infraestrutura_id,
]);
$unidadeReguladora = $unidadesReguladoras->first();
$reguladores = is_null($unidadeReguladora)
? collect()
: self::getReguladores([
'unidade_reguladora_id' => $unidadeReguladora->id,
'infraestrutura_solicitante_id' => $lotacaoLogada->infraestrutura_id
]);
$regulador = $reguladores->first();
$solicitacoesItens = collect();
$solicitacoes = DB::table('regulacao_solicitacao as solicitacao')
->where('solicitacao.paciente_id', $pacienteId)
->where('solicitacao.infraestrutura_solicitante_id', self::getCurrentCentroCusto()->infraestrutura_id)
->get('solicitacao.id');
$solicitacoes->each(function ($solicitacao) use (&$solicitacoesItens) {
$itens = DB::table('regulacao_solicitacao_item as item')
->join('parametrizacao_exame as exame', 'exame.id', '=', 'item.exame_id')
->join('regulacao_solicitacao as solicitacao', 'solicitacao.id', '=', 'item.solicitacao_id')
->join('regulacao_status as status', 'status.id', 'solicitacao.status_id')
->join('regulacao_status_tipo as status_tipo', 'status_tipo.id', 'status.tipo_id')
->where('item.solicitacao_id', $solicitacao->id)
->whereNotNull('item.exame_id')
->selectRaw("
item.exame_id,
exame.codigo as exame_codigo,
exame.nome as exame_nome,
exame.validade as validade,
solicitacao.status_id,
status.nome as status_nome,
status_tipo.id as status_tipo,
DATE_FORMAT(solicitacao.data, '%d/%m/%Y') as solicitacao_data,
CASE
WHEN DATE_ADD(solicitacao.data, INTERVAL exame.validade DAY) >= CURDATE() THEN true
ELSE false
END as dentro_da_validade,
DATE_FORMAT(DATE_ADD(solicitacao.data, INTERVAL exame.validade DAY), '%d/%m/%Y') as data_validade
")
->get()
->sortBy('exame_codigo')
->values();
$solicitacoesItens = $solicitacoesItens->merge($itens);
});
return [
'additionals' => self::getAdditionalsData($paciente),
'form' => [
'paciente' => self::getPacienteData($paciente),
'unidades_solicitantes' => $unidadesSolicitantes,
'infraestruturas_solicitantes' => $infraestruturasSolicitantes,
'unidades_reguladoras' => $unidadesReguladoras,
'reguladores' => $reguladores,
'prioridades' => self::getPrioridades(),
'info_profissional' => [
'unidades' => [],
'infraestruturas' => [],
'lotacoes' => [],
'ocupacoes' => [],
'especialidades' => [],
],
],
'model' => [
'numero' => self::getNovoNumeroSolicitacao(),
'data' => Carbon::today()->format('d/m/Y'),
'unidade_solicitante_id' => $lotacaoLogada->infraestrutura->unidade_id,
'infraestrutura_solicitante_id' => $lotacaoLogada->infraestrutura_id,
'usuario_solicitante' => null,
'unidade_reguladora_id' => $unidadeReguladora->id ?? null,
'regulador_id' => $regulador->id ?? null,
'cid' => null,
'ciap' => null,
'hipotese_diagnostica_justificativa' => null,
'prioridade_id' => SolicitacaoPrioridadeEnum::ELETIVO,
'observacao' => null,
'data_desejada' => null,
'peso' => null,
'altura' => null,
'cancelado' => false,
'itens' => [],
'solicitacoes_itens' => $solicitacoesItens,
'info_profissional' => [
'unidade_usuario_id' => null,
'infraestrutura_usuario_id' => null,
'ocupacao_usuario_id' => null,
'lotacao_usuario_id' => null,
'usuario_solicitante_especialidade_id' => null,
],
'soap_id' => $solicitacao->soap_id ?? null,
'arquivos' => [],
],
];
}
public static function edit($id)
{
$solicitacao = Solicitacao::findOrFail($id);
$unidadesSolicitantes = self::getUnidadesSolicitantes();
$infraestruturasSolicitantes = self::getInfraestruturasSolicitantes([
'unidade_solicitante_id' => $solicitacao->infraestruturaSolicitante->unidade_id
]);
$unidadesReguladoras = self::getUnidadesReguladoras([
'infraestrutura_solicitante_id' => $solicitacao->infraestrutura_solicitante_id,
], $solicitacao->regulador->infraestrutura->unidade_id);
$reguladores = self::getReguladores([
'unidade_reguladora_id' => $solicitacao->regulador->infraestrutura->unidade_id,
'infraestrutura_solicitante_id' => $solicitacao->infraestrutura_solicitante_id,
], $solicitacao->regulador_id);
$unidadesProfissionalSolicitante = self::getUnidadeProfissional($solicitacao->usuarioSolicitante->id);
$infraestruturasProfissionalSolicitante = self::getInfraestruturaProfissional($solicitacao->usuarioSolicitante->id, $solicitacao->unidade_usuario_id);
$ocupacoesProfissionalSolicitante = self::getOcupacaoProfissional($solicitacao->usuarioSolicitante->id, $solicitacao->infraestrutura_usuario_id);
$especialidadesProfissionalSolicitante = self::getEspecialidadeProfissional($solicitacao->ocupacao_usuario_id);
$data = [
'additionals' => array_merge(self::getAdditionalsData($solicitacao->paciente), [
'allow_update' => $solicitacao->status->tipo_id !== StatusTipo::CANCELADO
&& (
!$solicitacao->confirmado || (
$solicitacao->status->tipo_id === StatusTipo::DEVOLVIDO
&& $solicitacao->status->statusPara()
->where('ativo', true)
->where('tipo_id', StatusTipo::REENVIADA)
->exists()
)
),
]),
'form' => [
'paciente' => self::getPacienteData($solicitacao->paciente),
'unidades_solicitantes' => $unidadesSolicitantes,
'infraestruturas_solicitantes' => $infraestruturasSolicitantes,
'unidades_reguladoras' => $unidadesReguladoras,
'reguladores' => $reguladores,
'prioridades' => self::getPrioridades(),
'info_profissional' => [
'unidades' => $unidadesProfissionalSolicitante['form']['info_profissional']['unidades'],
'infraestruturas' => $infraestruturasProfissionalSolicitante['form']['info_profissional']['infraestruturas'],
'ocupacoes' => $ocupacoesProfissionalSolicitante['form']['info_profissional']['ocupacoes'],
'especialidades' => $especialidadesProfissionalSolicitante['form']['info_profissional']['especialidades'],
],
],
'model' => [
'id' => $solicitacao->id,
'paciente_id' => $solicitacao->paciente_id,
'numero' => $solicitacao->numero,
'data' => $solicitacao->data->format('d/m/Y'),
'unidade_solicitante_id' => $solicitacao->infraestruturaSolicitante->unidade_id,
'infraestrutura_solicitante_id' => $solicitacao->infraestrutura_solicitante_id,
'usuario_solicitante' => [
'id' => $solicitacao->usuarioSolicitante->id,
'cidadao_nome' => $solicitacao->usuarioSolicitante->cidadao->nome,
],
'unidade_reguladora_id' => $solicitacao->regulador->infraestrutura->unidade_id,
'regulador_id' => $solicitacao->regulador_id,
'cid' => $solicitacao->cid ? [
'id' => $solicitacao->cid->id,
'codigo' => $solicitacao->cid->codigo,
'nome' => $solicitacao->cid->nome,
] : null,
'ciap' => $solicitacao->ciap ? [
'id' => $solicitacao->ciap->id,
'codigo' => $solicitacao->ciap->codigo,
'descricao' => $solicitacao->ciap->descricao,
] : null,
'hipotese_diagnostica_justificativa' => $solicitacao->hipotese_diagnostica_justificativa,
'prioridade_id' => $solicitacao->prioridade_id,
'observacao' => $solicitacao->observacao,
'data_desejada' => $solicitacao->data_desejada ? $solicitacao->data_desejada->format('d/m/Y') : null,
'peso' => $solicitacao->peso,
'altura' => $solicitacao->altura,
'confirmado' => $solicitacao->confirmado,
'cancelado' => $solicitacao->status->tipo_id === StatusTipo::CANCELADO,
'cancelado_em' => $solicitacao->cancelado_em ? $solicitacao->cancelado_em->format('d/m/Y H:i') : null,
'cancelado_usuario_nome' => $solicitacao->canceladoLotacao->usuario->cidadao->nome ?? null,
'justificativa_cancelamento' => $solicitacao->justificativa_cancelamento,
'info_profissional' => [
'unidade_usuario_id' => $solicitacao->unidade_usuario_id,
'infraestrutura_usuario_id' => $solicitacao->infraestrutura_usuario_id,
'ocupacao_usuario_id' => $solicitacao->ocupacao_usuario_id,
'lotacao_id' => $solicitacao->lotaca_usuario_id,
'usuario_solicitante_especialidade_id' => $solicitacao->usuario_solicitante_especialidade_id,
],
'itens' => $solicitacao->itens->map(function ($item) {
$codigo = null;
$nome = null;
$exameTipoId = null;
if (!is_null($item->exame_id)) {
$codigo = MaskUtil::getProcedimentoMasked($item->exame->codigo);
$nome = $item->exame->nome;
$exameTipoId = $item->exame->tipo_id;
$regulacaoTipoId = $item->exame->regulacao_tipo_id;
}
else if (!is_null($item->procedimento_cirurgico_id)) {
$codigo = MaskUtil::getProcedimentoMasked($item->procedimentoCirurgico->procedimento_codigo);
$nome = $item->procedimentoCirurgico->nome;
}
else if (!is_null($item->especialidade_id)) {
$codigo = $item->especialidade->ocupacao->codigo;
$nome = $item->especialidade->nome;
}
return [
'id' => $item->id,
'origem' => $item->origem,
'exame_id' => $item->exame_id,
'tipo_id' => $exameTipoId,
'procedimento_cirurgico_id' => $item->procedimento_cirurgico_id,
'especialidade_id' => $item->especialidade_id,
'regulacao_tipo_id' => $regulacaoTipoId ?? null,
'codigo' => $codigo,
'nome' => $nome,
];
}),
'soap_id' => $solicitacao->soap_id ?? null,
],
];
if ($data['model']['soap_id']) {
$soapId = $data['model']['soap_id'];
$atendimentoId = DB::table('ambulatorio_atendimento_soap')
->where('id', $soapId)
->value('atendimento_id');
$data['model']['dados_atendimento']['data'] = historicoAtendimento::show($data['model']['paciente_id']);
$historicos = $data['model']['dados_atendimento']['data']['form']['historico'] ?? [];
$data['model']['dados_atendimento']['data']['form']['historico'] = null;
foreach ($historicos as $historico) {
$historicoAtendimentoId = null;
if (is_array($historico) && isset($historico['atendimento_id'])) {
$historicoAtendimentoId = $historico['atendimento_id'];
} elseif (is_object($historico) && isset($historico->atendimento_id)) {
$historicoAtendimentoId = $historico->atendimento_id;
}
if ($historicoAtendimentoId == $atendimentoId) {
$data['model']['dados_atendimento']['data']['form']['historico'][] = $historico;
}
}
$data['model']['dados_atendimento']['soap'] = historicoAmbulatorioSoap::getAtendimentoSoap($soapId);
}
return $data;
}
private static function getAdditionalsData($paciente)
{
$parametrizacao = Parametrizacao::first();
$cnsPacienteValid = Cns::isValid($paciente->cidadao->cns);
return [
'data_atual' => Carbon::today()->format('d/m/Y'),
'exibir_numero' => $parametrizacao->numero_solicitacao_automatico ?? false,
'cns_paciente_valido' => $cnsPacienteValid,
'cns_paciente_provisorio' => $cnsPacienteValid && Str::startsWith($paciente->cidadao->cns, [5, 7, 8, 9]) ?? false,
'cpf_paciente_valido' => Cpf::isValid($paciente->cidadao->cpf) ?? false,
'solicitacao_retroativa' => $parametrizacao->solicitacao_retroativa,
'is_regulador' => ParametrizacaoRegulador::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)->exists() ?? false,
'is_data_desejada_required' => $parametrizacao->obriga_data_desejada ?? false,
'usuario_registro_estado_id' => $parametrizacao->usuario_registro_estado_id ?? false,
'obriga_preenchimento_cross' => $parametrizacao->obriga_protocolo_cross ?? false,
'exibe_protocolo_cross' => $parametrizacao->exibe_protocolo_cross ?? false,
'sempre_alterar_unidade_solicitante' => $parametrizacao->sempre_alterar_unidade_solicitante ?? false,
'nome_usuario_logado' => self::getCurrentLotacao()->usuario->cidadao->nome,
];
}
private static function getPacienteData($paciente)
{
return [
'nome' => $paciente->cidadao->nome,
'nome_social' => $paciente->cidadao->nome_social,
'data_nascimento' => $paciente->cidadao->data_nascimento
? (new Carbon($paciente->cidadao->data_nascimento))->format('d/m/Y')
: null,
'prontuario' => $paciente->prontuario,
'raca_cor' => $paciente->cidadao->racaCor->descricao ?? null,
'sexo' => $paciente->cidadao->sexo->descricao ?? null,
'sexo_id' => $paciente->cidadao->sexo_id,
'cns' => MaskUtil::getCnsMasked($paciente->cidadao->cns),
'cpf' => MaskUtil::getCpfMasked($paciente->cidadao->cpf),
'rg' => $paciente->cidadao->carteiraIdentidade->numero ?? null,
'telefones' => $paciente->cidadao->telefones->map(fn ($telefone) => [
'numero' => MaskUtil::getPhoneMasked($telefone->numero),
'observacao' => $telefone->observacao ?? null,
'autoriza_sms' => $telefone->autoriza_sms,
'principal' => $telefone->principal,
]),
'nome_mae' => $paciente->cidadao->nome_mae,
'endereco' => is_null($paciente->cidadao->domicilio_id)
? null
: "{$paciente->cidadao->domicilio->endereco->completo} - "
. MaskUtil::getCepMasked($paciente->cidadao->domicilio->endereco->logradouro->cep),
'unidade_referencia' => $paciente->unidade->nome_fantasia ?? null,
'usuario_responsavel' => $paciente->cadastroIndividual->usuario->cidadao->nome ?? null,
'protocolo_cross' => $paciente->protocolo_cross ?? null,
'clissificacao_id' => $paciente->classificacao_id,
];
}
private static function getUnidadesSolicitantes()
{
return DB::table('cadastro_unidade as unidade')
->leftJoin('cadastro_infraestrutura as infraestrutura', 'infraestrutura.unidade_id', 'unidade.id')
->leftJoin('regulacao_parametrizacao_solicitante as solicitante', 'solicitante.infraestrutura_id', 'infraestrutura.id')
->whereNull('unidade.deleted_at')
->groupBy('unidade.id', 'unidade.nome_fantasia')
->orderBy('unidade.nome_fantasia')
->selectRaw("
unidade.id,
unidade.nome_fantasia,
MAX(solicitante.atende_outro_municipio) as atende_outro_municipio,
MAX(solicitante.is_ppi) as is_ppi
")
->get();
}
private static function getInfraestruturasSolicitantes($params)
{
return DB::table('cadastro_infraestrutura as infraestrutura')
->leftJoin(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.infraestrutura_id',
'infraestrutura.id'
)
->join('cadastro_unidade as unidade', 'unidade.id', 'infraestrutura.unidade_id')
->whereNull('infraestrutura.deleted_at')
->where('infraestrutura.unidade_id', $params['unidade_solicitante_id'])
->orderByRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia)")
->selectRaw("
infraestrutura.id,
COALESCE(infraestrutura.nome, unidade.nome_fantasia) as nome,
solicitante.atende_outro_municipio
")
->get();
}
private static function getUnidadesReguladoras($params, $id = null)
{
return DB::table('cadastro_unidade as unidade')
->whereNull('unidade.deleted_at')
->where(fn ($q) => $q
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_regulador as regulador')
->join('cadastro_infraestrutura as infraestrutura', 'infraestrutura.id', 'regulador.infraestrutura_id')
->whereColumn('infraestrutura.unidade_id', 'unidade.id')
->where('regulador.ativo', true)
->where(fn ($q) => $q
->where('regulador.tipo_id', ReguladorTipo::MUNICIPAL)
->orWhere(fn ($q) => $q
->where('regulador.tipo_id', ReguladorTipo::LOCAL_ATENDIMENTO)
->where('regulador.infraestrutura_id', $params['infraestrutura_solicitante_id'])
)
)
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador as solicitante_regulador')
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->whereColumn('solicitante_regulador.regulador_id', 'regulador.id')
->where('solicitante.infraestrutura_id', $params['infraestrutura_solicitante_id'])
)
)
->when($id, fn ($q) => $q->orWhere('unidade.id', $id))
)
->orderBy('unidade.nome_fantasia')
->selectRaw("
unidade.id,
unidade.nome_fantasia
")
->get();
}
private static function getReguladores($params, $id = null)
{
return DB::table('regulacao_parametrizacao_regulador as regulador')
->join('cadastro_infraestrutura as infraestrutura', 'infraestrutura.id', 'regulador.infraestrutura_id')
->join('cadastro_unidade as unidade', 'unidade.id', 'infraestrutura.unidade_id')
->where('regulador.ativo', true)
->where('unidade.id', $params['unidade_reguladora_id'])
->where(fn ($q) => $q
->where('regulador.tipo_id', ReguladorTipo::MUNICIPAL)
->orWhere(fn ($q) => $q
->where('regulador.tipo_id', ReguladorTipo::LOCAL_ATENDIMENTO)
->where('regulador.infraestrutura_id', $params['infraestrutura_solicitante_id'])
)
)
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador as solicitante_regulador')
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->whereColumn('solicitante_regulador.regulador_id', 'regulador.id')
->where('solicitante.infraestrutura_id', $params['infraestrutura_solicitante_id'])
)
->when($id, fn ($q) => $q->orWhere('regulador.id', $id))
->orderByRaw("COALESCE(infraestrutura.nome, unidade.nome_fantasia)")
->selectRaw("
regulador.id,
COALESCE(infraestrutura.nome, unidade.nome_fantasia) as nome
")
->get();
}
private static function getGruposExames()
{
return DB::table('cadastro_grupo as grupo')
->whereNull('grupo.deleted_at')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('parametrizacao_exame as exame')
->whereColumn('exame.grupo_tipo_id', 'grupo.id')
->whereNull('exame.deleted_at')
->where('exame.ativo', true)
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador_exame as parametrizacao_exame')
->whereColumn('parametrizacao_exame.exame_id', 'exame.id')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador as solicitante_regulador')
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->whereColumn('solicitante_regulador.id', 'parametrizacao_exame.solicitante_regulador_id')
->where('solicitante.infraestrutura_id', request()->infraestrutura_solicitante_id)
->where('solicitante_regulador.regulador_id', request()->regulador_id)
)
)
)
->selectRaw("
grupo.id,
grupo.nome
")
->get();
}
private static function getGruposProcedimentosCirurgicos()
{
return DB::table('cadastro_grupo as grupo')
->whereNull('grupo.deleted_at')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('parametrizacao_procedimento_cirurgico as procedimento_cirurgico')
->whereColumn('procedimento_cirurgico.grupo_exame_id', 'grupo.id')
->where('procedimento_cirurgico.status', true)
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador_proced_cirurgico as parametrizacao_procedimento_cirurgico')
->whereColumn('parametrizacao_procedimento_cirurgico.procedimento_cirurgico_id', 'procedimento_cirurgico.id')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('regulacao_parametrizacao_solicitante_regulador as solicitante_regulador')
->join(
'regulacao_parametrizacao_solicitante as solicitante',
'solicitante.id',
'solicitante_regulador.solicitante_id'
)
->whereColumn('solicitante_regulador.id', 'parametrizacao_procedimento_cirurgico.solicitante_regulador_id')
->where('solicitante.infraestrutura_id', request()->infraestrutura_solicitante_id)
->where('solicitante_regulador.regulador_id', request()->regulador_id)
)
)
)
->selectRaw("
grupo.id,
grupo.nome
")
->get();
}
private static function getPrioridades()
{
return DB::table('regulacao_solicitacao_prioridade as prioridade')
->orderBy('prioridade.nome')
->selectRaw("
prioridade.id,
prioridade.nome
")
->get();
}
public static function getNovoNumeroSolicitacao()
{
return (int) (new DateTimeImmutable())->format('Uu');
}
public static function store()
{
self::validateStore();
$solicitacao = new Solicitacao();
DB::transaction(function () use ($solicitacao) {
Paciente::findOrFail(request()->paciente_id)->update([
'protocolo_cross' => request()->protocolo_cross ?? null,
]);
$statusId = Status::where('ativo', true)->where('tipo_id', StatusTipo::SOLICITADO)->first()->id ?? null;
if (is_null($statusId)) {
throw new CannotCreateSolicitacaoException();
}
$itens = collect(request()->itens);
$posicoes = self::getProximasPosicoes(request()->prioridade_id, request()->regulador_id, (object) $itens->first());
$posicaoPortal = self::getProximaPosicaoPortal(request()->prioridade_id, (object) $itens->first());
$solicitacao->fill([
'numero' => request()->numero,
'posicao_municipal' => $posicoes->posicao_municipal,
'posicao_regulador' => $posicoes->posicao_regulador,
'posicao_portal' => $posicaoPortal,
'data' => request()->data_solicitacao ?? Carbon::today(),
'paciente_id' => request()->paciente_id,
'status_id' => $statusId,
'infraestrutura_solicitante_id' => request()->infraestrutura_solicitante_id,
'usuario_solicitante_id' => request()->usuario_solicitante_id,
'regulador_id' => request()->regulador_id,
'cid_id' => request()->cid_id,
'ciap_id' => request()->ciap_id,
'hipotese_diagnostica_justificativa' => request()->hipotese_diagnostica_justificativa,
'prioridade_id' => request()->prioridade_id,
'observacao' => request()->observacao,
'data_desejada' => request()->data_desejada
? Carbon::createFromFormat('d/m/Y', request()->data_desejada)
: null,
'peso' => request()->peso,
'altura' => request()->altura,
'confirmado_em' => Carbon::now(),
'confirmado_lotacao_id' => self::getCurrentLotacao()->id,
'unidade_usuario_id' => request()->unidade_usuario_id,
'infraestrutura_usuario_id' => request()->infraestrutura_usuario_id,
'ocupacao_usuario_id' => request()->ocupacao_usuario_id,
'lotaca_usuario_id' => request()->lotacao_usuario_id,
'usuario_solicitante_especialidade_id' => request()->usuario_solicitante_especialidade_id,
]);
$solicitacao->save();
$itensExistentes = [];
$itens->each(function ($item) use ($solicitacao, &$itensExistentes) {
$exameId = $item['exame_id'] ?? null;
$procedimentoCirurgicoId = $item['procedimento_cirurgico_id'] ?? null;
$especialidadeId = $item['especialidade_id'] ?? null;
$existeItem = DB::table('regulacao_solicitacao_item')
->join('regulacao_solicitacao', 'regulacao_solicitacao.id', 'regulacao_solicitacao_item.solicitacao_id')
->join('regulacao_status', 'regulacao_status.id', 'regulacao_solicitacao.status_id')
->leftJoin('parametrizacao_exame', 'parametrizacao_exame.id', 'regulacao_solicitacao_item.exame_id')
->leftJoin('parametrizacao_procedimento_cirurgico', 'parametrizacao_procedimento_cirurgico.id', 'regulacao_solicitacao_item.procedimento_cirurgico_id')
->leftJoin('cadastro_especialidade', 'cadastro_especialidade.id', 'regulacao_solicitacao_item.especialidade_id')
->where('regulacao_solicitacao.paciente_id', $solicitacao->paciente_id)
->where('regulacao_solicitacao.paciente_id', $solicitacao->paciente_id)
->whereNotIn('regulacao_status.tipo_id', [StatusTipo::REALIZADO, StatusTipo::CANCELADO, StatusTipo::FALTA])
->when($exameId, function ($query, $exameId) {
return $query->where('exame_id', $exameId);
})
->when($procedimentoCirurgicoId, function ($query, $procedimentoCirurgicoId) {
return $query->where('procedimento_cirurgico_id', $procedimentoCirurgicoId);
})
->when($especialidadeId, function ($query, $especialidadeId) {
return $query->where('especialidade_id', $especialidadeId);
})
->selectRaw("
parametrizacao_exame.nome as exame_nome,
parametrizacao_procedimento_cirurgico.nome as procedimento_nome,
cadastro_especialidade.nome as especialidade_nome
")
->first();
if ($existeItem) {
$itensExistentes[] = [
'nome' => $exameId ? $existeItem->exame_nome :
($procedimentoCirurgicoId ? $existeItem->procedimento_nome :
$existeItem->especialidade_nome),
];
}
$solicitacao->itens()->create([
'exame_id' => $item['origem'] === 'exame' ? $item['exame_id'] : null,
'procedimento_cirurgico_id' => $item['origem'] === 'procedimento_cirurgico'
? $item['procedimento_cirurgico_id']
: null,
'especialidade_id' => $item['origem'] === 'especialidade' ? $item['especialidade_id'] : null,
]);
});
if (count($itensExistentes) > 0 && (!isset(request()->is_supervisor) || !request()->is_supervisor)) {
DB::rollBack();
throw new CannotStoreSolicitacaoException($itensExistentes);
}
self::saveHistorico($solicitacao);
});
return $solicitacao->fresh();
}
private static function validateStore()
{
return request()->validate([
'paciente_id' => [
'required',
'integer',
Rule::exists(Paciente::class, 'id'),
],
'protocolo_cross' => [
'nullable',
'digits_between:1,10',
],
'numero' => [
'required',
'digits:16',
Rule::unique(Solicitacao::class, 'numero'),
],
'infraestrutura_solicitante_id' => [
'required',
'integer',
Rule::exists(Infraestrutura::class, 'id'),
],
'usuario_solicitante_id' => [
'required',
'integer',
Rule::exists(Usuario::class, 'id'),
],
'regulador_id' => [
'required',
'integer',
Rule::exists(ParametrizacaoRegulador::class, 'id'),
],
'cid_id' => [
'nullable',
'integer',
Rule::exists(Cid::class, 'id'),
],
'ciap_id' => [
'nullable',
Rule::requiredIf(fn () => (Usuario::find(request()->usuario_solicitante_id)
->registro_tipo_id ?? null) === TipoRegistroUsuario::ENFERMAGEM),
'integer',
Rule::exists(Ciap::class, 'id'),
],
'hipotese_diagnostica_justificativa' => [
'nullable',
'string',
'max:5000',
],
'prioridade_id' => [
'required',
'integer',
Rule::exists(SolicitacaoPrioridade::class, 'id'),
],
'observacao' => [
'nullable',
'string',
'max:5000',
],
'data_desejada' => [
'nullable',
'date_format:d/m/Y',
'after_or_equal:' . Carbon::today()->format('d/m/Y'),
],
'peso' => [
'nullable',
'numeric',
'between:0.5,500',
],
'altura' => [
'nullable',
'numeric',
'between:20,250',
],
'itens' => [
'required',
'array',
],
'itens.*.origem' => [
'required',
'string',
Rule::in(['exame', 'procedimento_cirurgico', 'especialidade']),
],
'itens.*.exame_id' => [
'nullable',
'required_if:itens.*.origem,exame',
Rule::exists(Exame::class, 'id'),
],
'itens.*.procedimento_cirurgico_id' => [
'nullable',
'required_if:itens.*.origem,procedimento_cirurgico',
Rule::exists(ProcedimentoCirurgico::class, 'id'),
],
'itens.*.especialidade_id' => [
'nullable',
'required_if:itens.*.origem,especialidade',
Rule::exists(Especialidade::class, 'id'),
],
'unidade_usuario_id' => [
'required',
'integer',
Rule::exists(Unidade::class, 'id'),
],
'infraestrutura_usuario_id' => [
'required',
'integer',
Rule::exists(Infraestrutura::class, 'id'),
],
'ocupacao_usuario_id' => [
'required',
'integer',
Rule::exists(Ocupacao::class, 'id'),
],
'lotacao_usuario_id' => [
'required',
'integer',
Rule::exists(Lotacao::class, 'id'),
],
'usuario_solicitante_especialidade_id' => [
'nullable',
'integer',
Rule::exists(Especialidade::class, 'id'),
],
], [
'numero.unique' => 'O número já foi utilizado em outra solicitação.',
'unidade_usuario_id.required' => 'O campo unidade do profissional é obrigatório.',
'infraestrutura_usuario_id.required' => 'O campo local de atendimento do profissional é obrigatório.',
'lotacao_usuario_id.required' => 'Profissional sem lotação.',
'ocupacao_usuario_id.required' => 'O campo ocupação do profissional é obrigatório.',
]);
}
public static function getProximasPosicoes($prioridadeId, $reguladorId, $item)
{
$filterItem = fn ($q) => self::filterItemPosicao($q, $item);
$getUltimaPosicaoMunicipal = function ($prioridadeId = null) use ($filterItem) {
return Solicitacao::when($prioridadeId, fn ($q, $id) => $q->where('prioridade_id', $id))
->whereHas('itens', $filterItem)
->max('posicao_municipal') ?? 0;
};
$getUltimaPosicaoRegulador = function ($prioridadeId = null) use ($reguladorId, $filterItem) {
return Solicitacao::where('regulador_id', $reguladorId)
->when($prioridadeId, fn ($q, $id) => $q->where('prioridade_id', $id))
->whereHas('itens', $filterItem)
->max('posicao_regulador') ?? 0;
};
$ultimaPosicaoMunicipal = null;
$ultimaPosicaoRegulador = null;
if ($prioridadeId === SolicitacaoPrioridadeEnum::ELETIVO) {
$ultimaPosicaoMunicipal = $getUltimaPosicaoMunicipal();
$ultimaPosicaoRegulador = $getUltimaPosicaoRegulador();
}
else {
$ultimaPosicaoMunicipal = $getUltimaPosicaoMunicipal($prioridadeId);
$ultimaPosicaoRegulador = $getUltimaPosicaoRegulador($prioridadeId);
if ($prioridadeId === SolicitacaoPrioridadeEnum::URGENCIA) {
if ($ultimaPosicaoMunicipal === 0) {
$ultimaPosicaoMunicipal = $getUltimaPosicaoMunicipal(SolicitacaoPrioridadeEnum::EMERGENCIA);
}
if ($ultimaPosicaoRegulador === 0) {
$ultimaPosicaoRegulador = $getUltimaPosicaoRegulador(SolicitacaoPrioridadeEnum::EMERGENCIA);
}
}
else if ($prioridadeId === SolicitacaoPrioridadeEnum::PRIORITARIO) {
if ($ultimaPosicaoMunicipal === 0) {
$ultimaPosicaoMunicipal = $getUltimaPosicaoMunicipal(SolicitacaoPrioridadeEnum::URGENCIA);
if ($ultimaPosicaoMunicipal === 0) {
$ultimaPosicaoMunicipal = $getUltimaPosicaoMunicipal(SolicitacaoPrioridadeEnum::EMERGENCIA);
}
}
if ($ultimaPosicaoRegulador === 0) {
$ultimaPosicaoRegulador = $getUltimaPosicaoRegulador(SolicitacaoPrioridadeEnum::URGENCIA);
if ($ultimaPosicaoRegulador === 0) {
$ultimaPosicaoRegulador = $getUltimaPosicaoRegulador(SolicitacaoPrioridadeEnum::EMERGENCIA);
}
}
}
self::incrementPositionsAfter($ultimaPosicaoMunicipal, $reguladorId, $ultimaPosicaoRegulador, $item);
}
return (object) [
'posicao_municipal' => $ultimaPosicaoMunicipal + 1,
'posicao_regulador' => $ultimaPosicaoRegulador + 1,
];
}
public static function getProximaPosicaoPortal($prioridadeId, $item)
{
$filterItem = fn ($q) => self::filterItemPosicao($q, $item);
$getUltimaPosicaoPortal = function ($prioridadeId = null) use ($filterItem) {
return Solicitacao::when($prioridadeId, fn ($q, $id) => $q->where('prioridade_id', $id))
->whereHas('itens', $filterItem)
->max('posicao_portal') ?? 0;
};
$ultimaPosicaoPortal = null;
if ($prioridadeId === SolicitacaoPrioridadeEnum::ELETIVO) {
$ultimaPosicaoPortal = $getUltimaPosicaoPortal();
}
else {
$ultimaPosicaoPortal = $getUltimaPosicaoPortal($prioridadeId);
if ($prioridadeId === SolicitacaoPrioridadeEnum::URGENCIA) {
if ($ultimaPosicaoPortal === 0) {
$ultimaPosicaoPortal = $getUltimaPosicaoPortal(SolicitacaoPrioridadeEnum::EMERGENCIA);
}
}
else if ($prioridadeId === SolicitacaoPrioridadeEnum::PRIORITARIO) {
if ($ultimaPosicaoPortal === 0) {
$ultimaPosicaoPortal = $getUltimaPosicaoPortal(SolicitacaoPrioridadeEnum::URGENCIA);
if ($ultimaPosicaoPortal === 0) {
$ultimaPosicaoPortal = $getUltimaPosicaoPortal(SolicitacaoPrioridadeEnum::EMERGENCIA);
}
}
}
self::incrementPositionsPortalAfter($ultimaPosicaoPortal, $item);
}
return $ultimaPosicaoPortal + 1;
}
private static function incrementPositionsPortalAfter($posicaoPortal, $item)
{
$filterItem = fn ($q) => self::filterItemPosicao($q, $item);
Solicitacao::whereNotNull('posicao_portal')
->whereHas('itens', $filterItem)
->where('posicao_portal', '>', $posicaoPortal)
->orderByDesc('posicao_portal')
->get(['id', 'posicao_portal'])
->each(function ($solicitacao) {
$solicitacao->update(['posicao_portal' => $solicitacao->posicao_portal + 1]);
});
}
public static function update($id)
{
$solicitacao = Solicitacao::findOrFail($id);
$historico = DB::table('regulacao_solicitacao_historico')
->where('solicitacao_id', $solicitacao->id)
->count();
$statusReenviada = $solicitacao->status->statusPara()
->where('ativo', true)
->where('tipo_id', StatusTipo::REENVIADA)
->first();
if ($historico !== 1
&& $solicitacao->confirmado
&& ($solicitacao->status->tipo_id !== StatusTipo::DEVOLVIDO || is_null($statusReenviada))
) {
throw new CannotUpdateSolicitacaoException();
}
self::validateUpdate();
DB::transaction(function () use ($solicitacao, $statusReenviada) {
Paciente::findOrFail(request()->paciente_id)->update([
'protocolo_cross' => request()->protocolo_cross ?? null
]);
$params = [
'protocolo_cross' => request()->protocolo_cross ?? null,
'usuario_solicitante_id' => request()->usuario_solicitante_id,
'cid_id' => request()->cid_id,
'ciap_id' => request()->ciap_id,
'hipotese_diagnostica_justificativa' => request()->hipotese_diagnostica_justificativa,
'prioridade_id' => request()->prioridade_id,
'observacao' => request()->observacao,
'data_desejada' => request()->data_desejada
? Carbon::createFromFormat('d/m/Y', request()->data_desejada)
: null,
'peso' => request()->peso,
'altura' => request()->altura,
'unidade_usuario_id' => request()->unidade_usuario_id,
'infraestrutura_usuario_id' => request()->infraestrutura_usuario_id,
'ocupacao_usuario_id' => request()->ocupacao_usuario_id,
'lotaca_usuario_id' => request()->lotacao_usuario_id,
'usuario_solicitante_especialidade_id' => request()->usuario_solicitante_especialidade_id,
];
if ($solicitacao->confirmado && $statusReenviada) {
$params['status_id'] = $statusReenviada->id;
} else if (request()->confirmado) {
$params['confirmado_em'] = Carbon::now();
$params['confirmado_lotacao_id'] = self::getCurrentLotacao()->id;
}
$solicitacao->update($params);
$itensExistentes = [];
collect(request()->itens)
->filter(fn ($i) => is_null($i['id']) && $i['origem'] === 'exame')
->each(function ($item) use ($solicitacao, &$itensExistentes) {
$existeItem = DB::table('regulacao_solicitacao_item')
->join('regulacao_solicitacao', 'regulacao_solicitacao.id', 'regulacao_solicitacao_item.solicitacao_id')
->leftJoin('parametrizacao_exame', 'parametrizacao_exame.id', 'regulacao_solicitacao_item.exame_id')
->where('regulacao_solicitacao.paciente_id', $solicitacao->paciente_id)
->where('regulacao_solicitacao.status_id', '!=', StatusTipo::REALIZADO)
->where('regulacao_solicitacao.status_id', '!=', StatusTipo::CANCELADO)
->where('regulacao_solicitacao_item.exame_id', $item['exame_id'])
->selectRaw("
parametrizacao_exame.nome as exame_nome
")
->first();
if ($existeItem) {
$itensExistentes[] = [
'nome' => $existeItem->exame_nome,
];
}
});
collect(request()->itens)
->filter(fn ($i) => is_null($i['id']) && $i['origem'] === 'exame')
->each(function ($item) use ($solicitacao) {
$solicitacao->itens()->create([
'exame_id' => $item['exame_id']
]);
});
if (count($itensExistentes) > 0 && (!isset(request()->is_supervisor) || !request()->is_supervisor)) {
DB::rollBack();
throw new CannotStoreSolicitacaoException($itensExistentes);
}
self::saveHistorico($solicitacao);
});
return $solicitacao->fresh();
}
private static function validateUpdate()
{
return request()->validate([
'confirmado' => [
'required',
'boolean',
],
'protocolo_cross' => [
'nullable',
'digits_between:1,10',
],
'usuario_solicitante_id' => [
'required',
'integer',
Rule::exists(Usuario::class, 'id'),
],
'cid_id' => [
'nullable',
'integer',
Rule::exists(Cid::class, 'id'),
],
'ciap_id' => [
'nullable',
Rule::requiredIf(fn () => (Usuario::find(request()->usuario_solicitante_id)
->registro_tipo_id ?? null) === TipoRegistroUsuario::ENFERMAGEM),
'integer',
Rule::exists(Ciap::class, 'id'),
],
'hipotese_diagnostica_justificativa' => [
'nullable',
'string',
'max:5000',
],
'prioridade_id' => [
'required',
'integer',
Rule::exists(SolicitacaoPrioridade::class, 'id'),
],
'observacao' => [
'nullable',
'string',
'max:5000',
],
'data_desejada' => [
'nullable',
'date_format:d/m/Y',
'after_or_equal:' . Carbon::today()->format('d/m/Y'),
],
'peso' => [
'nullable',
'numeric',
'between:0.5,500',
],
'altura' => [
'nullable',
'numeric',
'between:20,250',
],
'itens' => [
'required',
'array',
],
'itens.*.id' => [
'nullable',
'integer',
Rule::exists(SolicitacaoItem::class, 'id'),
],
'itens.*.origem' => [
'required',
'string',
Rule::in(['exame', 'procedimento_cirurgico', 'especialidade']),
],
'itens.*.exame_id' => [
'nullable',
'required_if:itens.*.origem,exame',
Rule::exists(Exame::class, 'id'),
],
'itens.*.procedimento_cirurgico_id' => [
'nullable',
'required_if:itens.*.origem,procedimento_cirurgico',
Rule::exists(ProcedimentoCirurgico::class, 'id'),
],
'itens.*.especialidade_id' => [
'nullable',
'required_if:itens.*.origem,especialidade',
Rule::exists(Especialidade::class, 'id'),
],
'unidade_usuario_id' => [
'required',
'integer',
Rule::exists(Unidade::class, 'id'),
],
'infraestrutura_usuario_id' => [
'required',
'integer',
Rule::exists(Infraestrutura::class, 'id'),
],
'ocupacao_usuario_id' => [
'required',
'integer',
Rule::exists(Ocupacao::class, 'id'),
],
'lotacao_usuario_id' => [
'required',
'integer',
Rule::exists(Lotacao::class, 'id'),
],
'usuario_solicitante_especialidade_id' => [
'nullable',
'integer',
Rule::exists(Especialidade::class, 'id'),
],
]);
}
public static function cancel($id, $params)
{
$solicitacao = Solicitacao::findOrFail($id);
$statusCancelado = $solicitacao->status->statusPara()
->where('ativo', true)
->where('tipo_id', StatusTipo::CANCELADO)
->first();
if ($solicitacao->status->tipo_id === StatusTipo::CANCELADO || is_null($statusCancelado)) {
throw new CannotCancelSolicitacaoException();
}
self::validateCancel($params);
DB::transaction(function () use ($solicitacao, $statusCancelado, $params) {
$posicaoMunicipalAnterior = $solicitacao->posicao_municipal;
$posicaoReguladorAnterior = $solicitacao->posicao_regulador;
$posicaoPortalAnterior = $solicitacao->posicao_portal;
$solicitacao->update([
'posicao_municipal' => null,
'posicao_regulador' => null,
'posicao_portal' => null,
'status_id' => $statusCancelado->id,
'cancelado_em' => Carbon::now(),
'cancelado_lotacao_id' => self::getCurrentLotacao()->id,
'justificativa_cancelamento' => $params['justificativa'],
]);
self::saveHistorico($solicitacao);
self::decrementPositionsAfter(
$posicaoMunicipalAnterior,
$solicitacao->regulador_id,
$posicaoReguladorAnterior,
$solicitacao->itens()->first()
);
if (!is_null($posicaoPortalAnterior)) {
self::decrementPositionsPortalAfter(
$posicaoPortalAnterior,
$solicitacao->itens()->first()
);
}
self::updateStatusNoModuloDeAgendamento($solicitacao);
});
return $solicitacao->fresh();
}
private static function updateStatusNoModuloDeAgendamento($solicitacao)
{
if ($agendamento = self::getAmbulatorioAgendamentoAtual($solicitacao)) {
AmbulatorioAgendamentoService::cancel($agendamento->id, [
'is_from_regulacao' => true,
'motivo' => $solicitacao->justificativa_cancelamento,
]);
}
else if ($agendamento = $solicitacao->exameImagemAgendamento) {
ExameImagemAgendamentoExame::where('agendamento_id', $agendamento->id)->delete();
$agendamento->delete();
}
else if ($agendamento = $solicitacao->exameLaboratorialAgendamento) {
ExameLaboratorialAgendamentoExame::where('agendamento_id', $agendamento->id)
->update(['status_id' => ExameLaboratorialAgendamentoStatus::CANCELADO]);
$exames = ExameLaboratorialAgendamentoExame::where('agendamento_id', $agendamento->id)
->pluck('id');
$exames->map(function($item) use($agendamento) {
$exame = ExameLaboratorialAgendamentoExame::where('id', $item)->first();
AgendamentoExameHistoricoService::store($exame, $agendamento, Acao::ALTERACAO);
});
}
}
private static function getAmbulatorioAgendamentoAtual($solicitacao)
{
return $solicitacao->ambulatorioAgendamentos()
->whereNotIn('status_id', AmbulatorioAgendamentoService::getStatusLiberamHorario())
->first();
}
private static function validateCancel($params)
{
Validator::make($params, [
'justificativa' => [
'required',
'string',
'max:500',
],
])->validate();
}
public static function updatePrioridade($solicitacaoId, $prioridadeIdPara, $motivo)
{
$solicitacao = Solicitacao::findOrFail($solicitacaoId);
if ($solicitacao->prioridade_id === $prioridadeIdPara) {
return;
}
DB::transaction(function () use ($solicitacao, $prioridadeIdPara, $motivo) {
$posicaoMunicipalAnterior = $solicitacao->posicao_municipal;
$posicaoReguladorAnterior = $solicitacao->posicao_regulador;
$posicaoPortalAnterior = $solicitacao->posicao_portal;
$solicitacao->update([
'posicao_municipal' => null,
'posicao_regulador' => null,
'posicao_portal' => null,
'prioridade_id' => $prioridadeIdPara,
'motivo_alteracao_prioridade' => $motivo
]);
self::saveHistorico($solicitacao);
$solicitacao->refresh();
SolicitacaoService::decrementPositionsAfter(
$posicaoMunicipalAnterior,
$solicitacao->regulador_id,
$posicaoReguladorAnterior,
$solicitacao->itens()->first()
);
if (!is_null($posicaoPortalAnterior)) {
SolicitacaoService::decrementPositionsPortalAfter(
$posicaoPortalAnterior,
$solicitacao->itens()->first()
);
}
$posicoes = SolicitacaoService::getProximasPosicoes(
$solicitacao->prioridade_id,
$solicitacao->regulador_id,
$solicitacao->itens()->first()
);
$posicaoPortal = self::getStatusTiposLiberamPosicaoPortal()->contains($solicitacao->status->tipo_id)
? null
: SolicitacaoService::getProximaPosicaoPortal(
$solicitacao->prioridade_id,
$solicitacao->itens()->first()
);
$solicitacao->update([
'posicao_municipal' => $posicoes->posicao_municipal,
'posicao_regulador' => $posicoes->posicao_regulador,
'posicao_portal' => $posicaoPortal,
]);
SolicitacaoService::saveHistorico($solicitacao);
});
}
public static function getStatusTiposLiberamPosicaoPortal()
{
return collect([
StatusTipo::CANCELADO,
StatusTipo::AGENDADO,
StatusTipo::REAGENDADO,
StatusTipo::FALTA,
StatusTipo::REALIZADO,
]);
}
public static function updateStatus($solicitacaoId, $statusTipoId, $params = [])
{
$solicitacao = Solicitacao::find($solicitacaoId);
if($solicitacao)
{
if (!collect([StatusTipo::AGENDADO, StatusTipo::REAGENDADO])->contains($solicitacao->status->tipo_id)) {
return;
}
if ($statusTipoId === StatusTipo::CANCELADO) {
return self::cancel($solicitacaoId, $params);
}
$statusPara = $solicitacao->status->statusPara()
->where('ativo', true)
->where('tipo_id', $statusTipoId)
->first();
if (is_null($statusPara)) {
throw new CannotUpdateSolicitacaoException();
}
if (collect([StatusTipo::FALTA, StatusTipo::REALIZADO])->contains($statusTipoId)) {
$posicaoMunicipalAnterior = $solicitacao->posicao_municipal;
$posicaoReguladorAnterior = $solicitacao->posicao_regulador;
$solicitacao->update([
'status_id' => $statusPara->id,
'posicao_municipal' => null,
'posicao_regulador' => null,
]);
self::saveHistorico($solicitacao);
$solicitacao->refresh();
SolicitacaoService::decrementPositionsAfter(
$posicaoMunicipalAnterior,
$solicitacao->regulador_id,
$posicaoReguladorAnterior,
$solicitacao->itens()->first()
);
}
}
return $solicitacao;
}
public static function voltarParaStatusSolicitado($solicitacaoId)
{
$solicitacao = Solicitacao::findOrFail($solicitacaoId);
if (!collect([StatusTipo::AGENDADO, StatusTipo::REAGENDADO])->contains($solicitacao->status->tipo_id)) {
return;
}
$statusId = $solicitacao->historico()
->whereDoesntHave('status', fn ($q) => $q
->whereIn('tipo_id', [StatusTipo::AGENDADO, StatusTipo::REAGENDADO])
)
->orderByDesc('created_at')
->first('status_id')
->status_id ?? null;
if(is_null($statusId)){
$statusId = Status::where('ativo', true)->where('tipo_id', StatusTipo::SOLICITADO)->first()->id ?? null;
if (is_null($statusId)) {
throw new CannotCreateSolicitacaoException();
}
}
$solicitacao->update([
'status_id' => $statusId,
'prestador_interno_id' => null,
'prestador_externo_id' => null,
'opcao_retirada_protocolo_agendamento_id' => null,
'nome_pessoa_retirada_protocolo_agendamento' => null,
'data_agendada' => null,
'hora_agendada' => null,
]);
self::saveHistorico($solicitacao);
return $solicitacao->fresh();
}
public static function decrementPositionsAfter($posicaoMunicipal, $reguladorId, $posicaoRegulador, $item)
{
$filterItem = fn ($q) => self::filterItemPosicao($q, $item);
Solicitacao::whereNotNull('posicao_municipal')
->whereHas('itens', $filterItem)
->where('posicao_municipal', '>', $posicaoMunicipal)
->orderBy('posicao_municipal')
->get(['id', 'posicao_municipal'])
->each(function ($solicitacao) {
$solicitacao->update(['posicao_municipal' => $solicitacao->posicao_municipal - 1]);
});
Solicitacao::where('regulador_id', $reguladorId)
->whereNotNull('posicao_regulador')
->whereHas('itens', $filterItem)
->where('posicao_regulador', '>', $posicaoRegulador)
->orderBy('posicao_regulador')
->get(['id', 'posicao_regulador'])
->each(function ($solicitacao) {
$solicitacao->update(['posicao_regulador' => $solicitacao->posicao_regulador - 1]);
});
}
public static function decrementPositionsPortalAfter($posicaoPortal, $item)
{
$filterItem = fn ($q) => self::filterItemPosicao($q, $item);
Solicitacao::whereNotNull('posicao_portal')
->whereHas('itens', $filterItem)
->where('posicao_portal', '>', $posicaoPortal)
->orderBy('posicao_portal')
->get(['id', 'posicao_portal'])
->each(function ($solicitacao) {
$solicitacao->update(['posicao_portal' => $solicitacao->posicao_portal - 1]);
});
}
private static function incrementPositionsAfter($posicaoMunicipal, $reguladorId, $posicaoRegulador, $item)
{
$filterItem = fn ($q) => self::filterItemPosicao($q, $item);
Solicitacao::whereNotNull('posicao_municipal')
->whereHas('itens', $filterItem)
->where('posicao_municipal', '>', $posicaoMunicipal)
->orderByDesc('posicao_municipal')
->get(['id', 'posicao_municipal'])
->each(function ($solicitacao) {
$solicitacao->update(['posicao_municipal' => $solicitacao->posicao_municipal + 1]);
});
Solicitacao::where('regulador_id', $reguladorId)
->whereNotNull('posicao_regulador')
->whereHas('itens', $filterItem)
->where('posicao_regulador', '>', $posicaoRegulador)
->orderByDesc('posicao_regulador')
->get(['id', 'posicao_regulador'])
->each(function ($solicitacao) {
$solicitacao->update(['posicao_regulador' => $solicitacao->posicao_regulador + 1]);
});
}
public static function filterItemPosicao($query, $item)
{
return $query
->when($item->origem === 'procedimento_cirurgico', fn ($q) => $q
->where('procedimento_cirurgico_id', $item->procedimento_cirurgico_id)
)
->when($item->origem === 'especialidade', fn ($q) => $q
->where('especialidade_id', $item->especialidade_id)
)
->when($item->origem === 'exame', fn ($q) => $q
->when(Exame::findOrFail($item->exame_id)->tipo_id === Tipo::LABORATORIAL,
fn ($q) => $q->whereHas('exame', fn ($q) => $q
->where('tipo_id', Tipo::LABORATORIAL)
),
fn ($q) => $q->where('exame_id', $item->exame_id)
)
);
}
public static function saveHistorico($solicitacao)
{
$solicitacao = $solicitacao->fresh();
$raw = (object) $solicitacao->getRawOriginal();
$ultimoStatusId = SolicitacaoMovimentacao::where('solicitacao_id', $raw->id)
->orderByDesc('id')
->first('status_id')
->status_id ?? null;
if ($raw->status_id !== $ultimoStatusId) {
SolicitacaoMovimentacao::create([
'solicitacao_id' => $raw->id,
'status_id' => $raw->status_id,
'movimentado_em' => $raw->updated_at,
'lotacao_id' => $raw->updated_lotacao_id,
]);
}
$solicitacaoHistorico = SolicitacaoHistorico::create([
'solicitacao_id' => $raw->id,
'numero' => $raw->numero,
'posicao_municipal' => $raw->posicao_municipal,
'posicao_regulador' => $raw->posicao_regulador,
'posicao_portal' => $raw->posicao_portal,
'data' => $raw->data,
'paciente_id' => $raw->paciente_id,
'status_id' => $raw->status_id,
'infraestrutura_solicitante_id' => $raw->infraestrutura_solicitante_id,
'usuario_solicitante_id' => $raw->usuario_solicitante_id,
'regulador_id' => $raw->regulador_id,
'prestador_interno_id' => $raw->prestador_interno_id,
'prestador_externo_id' => $raw->prestador_externo_id,
'cid_id' => $raw->cid_id,
'ciap_id' => $raw->ciap_id,
'hipotese_diagnostica_justificativa' => $raw->hipotese_diagnostica_justificativa,
'prioridade_id' => $raw->prioridade_id,
'observacao' => $raw->observacao,
'data_desejada' => $raw->data_desejada,
'peso' => $raw->peso,
'altura' => $raw->altura,
'confirmado_em' => $raw->confirmado_em,
'confirmado_lotacao_id' => $raw->confirmado_lotacao_id,
'cancelado_em' => $raw->cancelado_em,
'cancelado_lotacao_id' => $raw->cancelado_lotacao_id,
'justificativa_cancelamento' => $raw->justificativa_cancelamento,
'justificativa_reagendamento' => $raw->justificativa_reagendamento,
'justificativa_remarcacao' => $raw->justificativa_remarcacao,
'justificativa_devolucao' => $raw->justificativa_devolucao,
'justificativa_reenvio' => $raw->justificativa_reenvio,
'justificativa_falta' => $raw->justificativa_falta,
'opcao_retirada_protocolo_agendamento_id' => $raw->opcao_retirada_protocolo_agendamento_id,
'nome_pessoa_retirada_protocolo_agendamento' => $raw->nome_pessoa_retirada_protocolo_agendamento,
'data_agendada' => $raw->data_agendada,
'hora_agendada' => $raw->hora_agendada,
'motivo_alteracao_prioridade' => $raw->motivo_alteracao_prioridade,
'acompanhamento_oci_id' => $raw->acompanhamento_oci_id,
'ocupacao_executora_id' => $raw->ocupacao_executora_id,
'usuario_executor_nome' => $raw->usuario_executor_nome,
'soap_id' => $raw->soap_id ?? null,
]);
$solicitacao->itens->each(function ($item) use ($solicitacaoHistorico) {
$raw = (object) $item->getRawOriginal();
$solicitacaoHistorico->itens()->create([
'exame_id' => $raw->exame_id,
'procedimento_cirurgico_id' => $raw->procedimento_cirurgico_id,
'especialidade_id' => $raw->especialidade_id,
]);
});
$solicitacao->tentativasContato->each(function ($tentativaContato) use ($solicitacaoHistorico) {
$raw = (object) $tentativaContato->getRawOriginal();
$solicitacaoHistorico->tentativasContato()->create([
'data' => $raw->data,
'usuario_id' => $raw->usuario_id,
'detalhes' => $raw->detalhes,
]);
});
}
public static function getInfoProfissional()
{
$id = request()->usuario_id ?? null;
switch (request()->listar) {
case 'unidades':
return self::getUnidadeProfissional($id);
case 'infraestruturas':
return self::getInfraestruturaProfissional(request()->usuario_id, request()->unidade_id);
case 'ocupacoes':
return self::getOcupacaoProfissional(request()->usuario_id, request()->infraestrutura_id);
case 'especialidades':
return self::getEspecialidadeProfissional(request()->ocupacao_id);
default:
return null;
}
}
public static function getUnidadeProfissional($id)
{
$unidades = DB::table('cadastro_lotacao')
->leftJoin('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_lotacao.infraestrutura_id')
->leftJoin('cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id')
->where('cadastro_lotacao.usuario_id', $id)
->whereNull('cadastro_lotacao.deleted_at')
->selectRaw("
cadastro_unidade.id as id,
cadastro_unidade.nome_fantasia
")
->distinct()
->orderBy('cadastro_unidade.nome_fantasia')
->get();
return [
'form' => [
'info_profissional' => [
'unidades' => $unidades,
'infraestruturas' => [],
'lotacoes' => [],
'ocupacoes' => [],
'especialidades' => [],
],
],
];
}
public static function getInfraestruturaProfissional($id, $unidadeId)
{
$infraestruturas = DB::table('cadastro_lotacao')
->leftJoin('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_lotacao.infraestrutura_id')
->leftJoin('cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id')
->where('cadastro_lotacao.usuario_id', $id)
->where('cadastro_infraestrutura.unidade_id', $unidadeId)
->whereNull('cadastro_lotacao.deleted_at')
->selectRaw("
cadastro_infraestrutura.id as id,
COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) as nome
")
->distinct()
->get();
return [
'form' => [
'info_profissional' => [
'infraestruturas' => $infraestruturas,
],
],
];
}
public static function getOcupacaoProfissional($id, $infraestruturaId)
{
$ocupacoes = DB::table('cadastro_lotacao')
->leftJoin('sigtap.ocupacao as ocupacao', 'ocupacao.id', 'cadastro_lotacao.ocupacao_id')
->where('cadastro_lotacao.usuario_id', $id)
->where('cadastro_lotacao.infraestrutura_id', $infraestruturaId)
->whereNull('cadastro_lotacao.deleted_at')
->selectRaw("
ocupacao.id as id,
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as nome,
cadastro_lotacao.id as lotacao_id
")
->distinct()
->get();
return [
'form' => [
'info_profissional' => [
'ocupacoes' => $ocupacoes,
]
],
];
}
public static function getEspecialidadeProfissional($ocupacaoId)
{
$especialidades = DB::table('cadastro_especialidade')
->where('ativo', true)
->where('ocupacao_id', $ocupacaoId)
->select('id', 'nome')
->orderBy('nome')
->get();
return [
'form' => [
'info_profissional' => [
'especialidades' => $especialidades,
]
],
];
}
public static function getAgendamentoExameNoPrazoDeValidade($pacienteId, $exameId)
{
$exame = Exame::findOrFail($exameId);
if (!is_null($exame->validade)) {
if ($exame->tipo_id === Tipo::LABORATORIAL) {
return DB::table('exame_laboratorial_agendamento_exame as agendamento_exame')
->join('exame_laboratorial_agendamento_exame_status as status', 'status.id', 'agendamento_exame.status_id')
->join('exame_laboratorial_agendamento as agendamento', 'agendamento.id', 'agendamento_exame.agendamento_id')
->where('agendamento_exame.exame_id', $exameId)
->where('agendamento.paciente_id', $pacienteId)
->whereRaw("TIMESTAMPDIFF(DAY, agendamento.data, CURRENT_DATE) <= {$exame->validade}")
->selectRaw("
TRUE as is_origem_exame_laboratorial,
agendamento_exame.exame_id,
DATE_FORMAT(agendamento.data, '%d/%m/%Y') as solicitacao_data,
status.descricao as status_nome,
TRUE as dentro_da_validade,
DATE_FORMAT(DATE_ADD(agendamento.data, INTERVAL {$exame->validade} DAY), '%d/%m/%Y') as data_validade
")
->get();
}
}
return [];
}
private static function getCotaUnidadeQuantidade()
{
$dataAtual = Carbon::now()->format('Y-m-d');
$cotaUnidade = Cota::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('cota_tipo_id', TipoCota::QUANTIDADE)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->first();
$cotaUnidadeValor = Cota::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('cota_tipo_id', TipoCota::VALOR)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->first();
if ($cotaUnidadeValor) {
return true;
}
if ($cotaUnidade) {
$totalUnidade = $cotaUnidade->cota_quantidade;
$saldoEnviado = CotaTransferencia::where('origem_infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('cota_tipo_id', TipoCota::QUANTIDADE)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('origem_inicio', '<=', $dataAtual)
->where('origem_fim', '>=', $dataAtual)
->sum('destino_cota_quantidade');
$saldoRecebido = CotaTransferencia::where('destino_infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('cota_tipo_id', TipoCota::QUANTIDADE)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('origem_inicio', '<=', $dataAtual)
->where('origem_fim', '>=', $dataAtual)
->sum('destino_cota_quantidade');
$cotaUtilizada = AgendamentoExame::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->whereHas('Agendamento', function ($query) {
$query->whereIn('status_id', [
StatusAgendamentoLaboratorio::AGENDADO,
StatusAgendamentoLaboratorio::REALIZADO,
StatusAgendamentoLaboratorio::PENDENTE_ASSINATURA,
StatusAgendamentoLaboratorio::ASSINADO,
StatusAgendamentoLaboratorio::NOVA_COLETA,
StatusAgendamentoLaboratorio::PENDENTE_ENTREGA,
StatusAgendamentoLaboratorio::ENTREGUE,
]);
})
->where('data', '>=', $cotaUnidade->inicio)
->where('data', '<=', $cotaUnidade->fim)
->count('id') ?? 0;
$inicio = Carbon::createFromFormat('Y-m-d', $cotaUnidade->inicio)->startOfDay();
$fim = Carbon::createFromFormat('Y-m-d', $cotaUnidade->fim)->endOfDay();
$prontoAtendimento = DB::table('pronto_atendimento_pedido_exame_item')
->join('pronto_atendimento_pedido_exame', 'pronto_atendimento_pedido_exame.id', '=', 'pronto_atendimento_pedido_exame_item.pedido_exame_id')
->join('cadastro_lotacao', 'cadastro_lotacao.id', '=', 'pronto_atendimento_pedido_exame.created_lotacao_id')
->join('parametrizacao_exame', 'parametrizacao_exame.id', '=', 'pronto_atendimento_pedido_exame_item.exame_id')
->where('parametrizacao_exame.tipo_id', Tipo::LABORATORIAL)
->where('pronto_atendimento_pedido_exame_item.status_id', StatusExame::REALIZADO)
->whereNull('pronto_atendimento_pedido_exame_item.deleted_at')
->where('cadastro_lotacao.infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->whereBetween('pronto_atendimento_pedido_exame_item.created_at', [$inicio, $fim])
->count('pronto_atendimento_pedido_exame_item.id');
$cotaUtilizada = $cotaUtilizada + $prontoAtendimento;
$totalCota = (($totalUnidade - $saldoEnviado) + $saldoRecebido);
$cotaExcedida = $cotaUtilizada > $totalCota;
return $cotaExcedida;
}
return true;
}
private static function getCotaUnidadeValor()
{
$dataAtual = Carbon::now()->format('Y-m-d');
$cotaUnidade = Cota::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('cota_tipo_id', TipoCota::VALOR)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->first();
$cotaUnidadeValor = Cota::where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('cota_tipo_id', TipoCota::VALOR)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->first();
if ($cotaUnidadeValor) {
return true;
}
if ($cotaUnidade) {
$totalUnidade = $cotaUnidade->cota_valor;
$saldoEnviado = CotaTransferencia::where('origem_infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('cota_tipo_id', TipoCota::VALOR)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('origem_inicio', '<=', $dataAtual)
->where('origem_fim', '>=', $dataAtual)
->sum('destino_cota_valor');
$saldoRecebido = CotaTransferencia::where('destino_infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('cota_tipo_id', TipoCota::VALOR)
->where('unidade_tipo_id', TipoUnidade::UNIDADE_SOLICITANTE)
->where('origem_inicio', '<=', $dataAtual)
->where('origem_fim', '>=', $dataAtual)
->sum('destino_cota_valor');
$cotaUtilizada = AgendamentoExameExame::whereIn('status_id', [
StatusAgendamentoLaboratorio::AGENDADO,
StatusAgendamentoLaboratorio::REALIZADO,
StatusAgendamentoLaboratorio::PENDENTE_ASSINATURA,
StatusAgendamentoLaboratorio::ASSINADO,
StatusAgendamentoLaboratorio::NOVA_COLETA,
StatusAgendamentoLaboratorio::PENDENTE_ENTREGA,
StatusAgendamentoLaboratorio::ENTREGUE,
])
->whereHas('Agendamento', function ($query) use ($cotaUnidade) {
$query->where('infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id)
->where('data', '>=', $cotaUnidade->inicio)
->where('data', '<=', $cotaUnidade->fim);
})
->sum('valor') ?? 0;
$inicio = Carbon::createFromFormat('Y-m-d', $cotaUnidade->inicio)->startOfDay();
$fim = Carbon::createFromFormat('Y-m-d', $cotaUnidade->fim)->endOfDay();
$prontoAtendimento = DB::table('pronto_atendimento_pedido_exame_item')
->join('pronto_atendimento_pedido_exame', 'pronto_atendimento_pedido_exame.id', '=', 'pronto_atendimento_pedido_exame_item.pedido_exame_id')
->join('cadastro_lotacao', 'cadastro_lotacao.id', '=', 'pronto_atendimento_pedido_exame.created_lotacao_id')
->join('parametrizacao_exame', 'parametrizacao_exame.id', '=', 'pronto_atendimento_pedido_exame_item.exame_id')
->where('parametrizacao_exame.tipo_id', Tipo::LABORATORIAL)
->where('pronto_atendimento_pedido_exame_item.status_id', StatusExame::REALIZADO)
->whereNull('pronto_atendimento_pedido_exame_item.deleted_at')
->where('cadastro_lotacao.infraestrutura_id', request()->infraestrutura_id)
->whereBetween('pronto_atendimento_pedido_exame_item.created_at', [$inicio, $fim])
->selectRaw('FORMAT(SUM(pronto_atendimento_pedido_exame_item.valor_exame), 2, "pt_BR") AS valor')
->value('valor');
$prontoAtendimento = str_replace(',', '.', str_replace('.', '', $prontoAtendimento));
$cotaUtilizada = floatval($cotaUtilizada) + floatval($prontoAtendimento);
$totalCota = (($totalUnidade - $saldoEnviado) + $saldoRecebido);
$cotaExcedida = $cotaUtilizada > $totalCota;
return $cotaExcedida;
}
return true;
}
private static function getCotaExamePeriodoQuantidade($queryExames)
{
$exames = $queryExames->get();
if ($exames->isEmpty()) {
return [];
}
$examesSemCota = [];
$dataAtual = Carbon::now()->format('Y-m-d');
foreach ($exames as $exame) {
$exameId = $exame->id;
$cotaExames = CotaExamePeriodo::where('exame_id', $exameId)
->where('cota_tipo_id', TipoCota::QUANTIDADE)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->get();
$cotaValor = CotaExamePeriodo::where('exame_id', $exameId)
->where('cota_tipo_id', TipoCota::VALOR)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->first();
if ($cotaValor) {
$examesSemCota[] = $exameId;
continue;
}
if ($exame->regulacao_tipo_id) {
$examesSemCota[] = $exameId;
continue;
}
$temCota = false;
foreach ($cotaExames as $cotaExame) {
$quantidadeUtilizada = AgendamentoExame::where('data', '>=', $cotaExame->inicio)
->where('data', '<=', $cotaExame->fim)
->whereHas('agendamentoExame', function ($query) use ($cotaExame) {
$query->where('exame_id', $cotaExame->exame_id)
->whereIn('status_id', [
StatusAgendamentoLaboratorio::AGENDADO,
StatusAgendamentoLaboratorio::REALIZADO,
StatusAgendamentoLaboratorio::PENDENTE_ASSINATURA,
StatusAgendamentoLaboratorio::ASSINADO,
StatusAgendamentoLaboratorio::NOVA_COLETA,
StatusAgendamentoLaboratorio::PENDENTE_ENTREGA,
StatusAgendamentoLaboratorio::ENTREGUE,
]);
})
->count('id') ?? 0;
$inicio = Carbon::createFromFormat('Y-m-d', $cotaExame->inicio)->startOfDay();
$fim = Carbon::createFromFormat('Y-m-d', $cotaExame->fim)->endOfDay();
$prontoAtendimento = DB::table('pronto_atendimento_pedido_exame_item')
->join('pronto_atendimento_pedido_exame', 'pronto_atendimento_pedido_exame.id', '=', 'pronto_atendimento_pedido_exame_item.pedido_exame_id')
->join('parametrizacao_exame', 'parametrizacao_exame.id', '=', 'pronto_atendimento_pedido_exame_item.exame_id')
->where('parametrizacao_exame.tipo_id', Tipo::LABORATORIAL)
->where('pronto_atendimento_pedido_exame_item.status_id', StatusExame::REALIZADO)
->whereNull('pronto_atendimento_pedido_exame_item.deleted_at')
->where('pronto_atendimento_pedido_exame_item.exame_id', $cotaExame->exame_id)
->whereBetween('pronto_atendimento_pedido_exame_item.created_at', [$inicio, $fim])
->count('pronto_atendimento_pedido_exame_item.id');
$quantidadeUtilizada += $prontoAtendimento;
if ($quantidadeUtilizada < $cotaExame->cota_quantidade) {
$temCota = true;
break;
}
}
if (!$temCota) {
$examesSemCota[] = $exameId;
}
}
return $examesSemCota;
}
private static function getCotaExamePeriodoValor($queryExames)
{
$exames = [];
$exames = $queryExames->get();
if ($exames->isEmpty()) {
return [];
}
$dataAtual = Carbon::now()->format('Y-m-d');
foreach ($exames as $exame) {
$exameId = $exame->id;
$cotaExames = CotaExamePeriodo::where('exame_id', $exameId)
->where('cota_tipo_id', TipoCota::VALOR)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->get();
$cotaQuantidade = CotaExamePeriodo::where('exame_id', $exameId)
->where('cota_tipo_id', TipoCota::QUANTIDADE)
->where('inicio', '<=', $dataAtual)
->where('fim', '>=', $dataAtual)
->first();
if ($cotaQuantidade) {
$examesSemCota[] = $exameId;
continue;
}
if ($exame->regulacao_tipo_id) {
$examesSemCota[] = $exameId;
continue;
}
$temCota = false;
$valorUtilizado = 0;
foreach ($cotaExames as $cotaExame) {
$inicio = Carbon::createFromFormat('Y-m-d', $cotaExame->inicio)->startOfDay();
$fim = Carbon::createFromFormat('Y-m-d', $cotaExame->fim)->endOfDay();
$valorUtilizadoAgendamento = AgendamentoExameExame::where('exame_id', $cotaExame->exame_id)
->whereIn('status_id', [
StatusAgendamentoLaboratorio::AGENDADO,
StatusAgendamentoLaboratorio::REALIZADO,
StatusAgendamentoLaboratorio::PENDENTE_ASSINATURA,
StatusAgendamentoLaboratorio::ASSINADO,
StatusAgendamentoLaboratorio::NOVA_COLETA,
StatusAgendamentoLaboratorio::PENDENTE_ENTREGA,
StatusAgendamentoLaboratorio::ENTREGUE,
])
->whereHas('Agendamento', function ($query) use ($cotaExame) {
$query->where('laboratorio_infraestrutura_id', request()->laboratorio_infraestrutura_id)
->where('data', '>=', $cotaExame->inicio)
->where('data', '<=', $cotaExame->fim);
})
->sum('valor') ?? 0;
$prontoAtendimento = DB::table('pronto_atendimento_pedido_exame_item')
->join('pronto_atendimento_pedido_exame', 'pronto_atendimento_pedido_exame.id', '=', 'pronto_atendimento_pedido_exame_item.pedido_exame_id')
->join('parametrizacao_exame', 'parametrizacao_exame.id', '=', 'pronto_atendimento_pedido_exame_item.exame_id')
->where('parametrizacao_exame.tipo_id', Tipo::LABORATORIAL)
->where('pronto_atendimento_pedido_exame_item.status_id', StatusExame::REALIZADO)
->whereNull('pronto_atendimento_pedido_exame_item.deleted_at')
->where('pronto_atendimento_pedido_exame_item.exame_id', $cotaExame->exame_id)
->whereBetween('pronto_atendimento_pedido_exame_item.created_at', [$inicio, $fim])
->selectRaw('FORMAT(SUM(pronto_atendimento_pedido_exame_item.valor_exame), 2, "pt_BR") AS valor')
->value('valor');
$prontoAtendimento = str_replace(',', '.', str_replace('.', '', $prontoAtendimento));
$valorUtilizado += floatval($valorUtilizadoAgendamento) + floatval($prontoAtendimento);
if ($valorUtilizado < $cotaExame->cota_valor) {
$temCota = true;
break;
}
}
if (!$temCota) {
$examesSemCota[] = $exameId;
}
}
return $examesSemCota;
}
private static function isSupervisor()
{
return ParametrizacaoSupervisor::where('usuario_id', self::getCurrentLotacao()->usuario_id)->exists();
}
}