Files
rkm-conectasus-ci-sandbox/api/app/Http/Requests/ProntoAtendimento/Atendimento/MedicoRequest.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

1719 lines
58 KiB
PHP

<?php
namespace App\Http\Requests\ProntoAtendimento\Atendimento;
use App\Enums\Cadastro\Estabelecimento\SetorTipo;
use App\Enums\Cadastro\Medicamento\TipoPosologia;
use App\Enums\Cadastro\Medicamento\ViaAdministracao;
use App\Enums\Cadastro\SujeitoAtencao\FatorRisco;
use App\Enums\Cadastro\UnidadeMedida;
use App\Enums\Geral\DocumentoTipo;
use App\Enums\Parametrizacao\ProntoAtendimento\TipoAtendimento;
use App\Enums\ProntoAtendimento\Atendimento\Desfecho;
use App\Enums\ProntoAtendimento\Atendimento\Medico\AtestadoModelo;
use App\Enums\ProntoAtendimento\Atendimento\Medico\DeclaracaoComparecimentoTipo;
use App\Enums\ProntoAtendimento\Raat\CausaAcidente;
use App\Enums\ProntoAtendimento\Raat\Diagnostico;
use App\Enums\ProntoAtendimento\Raat\ParteCorpoAtingida;
use App\Enums\Sigtap\Procedimento as ProcedimentoEnum;
use App\Http\Requests\FormRequest;
use App\Models\Cadastro\Estabelecimento\CentroCusto;
use App\Models\Cadastro\Medicamento\Medicamento;
use App\Models\Cadastro\SujeitoAtencao\Lotacao;
use App\Models\ProntoAtendimento\Atendimento\Atendimento;
use App\Models\ProntoAtendimento\Parametrizacao\AtendimentoMedico as ParametrizacaoAtendimentoMedico;
use App\Models\Sigtap\Procedimento;
use App\Rules\Cns;
use App\Rules\CnsTermoValido;
use App\Rules\Cpf;
use App\Rules\NomeCompleto;
use App\Services\Parametrizacao\ProntoAtendimento\AtendimentoMedicoService as ParametrizacaoAtendimentoMedicoService;
use App\Services\Sigtap\ProcedimentoValidationService;
use App\Utils\RequestUtil;
use Carbon\Carbon;
use Illuminate\Validation\Rule;
class MedicoRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
switch ($this->method()) {
case 'POST': {
return $this->getPostRules();
}
default: {
return [];
}
}
}
private function getPostRules()
{
$atendimento = is_numeric($this->atendimento_id ?? null)
? Atendimento::find($this->atendimento_id)
: null;
$rules = [
'plantao_id' => [
'required',
'integer'
],
'atendimento_id' => [
'required',
'integer',
'exists:\App\Models\ProntoAtendimento\Atendimento\Atendimento,id'
],
];
if (is_null($atendimento)) {
return $rules;
}
$centroCustoLogado = $this->getCentroCustoLogado();
$parametrizacao = ParametrizacaoAtendimentoMedicoService::get($centroCustoLogado->infraestrutura_id);
$isAtendimentoSimples = $parametrizacao->tipo_id === TipoAtendimento::SIMPLES;
$isReavaliacao = $atendimento->atendimentosMedico()->get()->isNotEmpty();
$isPrimeiroAtendimentoSimples = !$isReavaliacao && $isAtendimentoSimples;
$isPrimeiroAtendimentoEstruturado = !$isReavaliacao && !$isAtendimentoSimples;
$raatObrigatorio = !is_null($this->desfecho['id'] ?? null) && $atendimento->faa->isRaatAberta;
$procedimentoPadrao = ParametrizacaoAtendimentoMedico::first()->procedimento_padrao ?? null;
$rules = array_merge($rules, [
'classificacao_risco_id' => [
'required',
'integer',
'exists:\App\Models\ProntoAtendimento\ClassificacaoRisco\ClassificacaoRisco,id'
],
'evolucao' => [
'nullable',
Rule::requiredIf(fn () => $isReavaliacao),
'string',
'max:5000',
],
'atendimento_geral' => [
'nullable',
Rule::requiredIf(fn () => $isPrimeiroAtendimentoSimples),
'string',
'max:5000',
],
'queixa_principal_duracao' => [
'nullable',
($isPrimeiroAtendimentoEstruturado
? 'required_without_all:'
. 'historia,'
. 'exame_fisico,'
. 'diagnostico,'
. 'conduta'
: null),
'string',
'max:5000',
],
'historia' => [
'nullable',
($isPrimeiroAtendimentoEstruturado
? 'required_without_all:'
. 'queixa_principal_duracao,'
. 'exame_fisico,'
. 'diagnostico,'
. 'conduta'
: null),
'string',
'max:5000',
],
'exame_fisico' => [
'nullable',
($isPrimeiroAtendimentoEstruturado
? 'required_without_all:'
. 'queixa_principal_duracao,'
. 'historia,'
. 'diagnostico,'
. 'conduta'
: null),
'string',
'max:5000',
],
'diagnostico' => [
'nullable',
($isPrimeiroAtendimentoEstruturado
? 'required_without_all:'
. 'queixa_principal_duracao,'
. 'historia,'
. 'exame_fisico,'
. 'conduta'
: null),
'string',
'max:5000',
],
'conduta' => [
'nullable',
($isPrimeiroAtendimentoEstruturado
? 'required_without_all:'
. 'queixa_principal_duracao,'
. 'historia,'
. 'exame_fisico,'
. 'diagnostico'
: null),
'string',
'max:5000',
],
'observacoes' => [
'nullable',
'string',
'max:5000',
],
'dor_toracica_resultado_eletrocardiograma' => [
'nullable',
'string',
'max:5000',
],
'dor_toracica_protocolo_finalizado' => [
'nullable',
'boolean',
],
'dor_toracica_protocolo_tem_prosseguimento' => [
'nullable',
'boolean',
],
'dor_toracica_tem_contra_indicacao_trombolitico' => [
'nullable',
'boolean',
],
'dor_toracica_contra_indicacao_trombolitico_motivo' => [
'nullable',
'string',
'max:200',
],
'dor_toracica_sinais_instabilidade' => [
'present',
'array',
],
'dor_toracica_sinais_instabilidade.*' => [
'present',
'integer',
],
'doencas_cronicas' => [
'nullable',
'string',
'max:3000',
],
'cid_id' => [
'nullable',
Rule::requiredIf(fn () => !$isReavaliacao),
'integer',
],
'orientacoes' => [
'nullable',
'string',
'between:2,3000',
],
'centro_custo_id_para' => [
'nullable',
Rule::requiredIf(fn () => !$this->hasFinalizacao() && !$this->fromObservacao($atendimento)),
'integer',
'exists:\App\Models\Cadastro\Estabelecimento\CentroCusto,id',
],
'observacoes_enfermagem' => [
'nullable',
'string',
'max:5000',
],
'data_hora_proxima_reavaliacao' => [
'bail',
'nullable',
Rule::requiredIf(fn () =>
$this->fromObservacao($atendimento) && is_null($this->desfecho['id'] ?? null)
|| (
$this->isCentroCustoParaObservacao($this->centro_custo_id_para)
&& !$this->fromObservacao($atendimento)
&& is_null($this->desfecho['id'] ?? null)
)
),
'date_format:d/m/Y H:i',
function ($attribute, $value, $fail) {
if (!$value) return;
$dataAtual = Carbon::now();
$dataLimite = $dataAtual->copy()->modify('+24 hours');
$dataProximaReavaliacao = Carbon::createFromFormat('d/m/Y H:i', $value);
if ($dataProximaReavaliacao <= $dataAtual) {
$fail("Data/hora da próxima reavaliação deve ser maior "
. "que {$dataAtual->format('d/m/Y H:i')}.");
}
else if ($dataProximaReavaliacao > $dataLimite) {
$fail("Data/hora da próxima reavaliação deve ser menor ou "
. "igual a {$dataLimite->format('d/m/Y H:i')}.");
}
},
],
'fatores_risco' => [
'nullable',
'array',
],
'fatores_risco.*' => [
'integer',
'exists:\App\Models\Cadastro\SujeitoAtencao\FatorRisco,id',
],
'fator_risco_outro' => [
'nullable',
Rule::requiredIf(fn () => in_array(FatorRisco::OUTRO, $this->fatores_risco ?? [])),
'string',
'max:100',
],
'escala_coma_glasgow' => [
'nullable',
'array',
],
'escala_coma_glasgow.*.abertura_ocular_id' => [
'required',
'integer',
'exists:\App\Models\Geral\GlasgowAberturaOcular,id'
],
'escala_coma_glasgow.*.resposta_verbal_id' => [
'required',
'integer',
'exists:\App\Models\Geral\GlasgowRespostaVerbal,id'
],
'escala_coma_glasgow.*.resposta_motora_id' => [
'required',
'integer',
'exists:\App\Models\Geral\GlasgowRespostaMotora,id'
],
'escala_coma_glasgow.*.reatividade_pupilar_id' => [
'required',
'integer',
'exists:\App\Models\Geral\GlasgowReatividadePupilar,id'
],
'escala_coma_glasgow.*.observacao' => [
'nullable',
'string',
'max:2500'
],
]);
return array_merge(
$rules,
$this->getPostAlergiaRules(),
$this->getPostMedicamentosUsoRules(),
$this->getPostSinaisVitaisRules(),
$this->getPostAvaliacaoAntropometricaRules(),
$this->getPostGestacaoRules(),
$this->getPostAtestadoRules(),
$this->getPostReceitaMedicaRules(),
$this->getPostPrescricaoInternaRules(),
$this->getPostEncaminhamentosRules(),
$this->getPostDeclaracoesComparecimentoRules(),
$this->getPostRaatRules($raatObrigatorio),
$this->getPostProcedimentosRules($isReavaliacao, $atendimento, $procedimentoPadrao),
$this->getPostPedidoExameRules($atendimento),
$this->getPostServicosEnfermagemRules($atendimento),
$this->getPostDesfechoRules($atendimento),
$this->getPostFinalizacaoRules($atendimento, $raatObrigatorio),
);
}
private function fromObservacao($atendimento)
{
return $atendimento->fila->centroCusto->setor->tipo_id === SetorTipo::OBSERVACAO;
}
private function isCentroCustoParaObservacao($centroCustoIdPara)
{
if (is_null($centroCustoIdPara)) {
return false;
}
$centroCustoPara = CentroCusto::findOrFail($centroCustoIdPara);
return $centroCustoPara->setor->tipo_id === SetorTipo::OBSERVACAO;
}
private function getPostAlergiaRules()
{
return [
'alergias' => [
'nullable',
'array',
],
'alergias.*.alergia_id' => [
'required',
'integer',
'exists:\App\Models\Cadastro\SujeitoAtencao\Alergia,id',
],
'alergias.*.criticidade_id' => [
'required',
'integer',
'exists:\App\Models\Cadastro\SujeitoAtencao\AlergiaCriticidade,id',
],
'alergias.*.reacoes_observacoes' => [
'nullable',
'string',
'between:3,100',
],
];
}
private function getPostMedicamentosUsoRules()
{
return [
'medicamentos_uso' => [
'nullable',
'string',
'max:3000',
],
];
}
private function getPostSinaisVitaisRules()
{
$rules = [
'sinais_vitais' => [
'nullable',
'array',
],
'sinais_vitais.*.pa_unidade_medida_id' => [
'nullable',
'required_with:sinais_vitais.*.pa',
'integer',
Rule::in([UnidadeMedida::MILIMETROS_DE_MERCURIO, UnidadeMedida::CENTIMETROS_DE_MERCURIO]),
],
'sinais_vitais.*.glicemia' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.temperatura,'
. 'sinais_vitais.*.pulso,'
. 'sinais_vitais.*.respiracao,'
. 'sinais_vitais.*.saturacao,'
. 'sinais_vitais.*.intensidade_dor,'
. 'sinais_vitais.*.cintura',
'integer',
'max:999',
],
'sinais_vitais.*.temperatura' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.glicemia,'
. 'sinais_vitais.*.pulso,'
. 'sinais_vitais.*.respiracao,'
. 'sinais_vitais.*.saturacao,'
. 'sinais_vitais.*.intensidade_dor,'
. 'sinais_vitais.*.cintura',
'numeric',
'max:99.9',
],
'sinais_vitais.*.pulso' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.glicemia,'
. 'sinais_vitais.*.temperatura,'
. 'sinais_vitais.*.respiracao,'
. 'sinais_vitais.*.saturacao,'
. 'sinais_vitais.*.intensidade_dor,'
. 'sinais_vitais.*.cintura',
'integer',
'max:999',
],
'sinais_vitais.*.respiracao' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.glicemia,'
. 'sinais_vitais.*.temperatura,'
. 'sinais_vitais.*.pulso,'
. 'sinais_vitais.*.saturacao,'
. 'sinais_vitais.*.intensidade_dor,'
. 'sinais_vitais.*.cintura',
'integer',
'max:99',
],
'sinais_vitais.*.saturacao' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.glicemia,'
. 'sinais_vitais.*.temperatura,'
. 'sinais_vitais.*.pulso,'
. 'sinais_vitais.*.respiracao,'
. 'sinais_vitais.*.intensidade_dor,'
. 'sinais_vitais.*.cintura',
'integer',
'between:1,100',
],
'sinais_vitais.*.intensidade_dor' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.glicemia,'
. 'sinais_vitais.*.temperatura,'
. 'sinais_vitais.*.pulso,'
. 'sinais_vitais.*.respiracao,'
. 'sinais_vitais.*.saturacao,'
. 'sinais_vitais.*.cintura',
'integer',
'between:1,10',
],
'sinais_vitais.*.cintura' => [
'nullable',
'required_without_all:'
. 'sinais_vitais.*.pa,'
. 'sinais_vitais.*.glicemia,'
. 'sinais_vitais.*.temperatura,'
. 'sinais_vitais.*.pulso,'
. 'sinais_vitais.*.respiracao,'
. 'sinais_vitais.*.saturacao,'
. 'sinais_vitais.*.intensidade_dor,',
'integer',
'max:999',
],
];
foreach (($this->sinais_vitais ?? []) as $i => $sinalVital) {
$rules["sinais_vitais.{$i}.pa"] = [
'nullable',
'required_without_all:'
. "sinais_vitais.{$i}.glicemia,"
. "sinais_vitais.{$i}.temperatura,"
. "sinais_vitais.{$i}.pulso,"
. "sinais_vitais.{$i}.respiracao,"
. "sinais_vitais.{$i}.saturacao,"
. "sinais_vitais.{$i}.intensidade_dor,"
. "sinais_vitais.{$i}.cintura'",
'string',
];
if ($sinalVital['pa_unidade_medida_id'] === UnidadeMedida::MILIMETROS_DE_MERCURIO) {
$rules["sinais_vitais.{$i}.pa"][] = 'regex:/^[0-9]{2,3}\/+[0-9]{2,3}$/';
}
else if ($sinalVital['pa_unidade_medida_id'] === UnidadeMedida::CENTIMETROS_DE_MERCURIO) {
$rules["sinais_vitais.{$i}.pa"][] = 'regex:/^[0-9]{1,2}\/+[0-9]{1,2}$/';
}
}
return $rules;
}
private function getPostAvaliacaoAntropometricaRules()
{
$rules = [
'avaliacao_antropometrica' => [
'nullable',
'array',
],
];
if (is_array($this->avaliacao_antropometrica ?? null)) {
$rules = array_merge($rules, [
'avaliacao_antropometrica.massa' => [
'nullable',
'required_without:avaliacao_antropometrica.altura',
'numeric',
'max:999.999',
],
'avaliacao_antropometrica.massa_unidade_medida_id' => [
'nullable',
'required_with:avaliacao_antropometrica.massa',
'integer',
Rule::in([UnidadeMedida::GRAMAS, UnidadeMedida::QUILOGRAMAS]),
],
'avaliacao_antropometrica.altura' => [
'nullable',
'required_without:avaliacao_antropometrica.massa',
'numeric',
'max:999.99',
],
'avaliacao_antropometrica.altura_unidade_medida_id' => [
'nullable',
'required_with:avaliacao_antropometrica.altura',
'integer',
Rule::in([UnidadeMedida::CENTIMETROS, UnidadeMedida::METROS]),
],
'avaliacao_antropometrica.altura_tipo_medida_id' => [
'nullable',
'required_with:avaliacao_antropometrica.altura',
'integer',
'exists:\App\Models\Geral\TipoMedidaAltura,id',
],
]);
}
return $rules;
}
private function getPostGestacaoRules()
{
$rules = [
'gestacao' => [
'nullable',
'array',
],
];
if (is_array($this->gestacao ?? null)) {
$rules = array_merge($rules, [
'gestacao.gestante' => [
'required',
'boolean',
],
'gestacao.dum' => [
'nullable',
'date_format:Y-m-d',
'before_or_equal:now',
],
]);
}
return $rules;
}
private function getPostAtestadoRules()
{
$modeloId = (int) ($this->atestado['modelo_id'] ?? AtestadoModelo::PADRAO);
$rules = [
'atestado' => [
'nullable',
'array'
],
];
if (is_array($this->atestado ?? null)) {
$rules = array_merge($rules, [
'atestado.modelo_id' => [
'required',
'integer',
Rule::in([
AtestadoModelo::PADRAO,
AtestadoModelo::PERIODO_MANHA,
AtestadoModelo::PERIODO_TARDE,
AtestadoModelo::PERIODO_NOITE,
AtestadoModelo::QUANTIDADE_HORAS,
]),
],
'atestado.dias' => [
'nullable',
Rule::requiredIf(fn () => $modeloId === AtestadoModelo::PADRAO),
'integer',
'max:999'
],
'atestado.quantidade_horas' => [
'nullable',
Rule::requiredIf(fn () => $modeloId === AtestadoModelo::QUANTIDADE_HORAS),
'integer',
'between:1,24',
],
'atestado.horario_inicial' => [
'nullable',
Rule::requiredIf(fn () => $modeloId === AtestadoModelo::QUANTIDADE_HORAS),
'date_format:H:i',
],
'atestado.documento_tipo_id' => [
'required',
'integer',
'exists:\App\Models\Geral\DocumentoTipo,id'
],
'atestado.documento_numero' => [
'required',
($this->atestado['paciente'] == 1 ? 'digits_between:2,20' : ''),
],
]);
}
return $rules;
}
private function getPostReceitaMedicaRules()
{
$rules = [
'receitas_medicas_assinadas' => [
'present',
'array',
],
'receitas_medicas_assinadas.*' => [
'array',
],
'receitas_medicas_assinadas.*.*' => [
'string',
],
'receita_medica' => [
'nullable',
'array'
],
];
if (is_array($this->receita_medica ?? null)) {
$rules["receita_medica.is_assinada"] = [
'required',
'boolean',
];
$rules["receita_medica.medicamentos"] = [
'present',
'array',
];
if (is_array($this->receita_medica['medicamentos'] ?? null)) {
foreach ($this->receita_medica['medicamentos'] as $i => $params) {
$rules["receita_medica.medicamentos.{$i}.medicamento_id"] = [
'nullable',
'integer',
];
$rules["receita_medica.medicamentos.{$i}.tipo_aplicacao"] = [
'required',
'string',
Rule::in(['dose_unica', 'uso_continuo', 'livre', 'padrao'])
];
if (!is_numeric($params['medicamento_id'] ?? null)
|| !is_string($params['tipo_aplicacao'] ?? null)
) {
continue;
}
$rules["receita_medica.medicamentos.{$i}.via_administracao_outras"] = [
'nullable',
Rule::requiredIf(fn () => (Medicamento::find($params['medicamento_id'])
->via_administracao_id ?? null) === ViaAdministracao::OUTRAS
),
'string',
'max:100'
];
$usoContinuo = $params['tipo_aplicacao'] === 'uso_continuo';
$livre = $params['tipo_aplicacao'] === 'livre';
$padrao = $params['tipo_aplicacao'] === 'padrao';
$rules["receita_medica.medicamentos.{$i}.tipo_posologia"] = [
'nullable',
Rule::requiredIf(fn () => $padrao || $usoContinuo),
Rule::in([TipoPosologia::FREQUENCIA, TipoPosologia::TURNO]),
'string',
];
$rules["receita_medica.medicamentos.{$i}.quantidade"] = [
'nullable',
Rule::requiredIf(fn () => !$livre),
'numeric',
'between:0.1,999',
];
if (is_string($params['tipo_posologia'] ?? null)) {
$posologiaPorFrequencia = $params['tipo_posologia'] === TipoPosologia::FREQUENCIA;
$posologiaPorTurno = $params['tipo_posologia'] === TipoPosologia::TURNO;
$rules["receita_medica.medicamentos.{$i}.intervalo_tempo"] = [
'nullable',
Rule::requiredIf(fn () => $posologiaPorFrequencia),
'integer',
'between:1,999',
];
$rules["receita_medica.medicamentos.{$i}.intervalo_medida_tempo_id"] = [
'nullable',
Rule::requiredIf(fn () => $posologiaPorFrequencia),
'integer',
'exists:\App\Models\Geral\MedidaTempo,id',
];
$rules["receita_medica.medicamentos.{$i}.turno_id"] = [
'nullable',
Rule::requiredIf(fn () => $posologiaPorTurno),
'integer',
'exists:\App\Models\Geral\Turno,id',
];
}
$rules["receita_medica.medicamentos.{$i}.durante_tempo"] = [
'nullable',
Rule::requiredIf(fn () => $padrao),
'between:1,999',
];
$rules["receita_medica.medicamentos.{$i}.durante_medida_tempo_id"] = [
'nullable',
Rule::requiredIf(fn () => $padrao),
'integer',
'exists:\App\Models\Geral\MedidaTempo,id',
];
$rules["receita_medica.medicamentos.{$i}.recomendacoes"] = [
'nullable',
'string',
'max:250',
];
$rules["receita_medica.medicamentos.{$i}.descricao"] = [
'nullable',
Rule::requiredIf(fn () => $livre),
'string',
'max:250',
];
$rules["receita_medica.medicamentos.{$i}.medicamento_manual"] = [
'nullable',
'string',
'max:500',
];
$rules["receita_medica.medicamentos.{$i}.prescricao_manual"] = [
'nullable',
'string',
'max:5000',
];
}
}
}
return $rules;
}
private function getPostPrescricaoInternaRules()
{
$rules = [
'prescricoes_internas' => [
'nullable',
'array',
],
];
if (is_array($this->prescricoes_internas ?? null)) {
foreach ($this->prescricoes_internas as $i => $prescricaoInterna) {
$rules["prescricoes_internas.{$i}.dose_unica"] = [
'required',
'boolean',
];
$rules["prescricoes_internas.{$i}"][] = function ($attribute, $value, $fail) use ($prescricaoInterna) {
$faltando = false;
if (!isset($prescricaoInterna['dose_unica'])) {
$faltando = true;
}
if (
isset($prescricaoInterna['dose_unica']) &&
RequestUtil::isAcceptedBoolean($prescricaoInterna['dose_unica']) &&
!((bool) $prescricaoInterna['dose_unica'])
) {
if (
empty($prescricaoInterna['frequencia_quantidade_vezes']) ||
empty($prescricaoInterna['frequencia_tempo']) ||
empty($prescricaoInterna['frequencia_medida_tempo_id'])
) {
$faltando = true;
}
}
if (empty($prescricaoInterna['medicamentos']) || !is_array($prescricaoInterna['medicamentos'])) {
$faltando = true;
}
if ($faltando) {
$fail('Acessar a Prescrição Interna e preencher os campos corretamente.');
}
};
if (RequestUtil::isAcceptedBoolean($prescricaoInterna['dose_unica'] ?? null)
&& !((bool) $prescricaoInterna['dose_unica'])
) {
$rules["prescricoes_internas.{$i}.frequencia_quantidade_vezes"] = [
'required',
'integer',
'between:1,999',
];
$rules["prescricoes_internas.{$i}.frequencia_tempo"] = [
'required',
'integer',
'between:1,999',
];
$rules["prescricoes_internas.{$i}.frequencia_medida_tempo_id"] = [
'required',
'integer',
'exists:\App\Models\Geral\MedidaTempo,id',
];
}
$rules["prescricoes_internas.{$i}.observacoes"] = [
'nullable',
'string',
'max:250'
];
$rules["prescricoes_internas.{$i}.medicamentos"] = [
'required',
'array',
];
if (!is_array($prescricaoInterna['medicamentos'] ?? null)) {
continue;
}
foreach ($prescricaoInterna['medicamentos'] as $j => $params) {
$medicamento = is_numeric($params['medicamento_id'] ?? null)
? Medicamento::find($params['medicamento_id'])
: null;
$rules["prescricoes_internas.{$i}.medicamentos.{$j}.medicamento_id"] = [
'required',
'integer',
];
$rules["prescricoes_internas.{$i}.medicamentos.{$j}.unidade_medida_id"] = [
'nullable',
'integer',
];
$rules["prescricoes_internas.{$i}.medicamentos.{$j}.quantidade"] = [
'required',
'numeric',
'between:0.1,99',
];
$rules["prescricoes_internas.{$i}.medicamentos.{$j}.administracao"] = [
'nullable',
'string',
'max:3000',
];
if (is_null($medicamento)) {
continue;
}
$rules["prescricoes_internas.{$i}.medicamentos.{$j}.medicamento_id"][] =
function ($attribute, $value, $fail) use ($j, $prescricaoInterna) {
foreach ($prescricaoInterna['medicamentos'] as $k => $params) {
if ($j === $k || !isset($params['medicamento_id'])) {
continue;
}
if ($value == $params['medicamento_id']) {
$fail('O campo ' . $attribute . ' campo tem um valor duplicado.');
}
}
};
}
}
}
return $rules;
}
private function isPrescricaoDuplicada($medicamentos, $currentIndex)
{
$idsMedicamentosAtual = [];
foreach ($medicamentos as $params) {
if (!isset($params['medicamento_id'])) {
return false;
}
$idsMedicamentosAtual[] = $params['medicamento_id'];
}
foreach ($this->prescricoes_internas as $j => $prescricaoInterna) {
if ($currentIndex === $j) {
continue;
}
$idsMedicamentos = [];
foreach ($prescricaoInterna['medicamentos'] as $params) {
if (!isset($params['medicamento_id'])) {
continue 2;
}
$idsMedicamentos[] = $params['medicamento_id'];
}
if (count($idsMedicamentosAtual) === count($idsMedicamentos)
&& empty(array_diff($idsMedicamentosAtual, $idsMedicamentos))
) {
return true;
}
}
return false;
}
private function getPostEncaminhamentosRules()
{
return [
'encaminhamentos' => [
'nullable',
'array',
],
'encaminhamentos.*.urgente' => [
'required',
'boolean',
],
'encaminhamentos.*.ocupacao_id' => [
'required',
'integer',
'distinct',
'exists:\App\Models\Sigtap\Ocupacao,id',
],
'encaminhamentos.*.motivo' => [
'required',
'string',
'max:300',
],
'encaminhamentos.*.observacoes' => [
'nullable',
'string',
'max:300',
],
];
}
private function getPostDeclaracoesComparecimentoRules()
{
$rules = [
'declaracoes_comparecimento' => [
'nullable',
'array',
],
];
if (is_array($this->declaracoes_comparecimento ?? null)) {
foreach ($this->declaracoes_comparecimento as $i => $declaracaoComparecimento) {
$rules["declaracoes_comparecimento.{$i}.tipo_id"] = [
'required',
'integer',
'exists:\App\Models\ProntoAtendimento\Atendimento\Medico\DeclaracaoComparecimentoTipo,id',
];
$rules["declaracoes_comparecimento.{$i}.nome"] = [
Rule::requiredIf(fn () =>
($declaracaoComparecimento['tipo_id'] ?? null) == DeclaracaoComparecimentoTipo::ACOMPANHANTE),
'string',
'between:6,150',
($declaracaoComparecimento['tipo_id'] ?? null) == DeclaracaoComparecimentoTipo::ACOMPANHANTE
? new NomeCompleto
: null,
($declaracaoComparecimento['tipo_id'] ?? null) == DeclaracaoComparecimentoTipo::ACOMPANHANTE
? new CnsTermoValido(['attribute' => 'Acompanhante'])
: null,
];
$rules["declaracoes_comparecimento.{$i}.documento_tipo_id"] = [
'required',
'integer',
'exists:\App\Models\Geral\DocumentoTipo,id',
];
$rules["declaracoes_comparecimento.{$i}.documento_numero"] = [
'required',
'between:2,20',
$this->getDocumentoNumeroValidation($declaracaoComparecimento['documento_tipo_id'] ?? null)
];
$rules["declaracoes_comparecimento.{$i}.de"] = [
'required',
'date_format:Y-m-d H:i',
];
$rules["declaracoes_comparecimento.{$i}.ate"] = [
'required',
'date_format:Y-m-d H:i',
"after_or_equal:declaracoes_comparecimento.{$i}.de"
];
$rules["declaracoes_comparecimento.{$i}.motivo"] = [
'required',
'string',
'between:2,50',
];
}
}
return $rules;
}
private function getPostRaatRules($required)
{
if ($this->finalizacao && ($this->finalizacao['desfecho_id'] == Desfecho::EVASAO
|| $this->finalizacao['desfecho_id'] == Desfecho::OBITO)
) {
$required = false;
}
$rules = [
'raat' => [
'nullable',
Rule::requiredIf(fn () => $required),
'array',
],
];
if (is_array($this->raat ?? null)) {
$rules = array_merge($rules, [
'raat.agente_id' => [
'required',
'integer',
'exists:\App\Models\ProntoAtendimento\Raat\Agente,id',
],
'raat.partes_corpo_atingidas' => [
'required',
'array',
],
'raat.partes_corpo_atingidas.*' => [
'integer',
'exists:\App\Models\ProntoAtendimento\Raat\ParteCorpoAtingida,id',
],
'raat.parte_corpo_atingida_outras' => [
'nullable',
Rule::requiredIf(fn () => in_array(
ParteCorpoAtingida::OUTROS,
$this->raat['partes_corpo_atingidas'] ?? [])
),
'string',
'between:3,150',
],
'raat.causas_acidente' => [
'required',
'array',
],
'raat.causas_acidente.*' => [
'integer',
'exists:\App\Models\ProntoAtendimento\Raat\CausaAcidente,id',
],
'raat.causa_acidente_outras' => [
'nullable',
Rule::requiredIf(fn () => in_array(
CausaAcidente::OUTROS,
$this->raat['causas_acidente'] ?? [])
),
'string',
'between:3,150',
],
'raat.diagnosticos' => [
'required',
'array',
],
'raat.diagnosticos.*' => [
'integer',
'exists:\App\Models\ProntoAtendimento\Raat\Diagnostico,id',
],
'raat.diagnostico_outros' => [
'nullable',
Rule::requiredIf(fn () => in_array(
Diagnostico::OUTROS,
$this->raat['diagnosticos'] ?? [])
),
'string',
'between:3,150',
],
'raat.observacao' => [
'nullable',
'string',
'between:3,150',
],
'raat.classificacao_inicial_id' => [
'required',
'integer',
'exists:\App\Models\ProntoAtendimento\Raat\ClassificacaoInicial,id',
],
'raat.afastado' => [
'required',
'boolean',
]
]);
}
return $rules;
}
private function getDocumentoNumeroValidation($documentoTipoId)
{
switch ($documentoTipoId) {
case DocumentoTipo::CPF: {
return new Cpf;
}
case DocumentoTipo::CNS: {
return new Cns;
}
default: {
return null;
}
}
}
private function getPostProcedimentosRules($isReavaliacao, $atendimento, $procedimentoPadrao)
{
$rules = [
'procedimentos' => [
'nullable',
Rule::requiredIf(fn () => !$isReavaliacao && is_null($procedimentoPadrao)),
'array',
],
];
if (is_array($this->procedimentos ?? null)) {
foreach ($this->procedimentos as $i => $params) {
$procedimento = is_numeric($params['procedimento_id'] ?? null)
? Procedimento::find($params['procedimento_id'])
: null;
$rules["procedimentos.{$i}.procedimento_id"] = [
'required',
'integer',
Rule::notIn([
ProcedimentoEnum::AFERICAO_PRESSAO_ARTERIAL,
ProcedimentoEnum::GLICEMIA_CAPILAR,
]),
'exists:\App\Models\Sigtap\Procedimento,id',
];
if (is_null($procedimento)) {
continue;
}
$validation = new ProcedimentoValidationService($procedimento);
$rules["procedimentos.{$i}.procedimento_id"] = array_merge(
$rules["procedimentos.{$i}.procedimento_id"],
[
$this->getDuplicatedValidator($this->procedimentos, $i),
$this->getOnValidCompetenciaValidator($validation),
$this->getOcupacaoValidator($validation),
$this->getSexoValidator($validation, $atendimento),
$this->getIdadeValidator($validation, $atendimento),
]
);
if (is_numeric($params['quantidade'] ?? null)) {
$quantidade = $atendimento->procedimentos
->where('procedimento_id', $procedimento->id)
->sum('quantidade') + $params['quantidade'];
$rules["procedimentos.{$i}.procedimento_id"][] = $this->getQuantidadeValidator($validation, $quantidade);
}
$rules["procedimentos.{$i}.cid_principal_id"] = [
'nullable',
Rule::requiredIf(fn () => $procedimento->hasCidPrincipal),
'integer',
$procedimento->hasCidPrincipal
? Rule::in($procedimento->cidsPrincipais()->pluck('id'))
: 'exists:\App\Models\Sigtap\Cid,id',
];
$rules["procedimentos.{$i}.cid_secundario_id"] = [
'nullable',
'integer',
Rule::in($procedimento->cidsSecundarios()->pluck('id')),
];
$rules["procedimentos.{$i}.quantidade"] = [
'required',
'integer',
'min:1',
];
}
}
return $rules;
}
private function getPostPedidoExameRules($atendimento)
{
$rules = [
'pedidos_exames' => [
'nullable',
'array',
],
];
if ((is_array($this->pedidos_exames) ?? null)) {
$rules = array_merge($rules, [
'pedidos_exames.urgente' => [
'required',
'boolean',
],
'pedidos_exames.justificativa' => [
'nullable',
'string',
'max:100',
],
'pedidos_exames.exames' => [
'required',
'array',
],
'pedidos_exames.exames.*.exame_id' => [
'required',
'distinct',
'integer',
'exists:\App\Models\Parametrizacao\Exame\Exame,id'
],
'pedidos_exames.exames.*.observacao' => [
'nullable',
'string',
'max:1000'
],
]);
}
return $rules;
}
private function getPostServicosEnfermagemRules($atendimento)
{
$rules = [
'servicos_enfermagem' => [
'nullable',
'array',
],
];
if (is_array($this->servicos_enfermagem ?? null)) {
foreach ($this->servicos_enfermagem as $i => $params) {
$rules["servicos_enfermagem.{$i}.observacoes"] = [
'nullable',
'string',
'max:100'
];
$rules["servicos_enfermagem.{$i}.procedimento_id"] = [
'required',
'integer',
'exists:\App\Models\Sigtap\Procedimento,id',
];
$procedimento = is_numeric($params['procedimento_id'] ?? null)
? Procedimento::find($params['procedimento_id'])
: null;
if (is_null($procedimento)) {
continue;
}
$validation = new ProcedimentoValidationService($procedimento);
$quantidade = $atendimento->procedimentos
->where('procedimento_id', $procedimento->id)
->sum('quantidade') + 1;
$rules["servicos_enfermagem.{$i}.procedimento_id"] = [
$this->getOnValidCompetenciaValidator($validation),
$this->getSexoValidator($validation, $atendimento),
$this->getIdadeValidator($validation, $atendimento),
$this->getQuantidadeValidator($validation, $quantidade),
];
}
}
return $rules;
}
private function getDuplicatedValidator($procedimentos, $index)
{
return function ($attribute, $value, $fail) use ($procedimentos, $index) {
foreach ($procedimentos as $j => $params) {
if ($index === $j || !isset($params['procedimento_id'])) {
continue;
}
if ($value == $params['procedimento_id']) {
$fail('O campo ' . $attribute . ' campo tem um valor duplicado.');
}
}
};
}
private function getOnValidCompetenciaValidator($validation)
{
return function ($attribute, $value, $fail) use ($validation) {
if (!$validation->isOnValidCompetencia()) {
$fail('Competência do ' . $attribute . ' inválida.');
}
};
}
private function getOcupacaoValidator($validation)
{
return function ($attribute, $value, $fail) use ($validation) {
$ocupacao = Lotacao::find(auth()->payload()->get('lotacao_id'))->ocupacao;
if (!$validation->isOcupacaoValid($ocupacao)) {
$fail($attribute . ' não permitido para o CBO do médico.');
}
};
}
private function getSexoValidator($validation, $atendimento)
{
return function($attribute, $value, $fail) use ($validation, $atendimento)
{
if (!$validation->isSexoValid($atendimento->faa->paciente->cidadao->sexo)) {
$fail($attribute . ' não permitido para o sexo do paciente.');
}
};
}
private function getIdadeValidator($validation, $atendimento)
{
return function ($attribute, $value, $fail) use ($validation, $atendimento) {
if (!$atendimento->faa->paciente->is_desconhecido
&& !$validation->isIdadeValid($atendimento->faa->paciente->cidadao->idade['anos'])
) {
$fail($attribute . ' não permitido para a idade do paciente.');
}
};
}
private function getQuantidadeValidator($validation, $quantidade)
{
return function ($attribute, $value, $fail) use ($validation, $quantidade) {
if (!$validation->isQuantidadeValid($quantidade)) {
$fail('Quantidade máxima atingida para o '. $attribute);
}
};
}
private function getPostDesfechoRules($atendimento)
{
$rules = [
'desfecho' => [
'nullable',
'array'
],
'desfecho.id' => [
'nullable',
'integer',
Rule::in(
Desfecho::ALTA_MEDICA,
Desfecho::EVASAO,
Desfecho::ENCAMINHAMENTO_HOSPITALAR,
Desfecho::OBITO,
),
'exists:\App\Models\ProntoAtendimento\Atendimento\Desfecho,id',
],
'desfecho.evasao' => [
'nullable',
'required_if:desfecho.id,' . Desfecho::EVASAO,
'array',
],
'desfecho.evasao.motivo' => [
'nullable',
'required_if:desfecho.id,' . Desfecho::EVASAO,
'string',
'max:200'
],
'desfecho.encaminhamento_hospitalar' => [
'nullable',
'array',
],
'desfecho.encaminhamento_hospitalar.unidade_id' => [
'nullable',
'integer',
'exists:\App\Models\Cadastro\Estabelecimento\Unidade,id',
],
'desfecho.encaminhamento_hospitalar.unidade_nome' => [
'nullable',
'string',
'max:100',
],
'desfecho.encaminhamento_hospitalar.quarto' => [
'nullable',
'string',
'max:3',
],
'desfecho.encaminhamento_hospitalar.leito' => [
'nullable',
'string',
'max:3',
],
'desfecho.encaminhamento_hospitalar.cid_id' => [
'nullable',
'integer',
'exists:\App\Models\Sigtap\Cid,id',
],
'desfecho.encaminhamento_hospitalar.medico_hospitalar' => [
'nullable',
'string',
'max:150',
new NomeCompleto,
],
'desfecho.encaminhamento_hospitalar.observacoes' => [
'nullable',
'string',
'max:3000',
],
'desfecho.obito' => [
'required_if:desfecho.id,' . Desfecho::OBITO,
'array',
],
];
if (is_array($this->desfecho['obito'] ?? null)) {
$rules = array_merge($rules, [
'desfecho.obito.obito_em' => [
'required',
'date_format:d/m/Y H:i',
$this->getObitoEmValidator($atendimento),
],
'desfecho.obito.declaracao' => [
'nullable',
'string',
'min:8',
'max:13'
],
'desfecho.obito.causa' => [
'required',
'string',
'max:255'
],
'desfecho.obito.cid_id' => [
'required',
'integer',
'exists:\App\Models\Sigtap\Cid,id'
]
]);
}
return $rules;
}
private function getPostFinalizacaoRules($atendimento, $raatObrigatorio)
{
$rules = [
'finalizacao' => [
'nullable',
'array',
],
];
return array_merge(
$rules,
$this->getPostFinalizacaoDesfechoRules($atendimento)
);
}
private function getPostFinalizacaoDesfechoRules($atendimento)
{
$rules = [
'finalizacao.desfecho_id' => [
Rule::requiredIf(fn () => $this->hasFinalizacao()),
'integer',
'exists:\App\Models\ProntoAtendimento\Atendimento\Desfecho,id',
],
'finalizacao.evasao' => [
'nullable',
'required_if:finalizacao.desfecho_id,' . Desfecho::EVASAO,
'array',
],
'finalizacao.evasao.motivo' => [
'nullable',
'required_if:finalizacao.desfecho_id,' . Desfecho::EVASAO,
'string',
'max:200'
],
'finalizacao.encaminhamento_hospitalar' => [
'nullable',
'required_if:finalizacao.desfecho_id,' . Desfecho::ENCAMINHAMENTO_HOSPITALAR,
'array',
],
'finalizacao.encaminhamento_hospitalar.unidade_id' => [
'nullable',
Rule::requiredIf(fn () =>
$this->finalizacao &&
$this->finalizacao['desfecho_id'] === Desfecho::ENCAMINHAMENTO_HOSPITALAR &&
$this->finalizacao['encaminhamento_hospitalar']['unidade_nome'] === null
),
'integer',
'exists:\App\Models\Cadastro\Estabelecimento\Unidade,id',
],
'finalizacao.encaminhamento_hospitalar.unidade_nome' => [
'nullable',
Rule::requiredIf(fn () =>
$this->finalizacao &&
$this->finalizacao['desfecho_id'] === Desfecho::ENCAMINHAMENTO_HOSPITALAR &&
$this->finalizacao['encaminhamento_hospitalar']['unidade_id'] === null
),
'string',
'max:100',
],
'finalizacao.encaminhamento_hospitalar.quarto' => [
'nullable',
'string',
'max:3',
],
'finalizacao.encaminhamento_hospitalar.leito' => [
'nullable',
'string',
'max:3',
],
'finalizacao.encaminhamento_hospitalar.cid_id' => [
'nullable',
'integer',
'exists:\App\Models\Sigtap\Cid,id',
],
'finalizacao.encaminhamento_hospitalar.medico_hospitalar' => [
'nullable',
'string',
'max:150',
],
'finalizacao.encaminhamento_hospitalar.observacoes' => [
'nullable',
'string',
'max:3000',
],
'finalizacao.obito' => [
'required_if:finalizacao.desfecho_id,' . Desfecho::OBITO,
'array',
],
];
if (is_array($this->finalizacao['obito'] ?? null)) {
$rules = array_merge($rules, [
'finalizacao.obito.obito_em' => [
'required',
'date_format:d/m/Y H:i',
$this->getObitoEmValidator($atendimento),
],
'finalizacao.obito.declaracao' => [
'nullable',
'string',
'min:8',
'max:13'
],
'finalizacao.obito.causa' => [
'required',
'string',
'max:255'
],
'finalizacao.obito.cid_id' => [
'required',
'integer',
'exists:\App\Models\Sigtap\Cid,id'
]
]);
}
return $rules;
}
private function hasFinalizacao()
{
return isset($this->finalizacao);
}
private function getObitoEmValidator($atendimento)
{
return function ($attribute, $value, $fail) use ($atendimento) {
if (!$atendimento->faa->paciente->cidadao->data_nascimento) {
return;
}
$dataAtual = Carbon::today();
$dataNascimento = $atendimento->faa->paciente->cidadao->data_nascimento;
$dataObito = Carbon::createFromFormat('d/m/Y H:i', $value);
$diffObitoDataNascimento = $dataNascimento->diffInDays($dataObito, false);
$diffObitoDataAtual = $dataAtual->diffInDays($dataObito, false);
if ($diffObitoDataNascimento < 0 || $diffObitoDataAtual > 0) {
$fail("A data inserida deve ser entre a data de nascimento {$dataNascimento->format('d/m/Y')} e a data atual.");
}
};
}
private function getCentroCustoLogado()
{
return CentroCusto::findOrFail(auth()->payload()->get('centro_custo_id'));
}
}