Files
rkm-conectasus-ci-sandbox/api/app/Services/Cadastro/EspecialidadeService.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

651 lines
27 KiB
PHP

<?php
namespace App\Services\Cadastro;
use App\Enums\AtencaoBasica\AtendimentoIndividual\CondicaoAvaliada as AtendimentoIndividualCondicaoAvaliada;
use App\Enums\AtencaoBasica\AtendimentoIndividual\Conduta as CondutaEnum;
use App\Enums\Cadastro\SujeitoAtencao\Sexo as SexoEnum;
use App\Enums\Sigtap\ClassificacaoServicoAtencaoPsicossocial;
use App\Enums\Sigtap\Registro;
use App\Enums\Sigtap\Servico;
use App\Models\Ambulatorio\ProblemaCondicaoSituacao;
use App\Models\Ambulatorio\SaudeBucalVigilancia;
use App\Models\AtencaoBasica\AtendimentoIndividual\CondicaoAvaliada;
use App\Models\AtencaoBasica\AtendimentoIndividual\Conduta;
use App\Models\AtencaoBasica\AtendimentoOdontologico\TipoConsulta;
use App\Models\Cadastro\Especialidade;
use App\Models\Cadastro\SujeitoAtencao\Sexo;
use App\Models\Geral\Ciap;
use App\Models\Raas\MotivoSaidaPermanencia;
use App\Models\Regulacao\Tipo as RegulacaoTipo;
use App\Models\Sigtap\Cid;
use App\Models\Sigtap\Ocupacao;
use App\Models\Sigtap\Procedimento;
use App\Services\Service;
use App\Utils\DataUtil;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class EspecialidadeService extends Service
{
public static function datatable()
{
return DB::table('cadastro_especialidade as especialidade')
->join(
'sigtap.ocupacao as ocupacao',
'ocupacao.id',
'especialidade.ocupacao_id'
)
->select(DB::raw("
especialidade.id,
especialidade.nome,
especialidade.ativo,
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as ocupacao_descricao,
CASE
WHEN especialidade.permite_integracao_conectasus_cidadao = 1 THEN 'Sim'
ELSE 'Não'
END as permite_integracao_conectasus_cidadao,
CASE
WHEN especialidade.permite_integracao_aplicativo_feridas = 1 THEN 'Sim'
ELSE 'Não'
END as permite_integracao_aplicativo_feridas
"));
}
public static function autocomplete()
{
return DB::table('cadastro_especialidade as especialidade')
->join(
'sigtap.ocupacao as ocupacao',
'ocupacao.id',
'especialidade.ocupacao_id'
)
->where('ativo', true)
->when(isset(request()->encaminhamento), fn ($q) => $q
->where('especialidade.encaminhamento', DataUtil::getBooleanValueFromStringBoolean(request()->encaminhamento)))
->where(function ($q) {
$q->where('is_regulado', false)
->orWhere(function ($q2) {
$q2->where('is_regulado', true)
->whereExists(function ($sub) {
$sub->select(DB::raw(1))
->from('regulacao_parametrizacao_solicitante as solicitante')
->join('regulacao_parametrizacao_solicitante_regulador as regulador', 'regulador.solicitante_id', 'solicitante.id')
->join('regulacao_parametrizacao_solicitante_regulador_especialidade as regulador_especialidade', 'regulador_especialidade.solicitante_regulador_id', 'regulador.id')
->whereColumn('regulador_especialidade.especialidade_id', 'especialidade.id')
->where('solicitante.infraestrutura_id', self::getCurrentCentroCusto()->infraestrutura_id);
});
});
})
->when(is_array(request()->ocupacoes), fn($q) => $q->whereIn('ocupacao_id', request()->ocupacoes))
->select(DB::raw("
especialidade.id,
especialidade.nome,
especialidade.ocupacao_id,
especialidade.sexo_id,
especialidade.idade_minima,
especialidade.idade_maxima,
especialidade.tratamento,
especialidade.encaminhamento,
especialidade.exigir_peso_altura_circunferencia,
especialidade.permite_agendamento_mesmo_dia,
especialidade.permite_agendamento_gestante,
especialidade.permite_fechamento_sem_procedimento,
especialidade.permite_agendamento_nao_municipe,
especialidade.precisa_informar_conclusao_tratamento,
especialidade.permite_integracao_conectasus_cidadao,
especialidade.permite_integracao_aplicativo_feridas,
especialidade.limite_consulta,
especialidade.limite_consulta_mes,
especialidade.procedimento_grupo_codigo,
ocupacao.codigo as ocupacao_codigo,
especialidade.is_regulado
"));
}
public static function create()
{
return [
'form' => self::getFormData(),
'model' => [
'encaminhamento' => false,
'idade_maxima' => null,
'idade_minima' => null,
'is_regulado' => false,
'limite_consulta' => null,
'limite_consulta_mes' => null,
'mensagem_protocolo_agendamento' => null,
'nome' => null,
'ocupacao' => null,
'permite_agendamento_gestante' => false,
'permite_agendamento_mesmo_dia' => false,
'permite_agendamento_nao_municipe' => false,
'permite_fechamento_sem_procedimento' => false,
'precisa_informar_conclusao_tratamento' => false,
'permite_integracao_conectasus_cidadao' => false,
'permite_integracao_aplicativo_feridas' => false,
'exigir_peso_altura_circunferencia' => false,
'procedimento_grupo' => null,
'regulacao_tipo_id' => null,
'sexo_id' => null,
'tratamento' => false,
'atencao_basica' => [
'procedimento_padrao' => null,
'motivo_saida_permanencia_id' => null,
'classificacao_codigo' => null,
'numero_autorizacao' => null,
'problema_condicao' => [
'situacao_id' => null,
'cid' => null,
'ciap' => null,
],
'condutas' => [],
'odontologico' => [
'consulta_tipo_id' => null,
'vigilancia_id' => null,
'conduta_id' => null,
],
'condicoes_avaliadas' => []
],
'is_ppi' => false,
'valor_ppi' => null,
'limite_ocorrencias_paciente' => null,
'periodo_monitoramento' => null,
'tempo_liberacao' => null,
'tempo_medio_previsto_atendimento_dias' => null,
],
];
}
public static function store()
{
self::validate();
$params = self::getParams();
$params['valor_ppi'] = str_replace(',', '.', str_replace('.', '', $params['valor_ppi']));
$especialidade = Especialidade::create($params);
$especialidade->condutas()->sync($params['condutas']);
$especialidade->condicoesAvaliadas()->sync($params['condicoes_avaliadas']);
return $especialidade;
}
public static function edit($id)
{
$especialidade = Especialidade::findOrFail($id);
return [
'form' => self::getFormData(),
'model' => [
'nome' => $especialidade->nome,
'ocupacao' => [
'id' => $especialidade->ocupacao->id,
'codigo' => $especialidade->ocupacao->codigo,
'nome' => $especialidade->ocupacao->nome,
],
'sexo_id' => $especialidade->sexo_id ?? null,
'idade_minima' => $especialidade->idade_minima ?? null,
'idade_maxima' => $especialidade->idade_maxima ?? null,
'tratamento' => $especialidade->tratamento ?? false,
'encaminhamento' => $especialidade->encaminhamento ?? false,
'permite_agendamento_mesmo_dia' => $especialidade->permite_agendamento_mesmo_dia ?? false,
'permite_agendamento_gestante' => $especialidade->permite_agendamento_gestante ?? false,
'permite_fechamento_sem_procedimento' => $especialidade->permite_fechamento_sem_procedimento ?? false,
'permite_agendamento_nao_municipe' => $especialidade->permite_agendamento_nao_municipe ?? false,
'precisa_informar_conclusao_tratamento' => $especialidade->precisa_informar_conclusao_tratamento ?? false,
'permite_integracao_conectasus_cidadao' => $especialidade->permite_integracao_conectasus_cidadao ?? false,
'permite_integracao_aplicativo_feridas' => $especialidade->permite_integracao_aplicativo_feridas ?? false,
'exigir_peso_altura_circunferencia' => $especialidade->exigir_peso_altura_circunferencia ?? false,
'limite_consulta' => $especialidade->limite_consulta ?? null,
'limite_consulta_mes' => $especialidade->limite_consulta_mes ?? null,
'procedimento_grupo' => [
'codigo' => $especialidade->procedimentoGrupo->codigo ?? null,
'nome' => $especialidade->procedimentoGrupo->nome ?? null,
],
'mensagem_protocolo_agendamento' => $especialidade->mensagem_protocolo_agendamento ?? null,
'is_regulado' => $especialidade->is_regulado ?? false,
'regulacao_tipo_id' => $especialidade->regulacao_tipo_id ?? null,
'atencao_basica' => [
'procedimento_padrao' => is_null($especialidade->atencao_basica_procedimento_padrao_codigo)
? null
: [
'id' => $especialidade->atencaoBasicaProcedimentoPadrao->id,
'codigo' => $especialidade->atencaoBasicaProcedimentoPadrao->codigo,
'nome' => $especialidade->atencaoBasicaProcedimentoPadrao->nome,
'has_instrumento_registro_raas' => $especialidade->atencaoBasicaProcedimentoPadrao
->registros()
->whereIn('codigo', [Registro::RAAS_ATENCAO_DOMICILIAR, Registro::RAAS_ATENCAO_PSICOSSOCIAL])
->exists()
],
'motivo_saida_permanencia_id' => $especialidade->atencao_basica_motivo_saida_permanencia_id,
'classificacao_codigo' => $especialidade->atencao_basica_classificacao_codigo,
'numero_autorizacao' => $especialidade->atencao_basica_numero_autorizacao,
'problema_condicao' => [
'situacao_id' => $especialidade->atencao_basica_problema_condicao_situacao_id,
'ciap' => is_null($especialidade->atencao_basica_problema_condicao_ciap_id)
? null
: [
'id' => $especialidade->atencaoBasicaProblemaCondicaoCiap->id,
'codigo' => $especialidade->atencaoBasicaProblemaCondicaoCiap->codigo,
'descricao' => $especialidade->atencaoBasicaProblemaCondicaoCiap->descricao,
],
'cid' => is_null($especialidade->atencao_basica_problema_condicao_cid_id)
? null
: [
'id' => $especialidade->atencaoBasicaProblemaCondicaoCid->id,
'codigo' => $especialidade->atencaoBasicaProblemaCondicaoCid->codigo,
'nome' => $especialidade->atencaoBasicaProblemaCondicaoCid->nome,
],
],
'condutas' => $especialidade->condutas()->pluck('atencao_basica_cadastro_conduta.id'),
'odontologico' => [
'consulta_tipo_id' => $especialidade->atencao_basica_odontologico_consulta_tipo_id,
'vigilancia_id' => $especialidade->atencao_basica_odontologico_vigilancia_id,
'conduta_id' => $especialidade->atencao_basica_odontologico_conduta_id,
],
'condicoes_avaliadas' => $especialidade->condicoesAvaliadas()->pluck('atencao_basica_cadastro_condicao_avaliada.id')
],
'is_ppi' => $especialidade->is_ppi ?? false,
'valor_ppi' => $especialidade->valor_ppi ?? null,
'limite_ocorrencias_paciente' => $especialidade->limite_ocorrencias_paciente ?? null,
'periodo_monitoramento' => $especialidade->periodo_monitoramento ?? null,
'tempo_liberacao' => $especialidade->tempo_liberacao ?? null,
'tempo_medio_previsto_atendimento_dias' => $especialidade->tempo_medio_previsto_atendimento_dias,
],
];
}
private static function getFormData()
{
return [
'sexos' => Sexo::orderBy('descricao')->get()->map(fn($sexo) => [
'id' => $sexo->id,
'descricao' => $sexo->descricao,
]),
'regulacao_tipos' => RegulacaoTipo::orderBy('nome')->get()->map(fn($tipo) => [
'id' => $tipo->id,
'nome' => $tipo->nome,
]),
'atencao_basica' => [
'motivos_saida_permacencia' => MotivoSaidaPermanencia::orderBy('nome')->get(['id', 'nome']),
'classificacoes_servico' => self::getClassificacoesServico(),
'problema_condicao' => [
'situacoes' => ProblemaCondicaoSituacao::orderBy('nome')->get(['id', 'nome']),
],
'condutas' => Conduta::whereIn('id', [
CondutaEnum::RETORNO_PARA_CONSULTA_AGENDADA,
CondutaEnum::RETORNO_PARA_CUIDADO_CONTINUADO_PROGRAMADO,
CondutaEnum::AGENDAMENTO_PARA_GRUPOS,
CondutaEnum::AGENDAMENTO_PARA_E_MULTI,
CondutaEnum::ALTA_DO_EPISODIO,
])->orderBy('descricao')->get(['id', 'descricao']),
'odontologico' => [
'consulta_tipos' => TipoConsulta::orderBy('id')->get(['id', 'descricao']),
'vigilancias' => SaudeBucalVigilancia::orderBy('nome')->get(['id', 'nome']),
'condutas' => Conduta::whereIn('id', [
CondutaEnum::RETORNO_PARA_CONSULTA_AGENDADA,
CondutaEnum::AGENDAMENTO_PARA_E_MULTI,
CondutaEnum::AGENDAMENTO_PARA_GRUPOS,
CondutaEnum::ALTA_DO_EPISODIO,
])->orderBy('descricao')->get(['id', 'descricao']),
],
'condicoes_avaliadas' => CondicaoAvaliada::whereNotIn('id', [
AtendimentoIndividualCondicaoAvaliada::PRE_NATAL,
AtendimentoIndividualCondicaoAvaliada::PUERICULTURA,
])->orderBy('descricao')->get(),
],
];
}
private static function getClassificacoesServico()
{
return DB::table('sigtap.classificacao as classificacao')
->join('sigtap.servico as servico', 'servico.id', 'classificacao.servico_id')
->where('classificacao.competencia_id', DB::table('sigtap.competencia')->max('id'))
->where('servico.codigo', Servico::SERVICO_DE_ATENCAO_PSICOSSOCIAL)
->whereIn('classificacao.codigo', [
ClassificacaoServicoAtencaoPsicossocial::RESIDENCIA_TERAPEUTICA_EM_SAUDE_MENTAL,
ClassificacaoServicoAtencaoPsicossocial::SERVICO_RESIDENCIAL_TERAPEUTICO_TIPO_I_SRT_TIPO_I,
ClassificacaoServicoAtencaoPsicossocial::SERVICO_RESIDENCIAL_TERAPEUTICO_TIPO_II_SRT_TIPO_II,
])
->selectRaw("
classificacao.codigo,
classificacao.nome
")
->orderBy('classificacao.nome')
->get();
}
public static function update($id)
{
self::validate();
$especialidade = Especialidade::findOrFail($id);
$params = self::getParams();
$params['valor_ppi'] = str_replace(',', '.', str_replace('.', '', $params['valor_ppi']));
$especialidade->update($params);
$especialidade->condutas()->sync($params['condutas']);
$especialidade->condicoesAvaliadas()->sync($params['condicoes_avaliadas']);
return $especialidade->fresh();
}
private static function getParams()
{
$params = request()->except(['ativo', 'atencao_basica']);
if ($params['sexo_id'] === SexoEnum::MASCULINO) {
$params['permite_agendamento_gestante'] = false;
}
$atencaoBasica = request()->only('atencao_basica')['atencao_basica'];
$params['atencao_basica_procedimento_padrao_codigo'] = $atencaoBasica['procedimento_padrao_codigo'];
$params['atencao_basica_motivo_saida_permanencia_id'] = $atencaoBasica['motivo_saida_permanencia_id'];
$params['atencao_basica_classificacao_codigo'] = $atencaoBasica['classificacao_codigo'];
$params['atencao_basica_numero_autorizacao'] = $atencaoBasica['numero_autorizacao'];
$params['atencao_basica_problema_condicao_situacao_id'] = $atencaoBasica['problema_condicao']['situacao_id'];
$params['atencao_basica_problema_condicao_ciap_id'] = $atencaoBasica['problema_condicao']['ciap_id'];
$params['atencao_basica_problema_condicao_cid_id'] = $atencaoBasica['problema_condicao']['cid_id'];
$params['atencao_basica_odontologico_consulta_tipo_id'] = $atencaoBasica['odontologico']['consulta_tipo_id'];
$params['atencao_basica_odontologico_vigilancia_id'] = $atencaoBasica['odontologico']['vigilancia_id'];
$params['atencao_basica_odontologico_conduta_id'] = $atencaoBasica['odontologico']['conduta_id'];
$params['condutas'] = $atencaoBasica['condutas'];
$params['condicoes_avaliadas'] = $atencaoBasica['condicoes_avaliadas'];
return $params;
}
public static function activate($id)
{
$especialidade = Especialidade::findOrFail($id);
$especialidade->update(['ativo' => true]);
return $especialidade->fresh();
}
public static function deactivate($id)
{
$especialidade = Especialidade::findOrFail($id);
$especialidade->update(['ativo' => false]);
return $especialidade->fresh();
}
public static function destroy($id)
{
Especialidade::findOrFail($id)->delete();
}
private static function validate()
{
return request()->validate([
'nome' => [
'required',
'string',
'between:3,100',
Rule::unique(Especialidade::class, 'nome')
->ignore(request()->route('especialidade'))
],
'ocupacao_id' => [
'required',
Rule::exists(Ocupacao::class, 'id'),
],
'sexo_id' => [
'nullable',
'integer',
Rule::exists(Sexo::class, 'id'),
],
'idade_minima' => [
'nullable',
'integer',
'max:130',
],
'idade_maxima' => [
'nullable',
'integer',
'max:130',
],
'tratamento' => [
'required',
'boolean',
],
'encaminhamento' => [
'required',
'boolean',
],
'permite_agendamento_mesmo_dia' => [
'required',
'boolean',
],
'permite_agendamento_gestante' => [
'required',
'boolean',
],
'permite_fechamento_sem_procedimento' => [
'required',
'boolean',
],
'permite_agendamento_nao_municipe' => [
'required',
'boolean',
],
'precisa_informar_conclusao_tratamento' => [
'required',
'boolean',
],
'permite_integracao_conectasus_cidadao' => [
'required',
'boolean',
],
'permite_integracao_aplicativo_feridas' => [
'required',
'boolean',
],
'exigir_peso_altura_circunferencia' => [
'required',
'boolean',
],
'limite_consulta' => [
'nullable',
'required_with:limite_consulta_mes',
'integer',
'between:1,9999'
],
'limite_consulta_mes' => [
'nullable',
'required_with:limite_consulta',
'integer',
'between:1,12'
],
'regulacao_tipo_id' => [
'nullable',
'integer',
],
'procedimento_grupo_codigo' => [
'bail',
'nullable',
'numeric',
'digits:10',
Rule::exists(Procedimento::class, 'codigo'),
function ($_, $value, $fail) {
$procedimento = Procedimento::where('codigo', $value)
->orderByDesc('competencia_id')
->first(['id', 'competencia_id']);
$valid = $procedimento->registros()
->where('codigo', Registro::BPA_CONSOLIDADO)
->exists();
if (!$valid) {
$fail("O procedimento deve ser do tipo BPA (consolidado).");
}
},
],
'mensagem_protocolo_agendamento' => [
'nullable',
'string',
'max:500',
],
'atencao_basica.procedimento_padrao_codigo' => [
'nullable',
'digits:10'
],
'atencao_basica.motivo_saida_permanencia_id' => [
'nullable',
'integer',
Rule::exists(MotivoSaidaPermanencia::class, 'id'),
],
'atencao_basica.classificacao_codigo' => [
'nullable',
'digits:3'
],
'atencao_basica.numero_autorizacao' => [
'nullable',
'string',
'max:13'
],
'atencao_basica.problema_condicao.situacao_id' => [
'nullable',
'integer',
Rule::exists(ProblemaCondicaoSituacao::class, 'id'),
],
'atencao_basica.problema_condicao.ciap_id' => [
'nullable',
'integer',
Rule::exists(Ciap::class, 'id'),
],
'atencao_basica.problema_condicao.cid_id' => [
'nullable',
'integer',
Rule::exists(Cid::class, 'id'),
],
'atencao_basica.odontologico.consulta_tipo_id' => [
'nullable',
'integer',
Rule::exists(TipoConsulta::class, 'id'),
],
'atencao_basica.odontologico.vigilancia_id' => [
'nullable',
'integer',
Rule::exists(SaudeBucalVigilancia::class, 'id'),
],
'atencao_basica.odontologico.conduta_id' => [
'nullable',
'integer',
Rule::exists(Conduta::class, 'id'),
],
'limite_ocorrencias_paciente' => [
'nullable',
'integer',
'min:1',
],
'periodo_monitoramento' => [
'nullable',
'integer',
'min:1',
],
'tempo_liberacao' => [
'nullable',
'integer',
'min:0',
],
'tempo_medio_previsto_atendimento_dias' => [
'nullable',
'integer',
'max:9999'
],
], [
'nome.unique' => 'O nome da Especialidade já foi inserido anteriormente.',
]);
}
public static function getDadosParaAtribuicao()
{
return [
'ocupacoes' => self::getOcupacoesParaAtribuicao(),
'especialidades' => self::getEspecialidadesParaAtribuicao(),
];
}
private static function getOcupacoesParaAtribuicao()
{
return DB::table('sigtap.ocupacao AS ocupacao')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('cadastro_especialidade AS especialidade')
->whereColumn('especialidade.ocupacao_id', 'ocupacao.id')
)
->select(
'ocupacao.id',
'ocupacao.codigo',
'ocupacao.nome',
)
->get();
}
private static function getEspecialidadesParaAtribuicao()
{
return DB::table('cadastro_especialidade AS especialidade')
->select(
'especialidade.id',
'especialidade.nome',
'especialidade.ocupacao_id',
)
->get();
}
public static function saveAtribuicao()
{
self::validateSaveAtribuicao();
$params = [];
if (isset(request()->tempo_medio_previsto_atendimento_dias)) {
$params['tempo_medio_previsto_atendimento_dias'] = request()->tempo_medio_previsto_atendimento_dias;
}
Especialidade::where(fn ($q) => $q
->whereIn('id', request()->especialidades)
->orWhereIn('ocupacao_id', request()->ocupacoes)
)->update($params);
}
private static function validateSaveAtribuicao()
{
request()->validate([
'ocupacoes' => [
'present',
'array',
],
'ocupacoes.*' => [
'required',
'integer',
],
'especialidades' => [
'present',
'array',
],
'especialidades.*' => [
'required',
'integer',
],
'tempo_medio_previsto_atendimento_dias' => [
'nullable',
'integer',
'max:9999'
],
]);
}
}