2753 lines
110 KiB
PHP
2753 lines
110 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Ambulatorio;
|
|
|
|
use App\Enums\Administracao\Modulo;
|
|
use App\Enums\Ambulatorio\AgendamentoStatus as AgendamentoStatusEnum;
|
|
use App\Enums\Ambulatorio\AgendamentoTipo as AgendamentoTipoEnum;
|
|
use App\Enums\Ambulatorio\JornadaTipo;
|
|
use App\Enums\Cadastro\SujeitoAtencao\Classificacao;
|
|
use App\Enums\Cadastro\SujeitoAtencao\Subclassificacao;
|
|
use App\Enums\Cadastro\Estabelecimento\SetorTipo;
|
|
use App\Enums\ExameImagem\Fechamento\Status as ExameImagemAgendamentoStatus;
|
|
use App\Enums\ExameLaboratorial\StatusAgendamento as ExameLaboratorialAgendamentoStatus;
|
|
use App\Enums\Regulacao\StatusTipo as RegulacaoStatusTipo;
|
|
use App\Enums\PainelSenha\Status;
|
|
use App\Exceptions\Ambulatorio\AgendamentoConflitanteException;
|
|
use App\Exceptions\Ambulatorio\AgendamentoNaoPermitidoJornadaGrupoException;
|
|
use App\Exceptions\Ambulatorio\NaoPodeAlterarStatusAgendamentoException;
|
|
use App\Exceptions\Ambulatorio\NaoPodeExcluirAgendamentoException;
|
|
use App\Http\Controllers\Cadastro\SujeitoAtencao\PacienteController;
|
|
use App\Models\Ambulatorio\Agendamento;
|
|
use App\Models\Ambulatorio\Atendimento;
|
|
use App\Models\Ambulatorio\AgendamentoStatus;
|
|
use App\Models\Ambulatorio\AgendamentoTipo;
|
|
use App\Models\Ambulatorio\DemandaEspontanea;
|
|
use App\Models\Ambulatorio\Jornada;
|
|
use App\Models\Ambulatorio\JornadaBloqueio;
|
|
use App\Models\Ambulatorio\ParametrizacaoAgendamento;
|
|
use App\Models\Ambulatorio\ParametrizacaoIntegracaoAplicativo;
|
|
use App\Models\Ambulatorio\ParametrizacaoInfraestrutura;
|
|
use App\Models\Ambulatorio\ParametrizacaoInfraestruturaEspecialidade;
|
|
use App\Models\Cadastro\Especialidade;
|
|
use App\Models\Cadastro\Estabelecimento\Infraestrutura;
|
|
use App\Models\Cadastro\Estabelecimento\Unidade;
|
|
use App\Models\Cadastro\Feriado\Feriado;
|
|
use App\Models\Cadastro\Parametrizacao\Parametrizacao;
|
|
use App\Models\Cadastro\SujeitoAtencao\Paciente;
|
|
use App\Models\Cadastro\SujeitoAtencao\Usuario;
|
|
use App\Models\ExameImagem\Agendamento\Agendamento as ExameImagemAgendamento;
|
|
use App\Models\ExameLaboratorial\AgendamentoExame\Agendamento as ExameLaboratorialAgendamento;
|
|
use App\Models\Geral\DiaSemana;
|
|
use App\Models\PainelSenha\OpcaoEntrada;
|
|
use App\Models\Regulacao\Parametrizacao as RegulacaoParametrizacao;
|
|
use App\Models\Regulacao\Solicitacao as RegulacaoSolicitacao;
|
|
use App\Models\Sigtap\Procedimento;
|
|
use App\Models\Cadastro\Estabelecimento\CentroCusto;
|
|
use App\Rules\Cns;
|
|
use App\Services\Integracao\CnsService;
|
|
use App\Services\Regulacao\SolicitacaoService as RegulacaoSolicitacaoService;
|
|
use App\Services\Service;
|
|
use App\Services\Sigtap\ProcedimentoValidationService;
|
|
use App\Services\Ambulatorio\RegistroPacienteAposAgendamento;
|
|
use App\Utils\DataUtil;
|
|
use App\Utils\MaskUtil;
|
|
use Illuminate\Http\Response;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Validator;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\Rule;
|
|
use Throwable;
|
|
|
|
class AgendamentoService extends Service
|
|
{
|
|
public static function datatable()
|
|
{
|
|
|
|
$parametrizacao = Parametrizacao::first();
|
|
$quantidadeDias = $parametrizacao->cadastro_paciente_desatualizado_quantidade_dias ?? 0;
|
|
$provisorioBloqueado = $parametrizacao->cadastro_paciente_provisorio_bloqueado ?? false;
|
|
$provisorioQuantidadeDias = $parametrizacao->cadastro_paciente_provisorio_quantidade_dias ?? 0;
|
|
|
|
$pacientes = 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')
|
|
->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 AND cidadao.updated_at IS NULL THEN 1
|
|
WHEN paciente.updated_at IS NOT NULL AND (cidadao.updated_at IS NULL OR paciente.updated_at > cidadao.updated_at) THEN
|
|
CASE
|
|
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
|
|
WHEN cidadao.updated_at IS NOT NULL AND (paciente.updated_at IS NULL OR cidadao.updated_at > paciente.updated_at) THEN
|
|
CASE
|
|
WHEN " . ($quantidadeDias > 0
|
|
? "DATE_ADD(cidadao.updated_at, INTERVAL " . $quantidadeDias . " DAY) < NOW()"
|
|
: "false") . "
|
|
THEN DATEDIFF(NOW(), DATE_ADD(cidadao.updated_at, INTERVAL " . $quantidadeDias . " DAY))
|
|
ELSE 0
|
|
END
|
|
ELSE 0
|
|
END as dias_cadastro_desatualizado
|
|
"));
|
|
|
|
if (!DataUtil::isStringTrue(request()->with_paciente_bloqueado)) {
|
|
|
|
$pacientes->where(function ($query) {
|
|
|
|
$query
|
|
->where('paciente.bloqueado', false)
|
|
->orWhereNull('paciente.bloqueado');
|
|
});
|
|
}
|
|
|
|
if (!DataUtil::isStringTrue(request()->with_paciente_provisorio) && $provisorioBloqueado) {
|
|
|
|
$pacientes->where(function ($query) use ($provisorioQuantidadeDias) {
|
|
$query->where('paciente.subclassificacao_id', '!=', Subclassificacao::TEMPORARIO)
|
|
->orWhere(function ($query) use ($provisorioQuantidadeDias) {
|
|
$query->where('paciente.subclassificacao_id', Subclassificacao::TEMPORARIO)
|
|
->where(function ($query) use ($provisorioQuantidadeDias) {
|
|
|
|
$query->where(function ($query) {
|
|
$query->whereNull('paciente.validade_inicio')
|
|
->orWhereDate('paciente.validade_inicio', '<=', Carbon::now()->format('Y-m-d'));
|
|
});
|
|
|
|
$query->where(function ($query) use ($provisorioQuantidadeDias) {
|
|
$query->whereNull('paciente.validade_fim')
|
|
->orWhere(function ($query) use ($provisorioQuantidadeDias) {
|
|
if (!is_null($provisorioQuantidadeDias) && $provisorioQuantidadeDias > 0) {
|
|
$query->whereDate('paciente.validade_fim', '>=', Carbon::now()->format('Y-m-d'))
|
|
->orWhereDate('paciente.validade_fim', '>=', Carbon::now()->subDays($provisorioQuantidadeDias)->format('Y-m-d'));
|
|
} else {
|
|
$query->whereDate('paciente.validade_fim', '>=', Carbon::now()->format('Y-m-d'));
|
|
}
|
|
});
|
|
});
|
|
});
|
|
})
|
|
->orWhereNull('paciente.subclassificacao_id');
|
|
});
|
|
}
|
|
|
|
return $pacientes;
|
|
}
|
|
|
|
public static function index($params)
|
|
{
|
|
$agendamentos = DB::table('ambulatorio_agendamento as agendamento')
|
|
->join(
|
|
'ambulatorio_agendamento_status as status',
|
|
'status.id',
|
|
'agendamento.status_id'
|
|
)
|
|
->join(
|
|
'ambulatorio_agendamento_tipo as tipo',
|
|
'tipo.id',
|
|
'agendamento.tipo_id'
|
|
)
|
|
->join(
|
|
'ambulatorio_jornada as jornada',
|
|
'jornada.id',
|
|
'agendamento.jornada_id'
|
|
)
|
|
->join(
|
|
'cadastro_lotacao as lotacao',
|
|
'lotacao.id',
|
|
'jornada.lotacao_id'
|
|
)
|
|
->join(
|
|
'cadastro_infraestrutura as infraestrutura',
|
|
'infraestrutura.id',
|
|
'lotacao.infraestrutura_id'
|
|
)
|
|
->join(
|
|
'cadastro_unidade as unidade',
|
|
'unidade.id',
|
|
'infraestrutura.unidade_id'
|
|
)
|
|
->join(
|
|
'cadastro_usuario as usuario',
|
|
'usuario.id',
|
|
'lotacao.usuario_id'
|
|
)
|
|
->join(
|
|
'cadastro_cidadao as cidadao',
|
|
'cidadao.id',
|
|
'usuario.cidadao_id'
|
|
)
|
|
->join(
|
|
'sigtap.ocupacao as ocupacao',
|
|
'ocupacao.id',
|
|
'lotacao.ocupacao_id'
|
|
)
|
|
->join(
|
|
'cadastro_especialidade as especialidade',
|
|
'especialidade.id',
|
|
'jornada.especialidade_id'
|
|
)
|
|
->join(
|
|
'cadastro_lotacao as lotacao_agendamento',
|
|
'lotacao_agendamento.id',
|
|
'agendamento.created_lotacao_id'
|
|
)
|
|
->join(
|
|
'cadastro_usuario as usuario_agendamento',
|
|
'usuario_agendamento.id',
|
|
'lotacao_agendamento.usuario_id'
|
|
)
|
|
->join(
|
|
'cadastro_cidadao as cidadao_agendamento',
|
|
'cidadao_agendamento.id',
|
|
'usuario_agendamento.cidadao_id'
|
|
)
|
|
->when($params->paciente_id ?? null, fn ($q, $id) => $q->where('agendamento.paciente_id', $id))
|
|
->when($params->periodo ?? null, fn ($q, $periodo) => $q
|
|
->whereBetween('jornada.data', [
|
|
Carbon::createFromFormat('d/m/Y', $periodo['start'])->startOfDay(),
|
|
Carbon::createFromFormat('d/m/Y', $periodo['end'])->endOfDay(),
|
|
])
|
|
)
|
|
->when(isset($params->inicio) && isset($params->fim), fn ($q) => $q
|
|
->whereBetween('agendamento.horario', [$params->inicio, $params->fim])
|
|
)
|
|
->when($params->unidade_id ?? null, fn ($q, $id) => $q->where('unidade.id', $id))
|
|
->when($params->infraestrutura_id ?? null, fn ($q, $id) => $q->where('infraestrutura.id', $id))
|
|
->when($params->ocupacao_id ?? null, fn ($q, $id) => $q->where('ocupacao.id', $id))
|
|
->when($params->especialidade_id ?? null, fn ($q, $id) => $q->where('especialidade.id', $id))
|
|
->when($params->usuario_id ?? null, fn ($q, $id) => $q->where('usuario.id', $id))
|
|
->when($params->tipo_id ?? null, fn ($q, $id) => $q->where('tipo.id', $id))
|
|
->when($params->status_id ?? null, fn ($q, $id) => $q->where('status.id', $id))
|
|
->select(DB::raw("
|
|
agendamento.id,
|
|
agendamento.regulacao_solicitacao_id,
|
|
jornada.data,
|
|
DATE_FORMAT(agendamento.horario, '%H:%i') as horario,
|
|
unidade.nome_fantasia as unidade,
|
|
COALESCE(infraestrutura.nome, unidade.nome_fantasia) as infraestrutura,
|
|
cidadao.nome as usuario,
|
|
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as ocupacao,
|
|
especialidade.nome as especialidade,
|
|
tipo.nome as tipo,
|
|
status.id as status_id,
|
|
status.nome as status,
|
|
cidadao_agendamento.nome as usuario_agendamento,
|
|
DATE_FORMAT(agendamento.created_at, '%d/%m/%Y às %H:%i') as data_hora_agendamento
|
|
"))
|
|
->addSelect([
|
|
'has_atendimento' => function ($query) {
|
|
|
|
$query->select(DB::raw(1))
|
|
->from('ambulatorio_atendimento as atendimento')
|
|
->whereColumn('atendimento.agendamento_id', 'agendamento.id')
|
|
->limit(1);
|
|
}
|
|
])
|
|
->get();
|
|
|
|
$agendamentos->each(function ($agendamento) {
|
|
|
|
$isAgendadoSemAtendimento = !$agendamento->has_atendimento
|
|
&& $agendamento->status_id === AgendamentoStatusEnum::AGENDADO;
|
|
|
|
$agendamento->permite_alteracao = $isAgendadoSemAtendimento
|
|
&& is_null($agendamento->regulacao_solicitacao_id);
|
|
|
|
$agendamento->permite_cancelamento_exclusao = $isAgendadoSemAtendimento;
|
|
|
|
unset($agendamento->regulacao_solicitacao_id, $agendamento->status_id, $agendamento->has_atendimento);
|
|
});
|
|
|
|
return $agendamentos;
|
|
}
|
|
|
|
public static function create($pacienteId)
|
|
{
|
|
$paciente = Paciente::findOrFail($pacienteId);
|
|
|
|
switch (request()->origem) {
|
|
|
|
case 'busca': {
|
|
|
|
return self::getDadosCreateBusca($paciente);
|
|
}
|
|
case 'cadastro': {
|
|
|
|
return self::getDadosCreateCadastro($paciente);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function getDadosCreateBusca($paciente)
|
|
{
|
|
$municipioResidencia = $paciente->cidadao->domicilio->endereco->logradouro->municipio ?? null;
|
|
$parametrizacao = ParametrizacaoAgendamento::first();
|
|
|
|
$agendamentos = self::index((object) [
|
|
'paciente_id' => $paciente->id,
|
|
'status_id' => AgendamentoStatusEnum::AGENDADO,
|
|
'periodo' => [
|
|
'start' => Carbon::now()->subYear()->format('d/m/Y'),
|
|
'end' => Carbon::now()->format('d/m/Y'),
|
|
]
|
|
]);
|
|
|
|
$formFilters = [
|
|
'unidades' => [],
|
|
'infraestruturas' => [],
|
|
'ocupacoes' => [],
|
|
'especialidades' => [],
|
|
'usuarios' => [],
|
|
'tipos' => [],
|
|
'status' => [],
|
|
];
|
|
|
|
$modelFilters = [
|
|
'periodo' => [
|
|
'start' => null,
|
|
'end' => null,
|
|
],
|
|
'inicio' => null,
|
|
'fim' => null,
|
|
'unidade_id' => null,
|
|
'infraestrutura_id' => null,
|
|
'ocupacao_id' => null,
|
|
'especialidade_id' => null,
|
|
'usuario_id' => null,
|
|
'tipo_id' => null,
|
|
'status_id' => null,
|
|
];
|
|
|
|
if ($agendamentos->isNotEmpty()) {
|
|
|
|
$agendamentosFilters = self::getAgendamentosFilters($paciente, $agendamentos);
|
|
|
|
$formFilters['unidades'] = $agendamentosFilters->form['unidades'];
|
|
$formFilters['ocupacoes'] = $agendamentosFilters->form['ocupacoes'];
|
|
$formFilters['usuarios'] = $agendamentosFilters->form['usuarios'];
|
|
$formFilters['tipos'] = $agendamentosFilters->form['tipos'];
|
|
$formFilters['status'] = $agendamentosFilters->form['status'];
|
|
|
|
$modelFilters['periodo'] = $agendamentosFilters->model['periodo'];
|
|
$modelFilters['status_id'] = $agendamentosFilters->model['status_id'];
|
|
}
|
|
|
|
$cadastroParametrizacao = Parametrizacao::first();
|
|
|
|
return [
|
|
'additionals' => [
|
|
'cadastro_paciente_vencido' => ($parametrizacao->bloqueia_paciente_temporario ?? false)
|
|
&& PacienteController::isCadastroPacienteVencido($paciente->id),
|
|
'cns_valido' => Cns::isValid($paciente->cidadao->cns),
|
|
'avisa_cns_provisorio' => self::avisaCnsProvisorio($parametrizacao, $paciente),
|
|
'avisa_cns_temporario_invalido' => $cadastroParametrizacao->exibe_alerta_paciente_cns_temporario_invalido ?? false,
|
|
'permissoes_atualizacao_cadastro_paciente' => self::getPermissoesAtualizacaoCadastroPaciente(),
|
|
],
|
|
'form' => array_merge($formFilters, [
|
|
'paciente' => [
|
|
'cidadao_id' => $paciente->cidadao->id,
|
|
'nome' => $paciente->cidadao->nome,
|
|
'nome_social' => $paciente->cidadao->nome_social,
|
|
'preferencia_nome_id' => $paciente->cidadao->preferencia_nome_id,
|
|
'data_nascimento' => is_null($paciente->cidadao->data_nascimento)
|
|
? null
|
|
: (new Carbon($paciente->cidadao->data_nascimento))->format('d/m/Y'),
|
|
'idade' => $paciente->cidadao->idade_formatada,
|
|
'nome_mae' => $paciente->cidadao->nome_mae,
|
|
'prontuario' => $paciente->prontuario,
|
|
'cpf' => MaskUtil::getCpfMasked($paciente->cidadao->cpf),
|
|
'cns' => MaskUtil::getCnsMasked($paciente->cidadao->cns),
|
|
'municipio_uf' => is_null($municipioResidencia)
|
|
? null
|
|
: "{$municipioResidencia->nome} / {$municipioResidencia->estado->uf}",
|
|
'telefone' => MaskUtil::getPhoneMasked($paciente->cidadao->telefone_principal->numero ?? null),
|
|
'unidade_referencia' => $paciente->unidade->nome_fantasia ?? null,
|
|
'classificacao_id' => $paciente->classificacao_id,
|
|
'subclassificacao_id' => $paciente->subclassificacao_id,
|
|
'classificacao' => $paciente->classificacao->descricao ?? null,
|
|
'validade_fim' => is_null($paciente->validade_fim)
|
|
? 'INDETERMINADO'
|
|
: (new Carbon($paciente->validade_fim))->format('d/m/Y')
|
|
],
|
|
'especialidades_permitem_nao_municipe' => self::getEspecialidadesPermitemNaoMunicipe($paciente->id),
|
|
]),
|
|
'model' => $modelFilters,
|
|
'agendamentos' => $agendamentos,
|
|
];
|
|
}
|
|
|
|
private static function getAgendamentosFilters($paciente, $agendamentos)
|
|
{
|
|
$datasAgendadas = collect();
|
|
|
|
$agendamentos->each(fn ($agendamento) => $datasAgendadas
|
|
->push(Carbon::createFromFormat('Y-m-d', $agendamento->data))
|
|
);
|
|
|
|
$datasAgendadas = $datasAgendadas->sort();
|
|
|
|
$periodo = [
|
|
'start' => $datasAgendadas->first()->copy()->startOfDay(),
|
|
'end' => $datasAgendadas->last()->copy()->endOfDay(),
|
|
];
|
|
|
|
$params = (object) [
|
|
'paciente_id' => $paciente->id,
|
|
'periodo' => $periodo,
|
|
];
|
|
|
|
return (object) [
|
|
'form' => [
|
|
'unidades' => self::getBuscaUnidades($params),
|
|
'ocupacoes' => self::getBuscaOcupacoes($params),
|
|
'usuarios' => self::getBuscaUsuarios($params),
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
],
|
|
'model' => [
|
|
'periodo' => [
|
|
'start' => $periodo['start']->format('d/m/Y'),
|
|
'end' => $periodo['end']->format('d/m/Y'),
|
|
],
|
|
'status_id' => AgendamentoStatusEnum::AGENDADO,
|
|
],
|
|
];
|
|
}
|
|
|
|
private static function avisaCnsProvisorio($parametrizacao, $paciente)
|
|
{
|
|
return ($parametrizacao->avisa_cns_provisorio ?? false)
|
|
&& Str::startsWith($paciente->cidadao->cns, [5, 7, 8, 9]);
|
|
}
|
|
|
|
private static function getEspecialidadesPermitemNaoMunicipe($pacienteId)
|
|
{
|
|
return Especialidade::where('permite_agendamento_nao_municipe', true)
|
|
->where(fn ($q) => self::setCadastroWhereEspecialidadePaciente($q, $pacienteId))
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::now())
|
|
)
|
|
->orderBy('nome')
|
|
->get(['id', 'nome']);
|
|
}
|
|
|
|
private static function getDadosCreateCadastro($paciente)
|
|
{
|
|
$params = (object) [
|
|
'paciente_id' => $paciente->id,
|
|
'paciente_nao_municipe' => $paciente->classificacao_id !== Classificacao::MUNICIPE,
|
|
];
|
|
|
|
return [
|
|
'additionals' => self::getAdditionalsCadastro($paciente),
|
|
'form' => [
|
|
'feriados' => self::getFeriados(),
|
|
'datas_com_agendamento' => self::getCadastroDatasComAgendamento($params),
|
|
'unidades' => self::getCadastroUnidades($params),
|
|
'infraestruturas' => [],
|
|
'ocupacoes' => [],
|
|
'especialidades' => [],
|
|
'faltas' => [],
|
|
'usuarios' => [],
|
|
'datas' => [],
|
|
'datas_bloqueadas' => [],
|
|
'horarios' => [],
|
|
'horarios_com_situacao' => [],
|
|
'quantidade_demanda_espontanea' => null,
|
|
'tipo_nome' => null,
|
|
],
|
|
'model' => [
|
|
'unidade_id' => null,
|
|
'infraestrutura_id' => null,
|
|
'ocupacao_id' => null,
|
|
'especialidade_id' => null,
|
|
'usuario_id' => null,
|
|
'demanda_espontanea_observa_vaga_atendimento' => null,
|
|
'data' => null,
|
|
'jornada_id' => null,
|
|
'horario' => null,
|
|
'observacao' => null,
|
|
'motivo_agendamento_excedente' => null,
|
|
],
|
|
];
|
|
}
|
|
|
|
public static function edit($id)
|
|
{
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
$params = (object) [
|
|
'paciente_id' => $agendamento->paciente_id,
|
|
'paciente_nao_municipe' => $agendamento->paciente->classificacao_id !== Classificacao::MUNICIPE,
|
|
'unidade_id' => $agendamento->jornada->lotacao->infraestrutura->unidade_id,
|
|
'infraestrutura_id' => $agendamento->jornada->lotacao->infraestrutura_id,
|
|
'ocupacao_id' => $agendamento->jornada->lotacao->ocupacao_id,
|
|
'especialidade_id' => $agendamento->jornada->especialidade_id,
|
|
'usuario_id' => $agendamento->jornada->lotacao->usuario_id,
|
|
'data' => $agendamento->jornada->data->format('d/m/Y'),
|
|
'tipo_id' => $agendamento->tipo_id,
|
|
];
|
|
|
|
return [
|
|
'additionals' => self::getAdditionalsCadastro(),
|
|
'form' => [
|
|
'feriados' => self::getFeriados(),
|
|
'datas_com_agendamento' => self::getCadastroDatasComAgendamento($params),
|
|
'unidades' => self::getCadastroUnidades($params),
|
|
'infraestruturas' => self::getCadastroInfraestruturas($params),
|
|
'ocupacoes' => self::getCadastroOcupacoes($params, $agendamento->jornada->lotacao->ocupacao_id),
|
|
'especialidades' => self::getCadastroEspecialidades($params, $agendamento->jornada->especialidade_id),
|
|
'faltas' => self::getFaltas($params),
|
|
'usuarios' => self::getCadastroUsuarios($params),
|
|
'datas' => self::getCadastroDatas($params),
|
|
'datas_bloqueadas' => self::getCadastroDatasBloqueadas($params),
|
|
'horarios' => self::getCadastroHorarios($params),
|
|
'horarios_com_situacao' => self::getCadastroHorariosComSituacao($params),
|
|
'quantidade_demanda_espontanea' => self::getQuantidadeDemandaEspontanea($params),
|
|
'tipo_nome' => $agendamento->tipo->nome,
|
|
'situacao' => self::getCadastroDatasComSituacao($params)
|
|
],
|
|
'model' => [
|
|
'unidade_id' => $agendamento->jornada->lotacao->infraestrutura->unidade_id,
|
|
'infraestrutura_id' => $agendamento->jornada->lotacao->infraestrutura_id,
|
|
'ocupacao_id' => $agendamento->jornada->lotacao->ocupacao_id,
|
|
'especialidade_id' => $agendamento->jornada->especialidade_id,
|
|
'usuario_id' => $agendamento->jornada->lotacao->usuario_id,
|
|
'demanda_espontanea_observa_vaga_atendimento' => self::getDemandaEspontaneaObservaVagaAtendimentoAgendamento($agendamento),
|
|
'data' => $agendamento->jornada->data->format('d/m/Y'),
|
|
'jornada_id' => $agendamento->jornada->id,
|
|
'horario' => $agendamento->horario->format('H:i'),
|
|
'observacao' => $agendamento->observacao,
|
|
'motivo_agendamento_excedente' => $agendamento->motivo_agendamento_excedente,
|
|
],
|
|
];
|
|
}
|
|
|
|
private static function getAdditionalsCadastro()
|
|
{
|
|
return [
|
|
'data_atual' => Carbon::today()->format('d/m/Y'),
|
|
'obriga_motivo_agendamento_excedente' => ParametrizacaoAgendamento::first()
|
|
->obriga_motivo_agendamento_excedente ?? false,
|
|
];
|
|
}
|
|
|
|
private static function getFeriados()
|
|
{
|
|
return Feriado::whereHas('modulos', fn ($q) => $q
|
|
->where('identificador', Modulo::AMBULATORIO)
|
|
)
|
|
->orderBy('data')
|
|
->get()
|
|
->map(fn ($feriado) => (object) [
|
|
'data' => (new Carbon($feriado->data))->format('d/m/Y'),
|
|
'tipo_descricao' => $feriado->tipo->descricao,
|
|
'observacao' => $feriado->observacao,
|
|
]);
|
|
}
|
|
|
|
private static function getCadastroDatasComAgendamento($params)
|
|
{
|
|
$agendamentosExameLaboratorial = ExameLaboratorialAgendamento::where('paciente_id', $params->paciente_id)
|
|
->whereHas('agendamentoExame', fn ($q) => $q
|
|
->where('status_id', ExameLaboratorialAgendamentoStatus::AGENDADO)
|
|
)
|
|
->get()
|
|
->map(fn ($agendamento) => [
|
|
'data' => $agendamento->data->format('d/m/Y'),
|
|
'horario' => Carbon::now()->setTimeFromTimeString($agendamento->horario)->format('H:i'),
|
|
'unidade_nome_fantasia' => $agendamento->coletaInfraestrutura->unidade->nome_fantasia,
|
|
'infraestrutura_nome' => $agendamento->coletaInfraestrutura->nome,
|
|
]);
|
|
|
|
$agendamentosExameImagem = ExameImagemAgendamento::where('paciente_id', $params->paciente_id)
|
|
->whereHas('agendamentoExame', fn ($q) => $q
|
|
->where('status_id', ExameImagemAgendamentoStatus::AGENDADO)
|
|
)
|
|
->get()
|
|
->map(fn ($agendamento) => [
|
|
'data' => $agendamento->data->format('d/m/Y'),
|
|
'horario' => Carbon::now()->setTimeFromTimeString($agendamento->hora_exame)->format('H:i'),
|
|
'unidade_nome_fantasia' => $agendamento->infraestrutura->unidade->nome_fantasia,
|
|
'infraestrutura_nome' => $agendamento->infraestrutura->nome,
|
|
]);
|
|
|
|
return [
|
|
'ambulatorio' => self::getAgendamentosPaciente($params->paciente_id),
|
|
'exame_laboratorial' => $agendamentosExameLaboratorial,
|
|
'exame_imagem' => $agendamentosExameImagem,
|
|
];
|
|
}
|
|
|
|
private static function getAgendamentosPaciente($pacienteId)
|
|
{
|
|
return Agendamento::where('paciente_id', $pacienteId)
|
|
->where('status_id', AgendamentoStatusEnum::AGENDADO)
|
|
->get()
|
|
->map(fn ($agendamento) => [
|
|
'id' => $agendamento->id,
|
|
'data' => $agendamento->jornada->data->format('d/m/Y'),
|
|
'horario' => $agendamento->horario->format('H:i'),
|
|
'tipo_nome' => Str::lower($agendamento->tipo->nome),
|
|
'unidade_nome_fantasia' => $agendamento->jornada->lotacao->infraestrutura->unidade->nome_fantasia,
|
|
'infraestrutura_nome' => $agendamento->jornada->lotacao->infraestrutura->nome,
|
|
'especialidade_id' => $agendamento->jornada->especialidade_id,
|
|
'especialidade_nome' => $agendamento->jornada->especialidade->nome,
|
|
]);
|
|
}
|
|
|
|
public static function list()
|
|
{
|
|
switch (request()->origem) {
|
|
|
|
case 'busca': {
|
|
|
|
return self::getDadosListBusca();
|
|
}
|
|
case 'cadastro': {
|
|
|
|
return self::getDadosListCadastro();
|
|
}
|
|
case 'agendamento-demanda-espontanea': {
|
|
|
|
return self::getDadosListAgendamentoDemandaEspontanea();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function getDadosListBusca()
|
|
{
|
|
$params = (object) request()->all();
|
|
|
|
$params->periodo = [
|
|
Carbon::createFromFormat('d/m/Y', $params->periodo['start'])->startOfDay(),
|
|
Carbon::createFromFormat('d/m/Y', $params->periodo['end'])->endOfDay(),
|
|
];
|
|
|
|
switch (request()->listar) {
|
|
|
|
case 'unidades': {
|
|
|
|
return [
|
|
'unidades' => self::getBuscaUnidades($params),
|
|
'infraestruturas' => [],
|
|
'ocupacoes' => self::getBuscaOcupacoes($params),
|
|
'especialidades' => [],
|
|
'usuarios' => self::getBuscaUsuarios($params),
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
}
|
|
case 'infraestruturas': {
|
|
|
|
return [
|
|
'infraestruturas' => self::getBuscaInfraestruturas($params),
|
|
'ocupacoes' => self::getBuscaOcupacoes($params),
|
|
'especialidades' => [],
|
|
'usuarios' => self::getBuscaUsuarios($params),
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
|
|
return self::getBuscaInfraestruturas($params);
|
|
}
|
|
case 'ocupacoes': {
|
|
|
|
return [
|
|
'ocupacoes' => self::getBuscaOcupacoes($params),
|
|
'especialidades' => [],
|
|
'usuarios' => self::getBuscaUsuarios($params),
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
}
|
|
case 'especialidades': {
|
|
|
|
return [
|
|
'especialidades' => self::getBuscaEspecialidades($params),
|
|
'usuarios' => self::getBuscaUsuarios($params),
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
}
|
|
case 'usuarios': {
|
|
|
|
return [
|
|
'usuarios' => self::getBuscaUsuarios($params),
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
}
|
|
case 'tipos': {
|
|
|
|
return [
|
|
'tipos' => self::getBuscaTipos($params),
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
}
|
|
case 'status': {
|
|
|
|
return [
|
|
'status' => self::getBuscaStatus($params),
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function getBuscaUnidades($params)
|
|
{
|
|
return Unidade::whereHas('infraestruturas', fn ($q) => $q
|
|
->whereHas('lotacoes', fn ($q) => $q
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereBetween('data', $params->periodo)
|
|
->whereHas('agendamentos', fn ($q) =>
|
|
self::setBuscaWhereAgendamento($q, $params)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
->orderBy('nome_fantasia')
|
|
->get(['id', 'nome_fantasia']);
|
|
}
|
|
|
|
private static function getBuscaInfraestruturas($params)
|
|
{
|
|
return Infraestrutura::setEagerLoads([])
|
|
->where('unidade_id', $params->unidade_id)
|
|
->whereHas('lotacoes', fn ($q) => $q
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereBetween('data', $params->periodo)
|
|
->whereHas('agendamentos', fn ($q) =>
|
|
self::setBuscaWhereAgendamento($q, $params)
|
|
)
|
|
)
|
|
)
|
|
->get(['id', 'nome', 'principal', 'unidade_id'])
|
|
->map(fn ($infraestrutura) => [
|
|
'id' => $infraestrutura->id,
|
|
'nome' => $infraestrutura->nome
|
|
])
|
|
->sortBy('nome')
|
|
->values();
|
|
}
|
|
|
|
private static function getBuscaOcupacoes($params)
|
|
{
|
|
return DB::table('sigtap.ocupacao as ocupacao')
|
|
->whereExists(function ($query) use ($params) {
|
|
|
|
$query->select(DB::raw(1))
|
|
->from('cadastro_lotacao as lotacao')
|
|
->join(
|
|
'cadastro_infraestrutura as infraestrutura',
|
|
'infraestrutura.id',
|
|
'lotacao.infraestrutura_id'
|
|
)
|
|
->whereColumn('lotacao.ocupacao_id', 'ocupacao.id')
|
|
->when($params->infraestrutura_id ?? null,
|
|
fn ($q, $id) => $q->where('lotacao.infraestrutura_id', $id),
|
|
fn ($q) => $q->when($params->unidade_id ?? null, fn ($q, $id) => $q
|
|
->where('infraestrutura.unidade_id', $id)
|
|
)
|
|
)
|
|
->whereExists(function ($query) use ($params) {
|
|
|
|
$query->select(DB::raw(1))
|
|
->from('ambulatorio_agendamento as agendamento')
|
|
->join(
|
|
'ambulatorio_jornada as jornada',
|
|
'jornada.id',
|
|
'agendamento.jornada_id'
|
|
)
|
|
->whereColumn('jornada.lotacao_id', 'lotacao.id')
|
|
->whereBetween('jornada.data', $params->periodo)
|
|
->where(fn ($q) => self::setBuscaWhereAgendamento($q, $params, 'agendamento'));
|
|
});
|
|
})
|
|
->select(DB::raw("
|
|
ocupacao.id,
|
|
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as descricao
|
|
"))
|
|
->orderByRaw("CONCAT(ocupacao.codigo, ' - ', ocupacao.nome)")
|
|
->get();
|
|
}
|
|
|
|
private static function getBuscaEspecialidades($params)
|
|
{
|
|
return Especialidade::whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereBetween('data', $params->periodo)
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->when($params->infraestrutura_id ?? null,
|
|
fn ($q, $id) => $q->where('infraestrutura_id', $id),
|
|
fn ($q) => $q->when($params->unidade_id ?? null, fn ($q, $id) => $q
|
|
->whereHas('infraestrutura', fn ($q) => $q->where('unidade_id', $id))
|
|
)
|
|
)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
)
|
|
->whereHas('agendamentos', fn ($q) =>
|
|
self::setBuscaWhereAgendamento($q, $params)
|
|
)
|
|
)
|
|
->orderBy('nome')
|
|
->get(['id', 'nome']);
|
|
}
|
|
|
|
private static function getBuscaUsuarios($params)
|
|
{
|
|
return Usuario::setEagerLoads([])
|
|
->whereHas('lotacoes', fn ($q) => $q
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereBetween('data', $params->periodo)
|
|
->whereHas('agendamentos', fn ($q) =>
|
|
self::setBuscaWhereAgendamento($q, $params)
|
|
)
|
|
->when($params->especialidade_id ?? null, fn ($q, $id) => $q->where('especialidade_id', $id))
|
|
)
|
|
->when($params->infraestrutura_id ?? null,
|
|
fn ($q, $id) => $q->where('infraestrutura_id', $id),
|
|
fn ($q) => $q->when($params->unidade_id ?? null, fn ($q, $id) => $q
|
|
->whereHas('infraestrutura', fn ($q) => $q->where('unidade_id', $id))
|
|
)
|
|
)
|
|
->when($params->ocupacao_id ?? null, fn ($q, $id) => $q->where('ocupacao_id', $id))
|
|
)
|
|
->get(['id', 'cidadao_id'])
|
|
->map(fn ($usuario) => [
|
|
'id' => $usuario->id,
|
|
'nome' => $usuario->cidadao()->setEagerLoads([])->first(['nome'])->nome,
|
|
])
|
|
->sortBy('nome')
|
|
->values();
|
|
}
|
|
|
|
private static function getBuscaTipos($params)
|
|
{
|
|
return AgendamentoTipo::whereHas('agendamentos', fn ($q) =>
|
|
self::setBuscaWhereAgendamento($q, $params)
|
|
->whereHas('jornada', fn ($q) => $q
|
|
->whereBetween('data', $params->periodo)
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->when($params->infraestrutura_id ?? null,
|
|
fn ($q, $id) => $q->where('infraestrutura_id', $id),
|
|
fn ($q) => $q->when($params->unidade_id ?? null, fn ($q, $id) => $q
|
|
->whereHas('infraestrutura', fn ($q) => $q->where('unidade_id', $id))
|
|
)
|
|
)
|
|
->when($params->usuario_id ?? null, fn ($q, $id) => $q->where('usuario_id', $id))
|
|
->when($params->ocupacao_id ?? null, fn ($q, $id) => $q->where('ocupacao_id', $id))
|
|
)
|
|
->when($params->especialidade_id ?? null, fn ($q, $id) => $q->where('especialidade_id', $id))
|
|
)
|
|
)
|
|
->orderBy('nome')
|
|
->get(['id', 'nome']);
|
|
}
|
|
|
|
private static function getBuscaStatus($params)
|
|
{
|
|
return AgendamentoStatus::whereHas('agendamentos', fn ($q) =>
|
|
self::setBuscaWhereAgendamento($q, $params)
|
|
->when($params->tipo_id ?? null, fn ($q, $id) => $q->where('tipo_id', $id))
|
|
->whereHas('jornada', fn ($q) => $q
|
|
->whereBetween('data', $params->periodo)
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->when($params->infraestrutura_id ?? null,
|
|
fn ($q, $id) => $q->where('infraestrutura_id', $id),
|
|
fn ($q) => $q->when($params->unidade_id ?? null, fn ($q, $id) => $q
|
|
->whereHas('infraestrutura', fn ($q) => $q->where('unidade_id', $id))
|
|
)
|
|
)
|
|
->when($params->usuario_id ?? null, fn ($q, $id) => $q->where('usuario_id', $id))
|
|
->when($params->ocupacao_id ?? null, fn ($q, $id) => $q->where('ocupacao_id', $id))
|
|
)
|
|
->when($params->especialidade_id ?? null, fn ($q, $id) => $q->where('especialidade_id', $id))
|
|
)
|
|
)
|
|
->orderBy('nome')
|
|
->get(['id', 'nome']);
|
|
}
|
|
|
|
private static function setBuscaWhereAgendamento($query, $params, $tableAlias = '')
|
|
{
|
|
if (!empty($tableAlias)) {
|
|
|
|
$tableAlias .= '.';
|
|
}
|
|
|
|
return $query->where("{$tableAlias}.paciente_id", $params->paciente_id)
|
|
->when(!is_null($params->inicio ?? null) && !is_null($params->fim ?? null), fn ($q) => $q
|
|
->whereBetween("{$tableAlias}.horario", [$params->inicio, $params->fim])
|
|
);
|
|
}
|
|
|
|
private static function getDadosListCadastro()
|
|
{
|
|
$params = (object) request()->all();
|
|
|
|
$agendamento = Agendamento::find($params->agendamento_id ?? null);
|
|
$paciente = Paciente::setEagerLoads([])->where('id', $params->paciente_id)->first();
|
|
|
|
$tipo = $agendamento->tipo ?? (isset($params->especialidade_id)
|
|
? self::getTipo($params->paciente_id, $params->infraestrutura_id, $params->especialidade_id)
|
|
: null);
|
|
|
|
$params->paciente_nao_municipe = $paciente->classificacao_id !== Classificacao::MUNICIPE;
|
|
$params->tipo_id = $tipo->id ?? null;
|
|
|
|
switch (request()->listar) {
|
|
|
|
case 'unidades': {
|
|
|
|
return [
|
|
'unidades' => self::getCadastroUnidades($params),
|
|
'infraestruturas' => [],
|
|
'ocupacoes' => [],
|
|
'especialidades' => [],
|
|
'usuarios' => [],
|
|
'datas' => [],
|
|
'horarios' => [],
|
|
];
|
|
}
|
|
case 'infraestruturas': {
|
|
|
|
return [
|
|
'infraestruturas' => self::getCadastroInfraestruturas($params),
|
|
'ocupacoes' => [],
|
|
'especialidades' => [],
|
|
'usuarios' => [],
|
|
'datas' => [],
|
|
'horarios' => [],
|
|
];
|
|
}
|
|
case 'ocupacoes': {
|
|
|
|
return [
|
|
'ocupacoes' => self::getCadastroOcupacoes(
|
|
$params,
|
|
$agendamento->jornada->lotacao->ocupacao_id ?? null
|
|
),
|
|
'especialidades' => [],
|
|
'usuarios' => [],
|
|
'datas' => [],
|
|
'horarios' => [],
|
|
];
|
|
}
|
|
case 'especialidades': {
|
|
|
|
return [
|
|
'especialidades' => self::getCadastroEspecialidades(
|
|
$params,
|
|
$agendamento->jornada->especialidade_id ?? null
|
|
),
|
|
'usuarios' => [],
|
|
'datas' => [],
|
|
'horarios' => [],
|
|
];
|
|
}
|
|
case 'usuarios': {
|
|
|
|
return [
|
|
'faltas' => self::getFaltas($params),
|
|
'usuarios' => self::getCadastroUsuarios($params),
|
|
'datas' => [],
|
|
'horarios' => [],
|
|
];
|
|
}
|
|
case 'datas': {
|
|
|
|
return [
|
|
'datas' => self::getCadastroDatas($params),
|
|
'datas_bloqueadas' => self::getCadastroDatasBloqueadas($params),
|
|
'datas_com_agendamento' => self::getCadastroDatasComAgendamento($params),
|
|
'situacao' => self::getCadastroDatasComSituacao($params),
|
|
'horarios' => [],
|
|
];
|
|
}
|
|
case 'horarios': {
|
|
|
|
return [
|
|
'horarios' => self::getCadastroHorarios($params),
|
|
'horarios_com_situacao' => self::getCadastroHorariosComSituacao($params),
|
|
'quantidade_demanda_espontanea' => self::getQuantidadeDemandaEspontanea($params),
|
|
'model' => [
|
|
'demanda_espontanea_observa_vaga_atendimento' => self::getDemandaEspontaneaObservaVagaAtendimento(
|
|
$params->infraestrutura_id,
|
|
$params->especialidade_id,
|
|
),
|
|
],
|
|
'tipo_nome' => $tipo->nome,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function getCadastroUnidades($params)
|
|
{
|
|
$infraestruturaLogada = self::getCurrentCentroCusto()->infraestrutura;
|
|
|
|
return Unidade::whereHas('infraestruturas', fn ($q) => $q
|
|
->where(fn ($q) => $q
|
|
->where('id', $infraestruturaLogada->id)
|
|
->orWhereHas('ambulatorioParametrizacaoJornadaInfraestrutura', fn ($q) => $q
|
|
->whereHas('infraestruturasAgendadoras', fn ($q) => $q
|
|
->where('infraestrutura_id', $infraestruturaLogada->id)
|
|
)
|
|
)
|
|
)
|
|
->whereHas('lotacoes', fn ($q) => $q
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
->orderBy('nome_fantasia')
|
|
->get(['id', 'nome_fantasia']);
|
|
}
|
|
|
|
private static function getCadastroInfraestruturas($params)
|
|
{
|
|
$infraestruturaLogada = self::getCurrentCentroCusto()->infraestrutura;
|
|
|
|
return Infraestrutura::setEagerLoads([])
|
|
->where('unidade_id', $params->unidade_id)
|
|
->where(fn ($q) => $q
|
|
->where('id', $infraestruturaLogada->id)
|
|
->orWhereHas('ambulatorioParametrizacaoJornadaInfraestrutura', fn ($q) => $q
|
|
->whereHas('infraestruturasAgendadoras', fn ($q) => $q
|
|
->where('infraestrutura_id', $infraestruturaLogada->id)
|
|
)
|
|
)
|
|
)
|
|
->whereHas('lotacoes', fn ($q) => $q
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
->get(['id', 'nome', 'principal', 'unidade_id'])
|
|
->map(fn ($infraestrutura) => [
|
|
'id' => $infraestrutura->id,
|
|
'nome' => $infraestrutura->nome
|
|
])
|
|
->sortBy('nome')
|
|
->values();
|
|
}
|
|
|
|
private static function getCadastroOcupacoes($params, $ocupacaoId = null)
|
|
{
|
|
return DB::table('sigtap.ocupacao as ocupacao')
|
|
->when($ocupacaoId, fn ($q, $id) => $q->where('id', $id))
|
|
->whereExists(function ($query) use ($params) {
|
|
|
|
$query->select(DB::raw(1))
|
|
->from('cadastro_lotacao as lotacao')
|
|
->whereColumn('lotacao.ocupacao_id', 'ocupacao.id')
|
|
->where('lotacao.infraestrutura_id', $params->infraestrutura_id)
|
|
->whereExists(function ($query) use ($params) {
|
|
|
|
$query->select(DB::raw(1))
|
|
->from('ambulatorio_jornada as jornada')
|
|
->join(
|
|
'cadastro_especialidade as especialidade',
|
|
'especialidade.id',
|
|
'jornada.especialidade_id'
|
|
)
|
|
->whereColumn('jornada.lotacao_id', 'lotacao.id')
|
|
->whereNull('jornada.situacao_id')
|
|
->whereDate('jornada.data', '>=', Carbon::now())
|
|
->where(fn ($query) => self::setCadastroWhereEspecialidadePaciente(
|
|
$query,
|
|
$params->paciente_id,
|
|
'especialidade'
|
|
))
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('especialidade.permite_agendamento_nao_municipe', true)
|
|
);
|
|
});
|
|
})
|
|
->orderByRaw("CONCAT(ocupacao.codigo, ' - ', ocupacao.nome)")
|
|
->select(DB::raw("
|
|
ocupacao.id,
|
|
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as descricao
|
|
"))
|
|
->get();
|
|
}
|
|
|
|
private static function getCadastroEspecialidades($params, $especialidadeId = null)
|
|
{
|
|
return Especialidade::when($especialidadeId, fn ($q, $id) => $q->where('id', $id))
|
|
->where(fn ($q) => self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id))
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
->orderBy('nome')
|
|
->get(['id', 'nome', 'tratamento', 'permite_agendamento_mesmo_dia','is_regulado']);
|
|
}
|
|
|
|
private static function getFaltas($params)
|
|
{
|
|
$parametrizacao = ParametrizacaoInfraestrutura::where('infraestrutura_id', $params->infraestrutura_id)
|
|
->first();
|
|
|
|
$parametrizacaoEspecialidade = $parametrizacao->especialidades()
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->first();
|
|
|
|
if (is_null($parametrizacaoEspecialidade)
|
|
|| is_null($parametrizacaoEspecialidade->avisa_falta_quantidade)
|
|
) {
|
|
|
|
return collect();
|
|
}
|
|
|
|
$dataAtual = Carbon::today()->endOfDay();
|
|
$data = $dataAtual->copy()->subDays($parametrizacaoEspecialidade->avisa_falta_dias)->startOfDay();
|
|
|
|
$faltas = Agendamento::where('paciente_id', $params->paciente_id)
|
|
->where('status_id', AgendamentoStatusEnum::FALTA_DO_PACIENTE)
|
|
->whereHas('jornada', fn ($q) => $q
|
|
->whereBetween('data', [$data, $dataAtual])
|
|
)
|
|
->get()
|
|
->map(fn ($agendamento) => [
|
|
'data' => $agendamento->jornada->data->format('d/m/Y'),
|
|
'horario' => $agendamento->horario->format('H:i'),
|
|
'especialidade' => $agendamento->jornada->especialidade->nome,
|
|
'usuario' => $agendamento->jornada->lotacao->usuario->cidadao()
|
|
->setEagerLoads([])
|
|
->first(['nome'])
|
|
->nome,
|
|
]);
|
|
|
|
return $faltas->count() >= $parametrizacaoEspecialidade->avisa_falta_quantidade ? $faltas : collect();
|
|
}
|
|
|
|
private static function getCadastroUsuarios($params)
|
|
{
|
|
$campoQuantidade = self::getCampoQuantidade($params->tipo_id);
|
|
|
|
return Usuario::setEagerLoads([])
|
|
->whereHas('lotacoes', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->whereHas('ambulatorioJornadas', fn ($q) => $q
|
|
->whereNotNull($campoQuantidade)
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
->get(['id', 'cidadao_id'])
|
|
->map(fn ($usuario) => [
|
|
'id' => $usuario->id,
|
|
'nome' => $usuario->cidadao()->setEagerLoads([])->first(['nome'])->nome,
|
|
])
|
|
->sortBy('nome')
|
|
->values();
|
|
}
|
|
|
|
private static function getCadastroDatas($params)
|
|
{
|
|
$campoQuantidade = self::getCampoQuantidade($params->tipo_id);
|
|
$campoQuantidadeCidadao = self::getCampoQuantidadeConectasusCidadao($params->tipo_id);
|
|
$feriados = self::getFeriados()->map(fn ($f) => Carbon::createFromFormat('d/m/Y', $f->data)->setTime(0, 0));
|
|
|
|
$jornadasAgrupadas = Jornada::whereNotNull($campoQuantidade)
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
->groupBy('data')
|
|
->select(
|
|
'data',
|
|
DB::raw("SUM({$campoQuantidade}) + SUM(COALESCE({$campoQuantidadeCidadao}, 0)) as quantidade_total")
|
|
)
|
|
->get()
|
|
->reject(function ($jornadasAgrupadas) use ($feriados) {
|
|
|
|
return $feriados->contains($jornadasAgrupadas->data);
|
|
})
|
|
->reject(function ($jornadasAgrupadas) use ($params) {
|
|
|
|
return JornadaBloqueio::where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereDate('inicio', '<=', $jornadasAgrupadas->data)
|
|
->whereDate('fim', '>=', $jornadasAgrupadas->data)
|
|
->where(function ($query) use ($params) {
|
|
$query->whereNull('usuario_id')
|
|
->orWhere('usuario_id', $params->usuario_id);
|
|
})
|
|
->exists();
|
|
})
|
|
->when(
|
|
self::getDataMinimaOcorrencia($params->paciente_id, $params->especialidade_id),
|
|
fn ($collection, $dataMinima) => $collection->reject(
|
|
fn ($jornada) => $jornada->data->lt($dataMinima)
|
|
)
|
|
)
|
|
->values();
|
|
|
|
$agendados = Agendamento::where('tipo_id', $params->tipo_id)
|
|
->whereNotIn('status_id', self::getStatusLiberamHorario())
|
|
->whereHas('jornada', fn ($q) => $q
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
)
|
|
->get()
|
|
->map(fn ($agendamento) => [
|
|
'data' => $agendamento->jornada->data->format('d/m/Y'),
|
|
]);
|
|
|
|
$demandas = DemandaEspontanea::whereHas('jornada', fn ($q) => $q
|
|
->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
)
|
|
->get()
|
|
->map(fn ($demanda) => [
|
|
'data' => $demanda->jornada->data->format('d/m/Y'),
|
|
]);
|
|
|
|
$contagens = [];
|
|
|
|
foreach ($agendados as $agendamento) {
|
|
$data = $agendamento["data"];
|
|
$contagens[$data] = isset($contagens[$data]) ? $contagens[$data] + 1 : 1;
|
|
}
|
|
|
|
foreach ($demandas as $demanda) {
|
|
$data = $demanda["data"];
|
|
$contagens[$data] = isset($contagens[$data]) ? $contagens[$data] + 1 : 1;
|
|
}
|
|
|
|
foreach ($jornadasAgrupadas as &$jornada) {
|
|
$data = $jornada["data"]->format("d/m/Y");
|
|
$jornada["quantidade_agendada"] = $contagens[$data] ?? 0;
|
|
}
|
|
|
|
return $jornadasAgrupadas;
|
|
}
|
|
|
|
private static function getCadastroDatasBloqueadas($params)
|
|
{
|
|
$datas = collect();
|
|
|
|
JornadaBloqueio::where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->where(fn ($q) => $q
|
|
->whereDate('inicio', '>=', Carbon::today())
|
|
->orWhereDate('fim', '>=', Carbon::today())
|
|
)
|
|
->where(function ($query) use ($params) {
|
|
$query->whereNull('usuario_id')
|
|
->orWhere('usuario_id', $params->usuario_id);
|
|
})
|
|
->get(['inicio', 'fim'])
|
|
->each(function ($parametrizacao) use ($datas) {
|
|
|
|
$dataAtual = Carbon::today();
|
|
$data = $parametrizacao->inicio;
|
|
|
|
while ($data <= $parametrizacao->fim) {
|
|
|
|
if ($data >= $dataAtual) {
|
|
|
|
$datas->push($data->format('d/m/Y'));
|
|
}
|
|
|
|
$data->addDay();
|
|
}
|
|
});
|
|
|
|
return $datas;
|
|
}
|
|
private static function getCadastroHorarios($params)
|
|
{
|
|
$horarios = collect();
|
|
$data = Carbon::createFromFormat('d/m/Y', $params->data);
|
|
|
|
$dataMinima = self::getDataMinimaOcorrencia($params->paciente_id, $params->especialidade_id);
|
|
|
|
if ($dataMinima && $data->lt($dataMinima)) {
|
|
return $horarios;
|
|
}
|
|
|
|
Jornada::whereDate('data', $data)
|
|
->whereNotNull(self::getCampoQuantidade($params->tipo_id))
|
|
->whereNull('situacao_id')
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
->get([
|
|
'id',
|
|
'inicio',
|
|
'tipo_id',
|
|
'quantidade_consulta',
|
|
'quantidade_retorno',
|
|
'tempo_consulta',
|
|
'tempo_retorno',
|
|
'quantidade_consulta_conectasus_cidadao',
|
|
'quantidade_retorno_conectasus_cidadao',
|
|
'permite_agendamento_somente_supervisor',
|
|
])
|
|
->each(function ($jornada) use ($horarios, $data, $params) {
|
|
|
|
$jornada->inicio = $data->copy()->setTimeFromTimeString($jornada->inicio);
|
|
|
|
if ($jornada->tipo_id === JornadaTipo::FIXA) {
|
|
|
|
self::setHorarioJornadaFixa($horarios, $jornada, $params->tipo_id);
|
|
}
|
|
else if ($jornada->tipo_id === JornadaTipo::DINAMICA) {
|
|
|
|
self::setHorariosJornadaDinamica($horarios, $jornada, $params->tipo_id);
|
|
}
|
|
});
|
|
|
|
return $horarios->sortBy('horario')->values();
|
|
}
|
|
|
|
private static function setHorarioJornadaFixa($horarios, $jornada, $tipoId)
|
|
{
|
|
$horarios->push((object) [
|
|
'jornada_id' => $jornada->id,
|
|
'horario' => $jornada->inicio->format('H:i'),
|
|
'quantidade_agendada' => Agendamento::where('jornada_id', $jornada->id)
|
|
->where('tipo_id', $tipoId)
|
|
->whereTime('horario', $jornada->inicio)
|
|
->whereNotIn('status_id', self::getStatusLiberamHorario())
|
|
->count(),
|
|
'quantidade_total' => $jornada->{self::getCampoQuantidade($tipoId)}
|
|
+ ($jornada->{self::getCampoQuantidadeConectasusCidadao($tipoId)} ?? 0),
|
|
'obrigatorio_autenticacao_supervisor' => $jornada->permite_agendamento_somente_supervisor
|
|
&& !SupervisorService::isUsuarioLogadoSupervisor(),
|
|
]);
|
|
}
|
|
|
|
private static function setHorariosJornadaDinamica($horarios, $jornada, $tipoId)
|
|
{
|
|
$agendamentos = self::getAgendamentos($jornada->id);
|
|
$agendamentos->each(fn ($a) => $a->horario = $jornada->inicio->copy()->setTimeFromTimeString($a->horario));
|
|
|
|
$agendamentos->where('tipo_id', $tipoId)
|
|
->each(fn ($agendamento) => $horarios->push((object) [
|
|
'jornada_id' => $jornada->id,
|
|
'horario' => $agendamento->horario->format('H:i'),
|
|
'quantidade_agendada' => $agendamento->quantidade_agendada,
|
|
'quantidade_total' => 1,
|
|
'obrigatorio_autenticacao_supervisor' => $jornada->permite_agendamento_somente_supervisor
|
|
&& !SupervisorService::isUsuarioLogadoSupervisor(),
|
|
]));
|
|
|
|
$quantidade = $agendamentos->where('tipo_id', $tipoId)->count();
|
|
|
|
$quantidadeTotal = $jornada->{self::getCampoQuantidade($tipoId)}
|
|
+ ($jornada->{self::getCampoQuantidadeConectasusCidadao($tipoId)} ?? 0);
|
|
|
|
if ($quantidade < $quantidadeTotal) {
|
|
|
|
$data = $jornada->inicio->copy();
|
|
|
|
self::setHorarioJornadaDinamica(
|
|
$horarios,
|
|
$agendamentos,
|
|
$jornada,
|
|
$tipoId,
|
|
$quantidade,
|
|
$data,
|
|
$quantidadeTotal
|
|
);
|
|
}
|
|
}
|
|
|
|
private static function getAgendamentos($jornadaId)
|
|
{
|
|
return Agendamento::where('jornada_id', $jornadaId)
|
|
->whereNotIn('status_id', self::getStatusLiberamHorario())
|
|
->groupBy([
|
|
'tipo_id',
|
|
'horario',
|
|
])
|
|
->orderBy('horario')
|
|
->select(
|
|
'tipo_id',
|
|
'horario',
|
|
DB::raw("COUNT(id) as quantidade_agendada")
|
|
)
|
|
->get();
|
|
}
|
|
|
|
private static function setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data, $quantidadeTotal = null)
|
|
{
|
|
if ($quantidadeTotal === null) {
|
|
$quantidadeTotal = $jornada->{self::getCampoQuantidade($tipoId)}
|
|
+ ($jornada->{self::getCampoQuantidadeConectasusCidadao($tipoId)} ?? 0);
|
|
}
|
|
|
|
$agendamento = $agendamentos->where('horario', $data)->first();
|
|
|
|
if (is_null($agendamento)) {
|
|
|
|
$final = $data->copy()->addMinutes($jornada->{self::getCampoTempo($tipoId)});
|
|
|
|
$agendamento = $agendamentos
|
|
->where('horario', '>', $data)
|
|
->where('horario', '<', $final)
|
|
->first();
|
|
|
|
if ($agendamento) {
|
|
|
|
self::setHorarioJornadaDinamica(
|
|
$horarios,
|
|
$agendamentos,
|
|
$jornada,
|
|
$tipoId,
|
|
$quantidade,
|
|
$agendamento->horario,
|
|
$quantidadeTotal
|
|
);
|
|
}
|
|
else {
|
|
|
|
$horarios->push((object) [
|
|
'jornada_id' => $jornada->id,
|
|
'horario' => $data->format('H:i'),
|
|
'quantidade_agendada' => 0,
|
|
'quantidade_total' => 1,
|
|
'obrigatorio_autenticacao_supervisor' => $jornada->permite_agendamento_somente_supervisor
|
|
&& !SupervisorService::isUsuarioLogadoSupervisor(),
|
|
]);
|
|
|
|
if (++$quantidade < $quantidadeTotal) {
|
|
|
|
$data->addMinutes($jornada->{self::getCampoTempo($tipoId)});
|
|
|
|
self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data, $quantidadeTotal);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
if ($agendamento->tipo_id == $tipoId) {
|
|
|
|
$data->addMinutes($jornada->{self::getCampoTempo($tipoId)});
|
|
|
|
self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data, $quantidadeTotal);
|
|
}
|
|
else {
|
|
|
|
$data = $agendamento->horario->copy()->addMinutes($jornada->{self::getCampoTempo($tipoId, true)});
|
|
|
|
self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data, $quantidadeTotal);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function getCadastroHorariosComSituacao($params)
|
|
{
|
|
return Jornada::whereDate('data', Carbon::createFromFormat('d/m/Y', $params->data))
|
|
->whereNotNull(self::getCampoQuantidade($params->tipo_id))
|
|
->whereNotNull('situacao_id')
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
->orderBy('inicio')
|
|
->get([
|
|
'situacao_id',
|
|
'inicio',
|
|
'fim',
|
|
'data'
|
|
])
|
|
->map(fn ($jornada) => [
|
|
'inicio' => $jornada->inicio->format('H:i'),
|
|
'fim' => $jornada->fim->format('H:i'),
|
|
'situacao_nome' => $jornada->situacao->nome,
|
|
]);
|
|
}
|
|
|
|
private static function getCadastroDatasComSituacao($params){
|
|
|
|
return Jornada::whereNotNull('situacao_id')
|
|
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->join('ambulatorio_jornada_situacao', 'ambulatorio_jornada_situacao.id', 'ambulatorio_jornada.situacao_id')
|
|
->groupBy(['ambulatorio_jornada_situacao.nome', 'ambulatorio_jornada.data'])
|
|
->get([
|
|
'ambulatorio_jornada_situacao.nome as situacao_nome',
|
|
'ambulatorio_jornada.data'
|
|
])
|
|
->map(fn($jornada) =>[
|
|
'data' => $jornada->data->format('d/m/Y'),
|
|
'situacao_nome'=> $jornada->situacao_nome
|
|
]);
|
|
}
|
|
|
|
private static function setCadastroWhereEspecialidadePaciente($query, $pacienteId, $tableAlias = '')
|
|
{
|
|
if (!empty($tableAlias)) {
|
|
|
|
$tableAlias .= '.';
|
|
}
|
|
|
|
$paciente = Paciente::find($pacienteId);
|
|
$idade = $paciente->cidadao->idade;
|
|
|
|
return $query->where(fn ($q) => $q
|
|
->when($idade, fn ($q) => $q
|
|
->where(fn ($q) => $q
|
|
->whereNull("{$tableAlias}idade_minima")
|
|
->orWhere("{$tableAlias}idade_minima", '<=', $idade['anos'])
|
|
)
|
|
->where(fn ($q) => $q
|
|
->whereNull("{$tableAlias}idade_maxima")
|
|
->orWhere("{$tableAlias}idade_maxima", '>=', $idade['anos'])
|
|
)
|
|
)
|
|
->where(fn ($q) => $q
|
|
->whereNull("{$tableAlias}sexo_id")
|
|
->orWhere("{$tableAlias}sexo_id", $paciente->cidadao->sexo_id)
|
|
)
|
|
);
|
|
}
|
|
|
|
private static function getDadosListAgendamentoDemandaEspontanea()
|
|
{
|
|
$params = (object) request()->all();
|
|
|
|
$params->periodo = [
|
|
Carbon::createFromFormat('d/m/Y', $params->periodo['start'])->startOfDay(),
|
|
Carbon::createFromFormat('d/m/Y', $params->periodo['end'])->endOfDay(),
|
|
];
|
|
|
|
switch (request()->listar) {
|
|
|
|
case 'origens': {
|
|
|
|
return [
|
|
'origens' => self::getAgendamentoDemandaEspontaneaOrigens($params),
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
private static function getAgendamentoDemandaEspontaneaOrigens($params)
|
|
{
|
|
$origens = collect();
|
|
|
|
$hasAgendamentos = DB::table('ambulatorio_agendamento AS agendamento')
|
|
->join('ambulatorio_jornada AS jornada', 'jornada.id', 'agendamento.jornada_id')
|
|
->where('agendamento.paciente_id', $params->paciente_id)
|
|
->whereBetween('jornada.data', $params->periodo)
|
|
->exists();
|
|
|
|
if ($hasAgendamentos) {
|
|
$origens->push((object) ['value' => 'consulta-agendada', 'text' => 'Consulta agendada']);
|
|
}
|
|
|
|
$hasDemandasEspontaneas = DB::table('ambulatorio_demanda_espontanea AS demanda_espontanea')
|
|
->where('demanda_espontanea.paciente_id', $params->paciente_id)
|
|
->whereBetween('demanda_espontanea.data', $params->periodo)
|
|
->exists();
|
|
|
|
if ($hasDemandasEspontaneas) {
|
|
$origens->push((object) ['value' => 'demanda-espontanea', 'text' => 'Demanda espontânea']);
|
|
}
|
|
|
|
return $origens;
|
|
}
|
|
|
|
public static function getSugestao($pacienteId, $infraestruturaId, $ocupacaoId, $especialidadeId, $usuarioId)
|
|
{
|
|
$agendamento = Agendamento::find(request()->agendamento_id ?? null);
|
|
$paciente = Paciente::setEagerLoads([])->where('id', $pacienteId)->first();
|
|
$tipo = $agendamento->tipo ?? self::getTipo($pacienteId, $infraestruturaId, $especialidadeId);
|
|
|
|
$datasAgendamentosPaciente = self::getAgendamentosPaciente($pacienteId)
|
|
->map(fn ($agendamento) => Carbon::createFromFormat('d/m/Y', $agendamento['data'])->startOfDay());
|
|
|
|
$params = (object) [
|
|
'paciente_id' => $pacienteId,
|
|
'paciente_nao_municipe' => $paciente->classificacao_id !== Classificacao::MUNICIPE,
|
|
'infraestrutura_id' => $infraestruturaId,
|
|
'ocupacao_id' => $ocupacaoId,
|
|
'especialidade_id' => $especialidadeId,
|
|
'usuario_id' => $usuarioId,
|
|
'tipo_id' => $tipo->id,
|
|
];
|
|
|
|
$horarioDisponivel = null;
|
|
|
|
self::getCadastroDatas($params)
|
|
->each(function ($data) use (&$horarioDisponivel, $params, $pacienteId, $datasAgendamentosPaciente) {
|
|
|
|
if($data->quantidade_agendada >= $data->quantidade_total){
|
|
return true;
|
|
}
|
|
|
|
if ($datasAgendamentosPaciente->contains($data->data->startOfDay())) {
|
|
|
|
return true;
|
|
}
|
|
|
|
$params->data = $data->data->format('d/m/Y');
|
|
$encontrado = false;
|
|
|
|
self::getCadastroHorarios($params)
|
|
->each(function ($horario) use ($data, &$encontrado, &$horarioDisponivel, $pacienteId) {
|
|
|
|
if ($horario->quantidade_agendada < $horario->quantidade_total) {
|
|
|
|
try {
|
|
|
|
self::validateAgendamento($pacienteId, $horario->jornada_id, $horario->horario);
|
|
|
|
$horarioDisponivel = (object) [
|
|
'jornada_id' => $horario->jornada_id,
|
|
'horario' => $horario->horario,
|
|
'data' => $data->data->format('d/m/Y'),
|
|
'dia_semana' => DiaSemana::find($data->dia_semana)->descricao,
|
|
'obrigatorio_autenticacao_supervisor' => $horario->obrigatorio_autenticacao_supervisor,
|
|
];
|
|
|
|
$encontrado = true;
|
|
|
|
return false;
|
|
}
|
|
catch (AgendamentoConflitanteException
|
|
| AgendamentoNaoPermitidoJornadaGrupoException $e
|
|
) { }
|
|
}
|
|
});
|
|
|
|
if ($encontrado) {
|
|
|
|
return false;
|
|
}
|
|
});
|
|
|
|
if (!is_null($horarioDisponivel)) {
|
|
|
|
$horarioDisponivel->tipo_nome = Str::lower($tipo->nome);
|
|
}
|
|
|
|
return $horarioDisponivel;
|
|
}
|
|
|
|
public static function unidadePaciente($pacienteId, $infraestruturaId)
|
|
{
|
|
$possuiJornadaUnidadePaciente = false;
|
|
$parametrizacao = ParametrizacaoAgendamento::first();
|
|
|
|
if ($parametrizacao->avisa_paciente_outra_unidade) {
|
|
|
|
$paciente = Paciente::findOrFail($pacienteId);
|
|
|
|
$unidadeId = Infraestrutura::findOrFail($infraestruturaId)->unidade_id;
|
|
|
|
if ($unidadeId !== $paciente->unidade_id) {
|
|
|
|
$possuiJornadaUnidadePaciente = Unidade::where('id', $paciente->unidade_id)->exists();
|
|
}
|
|
}
|
|
|
|
return [
|
|
'unidade_com_jornada' => $possuiJornadaUnidadePaciente,
|
|
'unidade' => $paciente->unidade->nome_fantasia ?? null,
|
|
];
|
|
}
|
|
|
|
private static function getTipo($pacienteId, $infraestruturaId, $especialidadeId)
|
|
{
|
|
$ultimaData = self::getUltimoDataAgendamento($pacienteId, $infraestruturaId, $especialidadeId);
|
|
$diasParaRetorno = ParametrizacaoService::getQuantidadeDiasRetorno($infraestruturaId, $especialidadeId);
|
|
|
|
$tipoId = $diasParaRetorno === 0 || is_null($ultimaData) || Carbon::today()->diff($ultimaData)->days > $diasParaRetorno
|
|
? AgendamentoTipoEnum::CONSULTA
|
|
: AgendamentoTipoEnum::RETORNO;
|
|
|
|
return AgendamentoTipo::find($tipoId);
|
|
}
|
|
|
|
private static function getUltimoDataAgendamento($pacienteId, $infraestruturaId, $especialidadeId)
|
|
{
|
|
$ultimaJornada = Jornada::where('especialidade_id', $especialidadeId)
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $infraestruturaId)
|
|
)
|
|
->whereHas('agendamentos', fn ($q) => $q
|
|
->where('paciente_id', $pacienteId)
|
|
->where('status_id', AgendamentoStatusEnum::REALIZADO)
|
|
)
|
|
->orderByDesc('data')
|
|
->first(['data']);
|
|
|
|
return is_null($ultimaJornada) ? null : $ultimaJornada->data->startOfDay();
|
|
}
|
|
|
|
private static function getCampoQuantidade($tipoId)
|
|
{
|
|
if ($tipoId === AgendamentoTipoEnum::CONSULTA) {
|
|
|
|
return 'quantidade_consulta';
|
|
}
|
|
else if ($tipoId === AgendamentoTipoEnum::RETORNO) {
|
|
|
|
return 'quantidade_retorno';
|
|
}
|
|
}
|
|
|
|
private static function getCampoQuantidadeConectasusCidadao($tipoId)
|
|
{
|
|
if ($tipoId === AgendamentoTipoEnum::CONSULTA) {
|
|
|
|
return 'quantidade_consulta_conectasus_cidadao';
|
|
}
|
|
else if ($tipoId === AgendamentoTipoEnum::RETORNO) {
|
|
|
|
return 'quantidade_retorno_conectasus_cidadao';
|
|
}
|
|
}
|
|
|
|
private static function getCampoTempo($tipoId, $inverso = false)
|
|
{
|
|
if ($tipoId === AgendamentoTipoEnum::CONSULTA) {
|
|
|
|
return $inverso ? 'tempo_retorno' : 'tempo_consulta';
|
|
}
|
|
else if ($tipoId === AgendamentoTipoEnum::RETORNO) {
|
|
|
|
return $inverso ? 'tempo_consulta' : 'tempo_retorno';
|
|
}
|
|
}
|
|
|
|
private static function getDemandaEspontaneaObservaVagaAtendimento($infraestruturaId, $especialidadeId)
|
|
{
|
|
if (is_null($infraestruturaId) || is_null($especialidadeId)) {
|
|
|
|
return false;
|
|
}
|
|
|
|
$parametrizacao = ParametrizacaoInfraestruturaEspecialidade::whereHas('parametrizacaoInfraestrutura', fn ($q) => $q
|
|
->where('infraestrutura_id', $infraestruturaId)
|
|
)
|
|
->where('especialidade_id', $especialidadeId)
|
|
->first(['demanda_espontanea_observa_vaga_atendimento']);
|
|
|
|
return $parametrizacao->demanda_espontanea_observa_vaga_atendimento ?? false;
|
|
}
|
|
|
|
private static function getDemandaEspontaneaObservaVagaAtendimentoAgendamento($agendamento)
|
|
{
|
|
return self::getDemandaEspontaneaObservaVagaAtendimento(
|
|
$agendamento->jornada->lotacao->infraestrutura_id,
|
|
$agendamento->jornada->especialidade_id,
|
|
);
|
|
}
|
|
|
|
public static function store()
|
|
{
|
|
self::validateStore();
|
|
|
|
$agendamento = new Agendamento();
|
|
$deveIntegrarSafecare = false;
|
|
|
|
DB::transaction(function () use ($agendamento, &$deveIntegrarSafecare) {
|
|
|
|
$jornada = Jornada::findOrFail(request()->jornada_id);
|
|
|
|
self::validateAgendamento(
|
|
request()->paciente_id,
|
|
$jornada->id,
|
|
request()->horario,
|
|
request()->motivo_agendamento_excedente
|
|
);
|
|
|
|
$agendamento->fill([
|
|
'jornada_id' => $jornada->id,
|
|
'tipo_id' => self::getTipo(
|
|
request()->paciente_id,
|
|
$jornada->lotacao->infraestrutura_id,
|
|
$jornada->especialidade_id
|
|
)->id,
|
|
'horario' => request()->horario,
|
|
'paciente_id' => request()->paciente_id,
|
|
'motivo_agendamento_excedente' => request()->motivo_agendamento_excedente,
|
|
'observacao' => request()->observacao,
|
|
'status_id' => AgendamentoStatusEnum::AGENDADO,
|
|
'regulacao_solicitacao_id' => request()->regulacao_solicitacao_id,
|
|
]);
|
|
|
|
$agendamento->save();
|
|
|
|
(new SmsService($agendamento->id))->send();
|
|
|
|
if (optional(ParametrizacaoIntegracaoAplicativo::first())->habilita_integracao_aplicativo_feridas) {
|
|
|
|
$infraestruturaId = $jornada->lotacao->infraestrutura_id;
|
|
|
|
$ocupacaoCodigo = $jornada->lotacao->ocupacao->codigo ?? '';
|
|
|
|
$isEnfermagem = substr($ocupacaoCodigo, 0, 4) == '2235' || substr($ocupacaoCodigo, 0, 4) == '3222';
|
|
|
|
$setorTipo = $isEnfermagem ? SetorTipo::ENFERMAGEM : SetorTipo::CONSULTORIO;
|
|
|
|
$centroCusto = CentroCusto::where('infraestrutura_id', $infraestruturaId)
|
|
->whereHas('setor', function ($query) use ($setorTipo) {
|
|
$query->where('tipo_id', $setorTipo);
|
|
})
|
|
->first();
|
|
|
|
if (!$centroCusto) {
|
|
|
|
$setorNome = $isEnfermagem ? 'enfermagem' : 'consultório';
|
|
|
|
abort(
|
|
Response::HTTP_UNPROCESSABLE_ENTITY,
|
|
"Não foi encontrado um centro de custo de {$setorNome} para a unidade da jornada."
|
|
);
|
|
}
|
|
|
|
$opcaoEntrada = OpcaoEntrada::whereHas('modulo', function ($query) {
|
|
$query->where('identificador', Modulo::AMBULATORIO);
|
|
})
|
|
->whereHas('centroCusto', function ($query) use ($infraestruturaId) {
|
|
$query->where('infraestrutura_id', $infraestruturaId)
|
|
->whereHas('setor', function ($subQuery) {
|
|
$subQuery->where('tipo_id', SetorTipo::RECEPCAO);
|
|
});
|
|
})
|
|
->where('prioridade_obrigatoria', 0)
|
|
->first();
|
|
|
|
if (!$opcaoEntrada) {
|
|
|
|
abort(
|
|
Response::HTTP_UNPROCESSABLE_ENTITY,
|
|
'Não há opção de entrada parametrizada para a recepção da unidade da jornada.'
|
|
);
|
|
}
|
|
|
|
$payload = [
|
|
'paciente_id' => request('paciente_id'),
|
|
'status_id' => Status::EM_ESPERA,
|
|
'opcao_entrada_id' => $opcaoEntrada->id,
|
|
'prioridade_id' => null,
|
|
'centro_custo_id' => $centroCusto->id,
|
|
'data_jornada' => $jornada->data,
|
|
'habilita_integracao_aplicativo_feridas' => optional(ParametrizacaoIntegracaoAplicativo::first())->habilita_integracao_aplicativo_feridas,
|
|
];
|
|
|
|
$fila = FilaService::store((object) $payload);
|
|
$filaId = is_array($fila) ? ($fila['id'] ?? null) : ($fila->id ?? null);
|
|
|
|
$atendimento = new Atendimento();
|
|
|
|
$atendimento->fill([
|
|
'fila_id' => $filaId,
|
|
'paciente_id' => request('paciente_id'),
|
|
'agendamento_id' => $agendamento->id,
|
|
'demanda_espontanea_id' => null,
|
|
]);
|
|
|
|
$atendimento->save();
|
|
|
|
$deveIntegrarSafecare = true;
|
|
}
|
|
});
|
|
|
|
if ($deveIntegrarSafecare) {
|
|
|
|
DB::afterCommit(fn() => self::integrarSafecare($agendamento));
|
|
}
|
|
|
|
$agendamento->refresh();
|
|
|
|
$agendamento->data = $agendamento->jornada()->first('data')->data->format('d/m/Y');
|
|
|
|
return $agendamento;
|
|
}
|
|
|
|
private static function integrarSafecare(Agendamento $agendamento): void
|
|
{
|
|
try {
|
|
app(RegistroPacienteAposAgendamento::class)->integracaoPaciente($agendamento);
|
|
} catch (Throwable $e) {
|
|
logger()->error('Falha na integração Safecare', [
|
|
'agendamento_id' => $agendamento->id,
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString()
|
|
]);
|
|
}
|
|
}
|
|
|
|
private static function validateStore()
|
|
{
|
|
request()->validate([
|
|
'paciente_id' => [
|
|
'required',
|
|
Rule::exists(Paciente::class, 'id'),
|
|
],
|
|
'jornada_id' => [
|
|
'required',
|
|
Rule::exists(Jornada::class, 'id'),
|
|
],
|
|
'horario' => [
|
|
'required',
|
|
'date_format:H:i',
|
|
],
|
|
'observacao' => [
|
|
'nullable',
|
|
'string',
|
|
'max:500',
|
|
],
|
|
'motivo_agendamento_excedente' => [
|
|
'nullable',
|
|
'string',
|
|
'max:500',
|
|
],
|
|
'regulacao_solicitacao_id' => [
|
|
'nullable',
|
|
'integer',
|
|
Rule::exists(RegulacaoSolicitacao::class, 'id'),
|
|
],
|
|
]);
|
|
}
|
|
|
|
public static function update($id)
|
|
{
|
|
self::validateUpdate();
|
|
|
|
$agendamentoAtual = Agendamento::findOrFail($id);
|
|
$agendamentoNovo = new Agendamento();
|
|
|
|
DB::transaction(function () use ($agendamentoAtual, $agendamentoNovo) {
|
|
|
|
if ($agendamentoAtual->status_id !== AgendamentoStatusEnum::AGENDADO) {
|
|
|
|
throw new NaoPodeAlterarStatusAgendamentoException();
|
|
}
|
|
|
|
$jornada = Jornada::findOrFail(request()->jornada_id);
|
|
|
|
self::validateAgendamento(
|
|
$agendamentoAtual->paciente_id,
|
|
$jornada->id,
|
|
request()->horario,
|
|
request()->motivo_agendamento_excedente,
|
|
$agendamentoAtual
|
|
);
|
|
|
|
$agendamentoNovo->fill([
|
|
'agendamento_anterior_id' => $agendamentoAtual->id,
|
|
'jornada_id' => $jornada->id,
|
|
'tipo_id' => $agendamentoAtual->tipo_id,
|
|
'horario' => request()->horario,
|
|
'paciente_id' => $agendamentoAtual->paciente_id,
|
|
'motivo_agendamento_excedente' => request()->motivo_agendamento_excedente,
|
|
'observacao' => request()->observacao,
|
|
'status_id' => AgendamentoStatusEnum::AGENDADO,
|
|
'regulacao_solicitacao_id' => $agendamentoAtual->regulacao_solicitacao_id,
|
|
]);
|
|
|
|
$agendamentoNovo->save();
|
|
|
|
$agendamentoAtual->update(['status_id' => AgendamentoStatusEnum::REAGENDADO_PELO_PACIENTE]);
|
|
|
|
(new SmsService($agendamentoAtual->id))->cancel();
|
|
(new SmsService($agendamentoNovo->id))->send();
|
|
});
|
|
|
|
$agendamentoNovo->refresh();
|
|
|
|
$agendamentoNovo->data = $agendamentoNovo->jornada()->first('data')->data->format('d/m/Y');
|
|
|
|
return $agendamentoNovo;
|
|
}
|
|
|
|
private static function validateUpdate()
|
|
{
|
|
request()->validate([
|
|
'jornada_id' => [
|
|
'required',
|
|
Rule::exists(Jornada::class, 'id'),
|
|
],
|
|
'horario' => [
|
|
'required',
|
|
'date_format:H:i',
|
|
],
|
|
'observacao' => [
|
|
'nullable',
|
|
'string',
|
|
'max:500',
|
|
],
|
|
'motivo_agendamento_excedente' => [
|
|
'nullable',
|
|
'string',
|
|
'max:500',
|
|
]
|
|
]);
|
|
}
|
|
|
|
private static function validateAgendamento(
|
|
$pacienteId,
|
|
$jornadaId,
|
|
$horario,
|
|
$motivoAgendamentoExcedente = null,
|
|
$agendamento = null
|
|
) {
|
|
self::validateProcedimentoGrupo($pacienteId, $jornadaId);
|
|
self::validateConflito($pacienteId, $jornadaId, $horario, $motivoAgendamentoExcedente, $agendamento);
|
|
}
|
|
|
|
private static function validateProcedimentoGrupo($pacienteId, $jornadaId)
|
|
{
|
|
$especialidade = Jornada::findOrFail($jornadaId)->especialidade()
|
|
->first(['procedimento_grupo_codigo']);
|
|
|
|
if (is_null($especialidade->procedimento_grupo_codigo)) {
|
|
|
|
return;
|
|
}
|
|
|
|
$paciente = Paciente::findOrFail($pacienteId);
|
|
|
|
$procedimento = Procedimento::where('codigo', $especialidade->procedimento_grupo_codigo)
|
|
->orderByDesc('competencia_id')
|
|
->first();
|
|
|
|
$validator = new ProcedimentoValidationService($procedimento);
|
|
|
|
if (!$validator->isSexoValid($paciente->cidadao->sexo)
|
|
|| !$validator->isIdadeValid($paciente->cidadao->idade['anos'])
|
|
) {
|
|
|
|
throw new AgendamentoNaoPermitidoJornadaGrupoException();
|
|
}
|
|
}
|
|
|
|
private static function validateConflito(
|
|
$pacienteId,
|
|
$jornadaId,
|
|
$horario,
|
|
$motivoAgendamentoExcedente = null,
|
|
$agendamento = null
|
|
) {
|
|
if (!empty($motivoAgendamentoExcedente)) {
|
|
|
|
return;
|
|
}
|
|
|
|
if (!is_null($agendamento)
|
|
&& $agendamento->jornada_id == $jornadaId
|
|
&& $agendamento->horario->format('H:i') == $horario
|
|
) {
|
|
|
|
return;
|
|
}
|
|
|
|
$paciente = Paciente::findOrFail($pacienteId);
|
|
$jornada = Jornada::findOrFail($jornadaId);
|
|
|
|
$tipo = $agendamento->tipo ?? self::getTipo(
|
|
$paciente->id,
|
|
$jornada->lotacao->infraestrutura_id,
|
|
$jornada->especialidade_id
|
|
);
|
|
|
|
$params = (object) [
|
|
'paciente_id' => $paciente->id,
|
|
'paciente_nao_municipe' => $paciente->classificacao_id !== Classificacao::MUNICIPE,
|
|
'unidade_id' => $jornada->lotacao->infraestrutura->unidade_id,
|
|
'infraestrutura_id' => $jornada->lotacao->infraestrutura_id,
|
|
'ocupacao_id' => $jornada->lotacao->ocupacao_id,
|
|
'especialidade_id' => $jornada->especialidade_id,
|
|
'usuario_id' => $jornada->lotacao->usuario_id,
|
|
'data' => $jornada->data->format('d/m/Y'),
|
|
'tipo_id' => $tipo->id,
|
|
];
|
|
|
|
$horarioJornada = self::getCadastroHorarios($params)->where('horario', $horario)->first();
|
|
|
|
$agendamento = Agendamento::where('jornada_id', $jornadaId)
|
|
->where('horario', $horario)
|
|
->whereNotIn('status_id', self::getStatusLiberamHorario())
|
|
->first();
|
|
|
|
if (!is_null($agendamento)) {
|
|
|
|
if ($jornada->tipo_id === JornadaTipo::FIXA
|
|
&& $horarioJornada->quantidade_agendada < $horarioJornada->quantidade_total
|
|
) {
|
|
|
|
return;
|
|
}
|
|
|
|
throw new AgendamentoConflitanteException();
|
|
}
|
|
}
|
|
|
|
public static function getStatusLiberamHorario()
|
|
{
|
|
return [
|
|
AgendamentoStatusEnum::REAGENDADO_PELO_PACIENTE,
|
|
AgendamentoStatusEnum::REAGENDADO_PELO_MEDICO,
|
|
AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE,
|
|
AgendamentoStatusEnum::CANCELADO_PELO_MEDICO,
|
|
];
|
|
}
|
|
|
|
private static function getDataMinimaOcorrencia($pacienteId, $especialidadeId)
|
|
{
|
|
$especialidade = DB::table('cadastro_especialidade')
|
|
->where('id', $especialidadeId)
|
|
->first(['limite_ocorrencias_paciente', 'periodo_monitoramento', 'tempo_liberacao']);
|
|
|
|
if (is_null($especialidade)
|
|
|| is_null($especialidade->limite_ocorrencias_paciente)
|
|
|| is_null($especialidade->periodo_monitoramento)
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
$dataInicio = Carbon::today()->subDays($especialidade->periodo_monitoramento);
|
|
|
|
$baseQuery = fn () => DB::table('ambulatorio_agendamento as agendamento')
|
|
->join('ambulatorio_jornada as jornada', 'jornada.id', 'agendamento.jornada_id')
|
|
->where('agendamento.paciente_id', $pacienteId)
|
|
->where('jornada.especialidade_id', $especialidadeId)
|
|
->whereDate('jornada.data', '>=', $dataInicio)
|
|
->whereIn('agendamento.status_id', [
|
|
AgendamentoStatusEnum::FALTA_DO_PACIENTE,
|
|
AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE,
|
|
]);
|
|
|
|
$ocorrencias = $baseQuery()->count();
|
|
|
|
if ($ocorrencias < $especialidade->limite_ocorrencias_paciente) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$tempoLiberacao = $especialidade->tempo_liberacao ?? 0;
|
|
|
|
if ($tempoLiberacao === 0) {
|
|
|
|
return null;
|
|
}
|
|
|
|
$ultimaOcorrencia = $baseQuery()->max('jornada.data');
|
|
|
|
if (is_null($ultimaOcorrencia)) {
|
|
|
|
return null;
|
|
}
|
|
|
|
return Carbon::parse($ultimaOcorrencia)->addDays($tempoLiberacao);
|
|
}
|
|
|
|
public static function cancel($id, $params)
|
|
{
|
|
self::validateCancel($params);
|
|
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
if ($agendamento->status_id !== AgendamentoStatusEnum::AGENDADO) {
|
|
|
|
throw new NaoPodeAlterarStatusAgendamentoException();
|
|
}
|
|
|
|
DB::transaction(function () use ($agendamento, $params) {
|
|
|
|
$agendamento->update([
|
|
'status_id' => AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE,
|
|
'motivo_cancelamento' => $params['motivo'],
|
|
]);
|
|
|
|
(new SmsService($agendamento->id))->cancel();
|
|
|
|
if (!is_null($agendamento->regulacao_solicitacao_id) && !($params['is_from_regulacao'] ?? false)) {
|
|
|
|
RegulacaoSolicitacaoService::updateStatus(
|
|
$agendamento->regulacao_solicitacao_id,
|
|
RegulacaoStatusTipo::CANCELADO,
|
|
['justificativa' => $params['motivo']],
|
|
);
|
|
}
|
|
});
|
|
|
|
return $agendamento->fresh();
|
|
}
|
|
|
|
private static function validateCancel($params)
|
|
{
|
|
Validator::make($params, [
|
|
'motivo' => [
|
|
'required',
|
|
'string',
|
|
'max:500',
|
|
]
|
|
])->validate();
|
|
}
|
|
|
|
public static function destroy($id)
|
|
{
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
if ($agendamento->status_id !== AgendamentoStatusEnum::AGENDADO) {
|
|
|
|
throw new NaoPodeExcluirAgendamentoException();
|
|
}
|
|
|
|
DB::transaction(function () use ($agendamento) {
|
|
|
|
if (!is_null($agendamento->regulacao_solicitacao_id)) {
|
|
|
|
RegulacaoSolicitacaoService::updateStatus(
|
|
$agendamento->regulacao_solicitacao_id,
|
|
RegulacaoStatusTipo::CANCELADO,
|
|
['justificativa' => 'Cancelado automaticamente pela funcionalidade Agendamento'],
|
|
);
|
|
}
|
|
|
|
(new SmsService($agendamento->id))->cancel();
|
|
|
|
$agendamento->delete();
|
|
});
|
|
}
|
|
|
|
public static function absent($id, $params = [])
|
|
{
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
DB::transaction(function () use ($agendamento, $params) {
|
|
|
|
$agendamento->update(['status_id' => AgendamentoStatusEnum::FALTA_DO_PACIENTE]);
|
|
|
|
if (!is_null($agendamento->regulacao_solicitacao_id) && !($params['is_from_regulacao'] ?? false)) {
|
|
|
|
RegulacaoSolicitacaoService::updateStatus(
|
|
$agendamento->regulacao_solicitacao_id,
|
|
RegulacaoStatusTipo::FALTA
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
public static function undoAbsent($id)
|
|
{
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
if ($agendamento->status_id === AgendamentoStatusEnum::FALTA_DO_PACIENTE) {
|
|
|
|
DB::transaction(function () use ($agendamento) {
|
|
|
|
$agendamento->update(['status_id' => AgendamentoStatusEnum::AGENDADO]);
|
|
});
|
|
}
|
|
}
|
|
|
|
public static function getPrintData($id)
|
|
{
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
return [
|
|
'isPrintExterno' => false,
|
|
'unidade' => [
|
|
'nome_fantasia' => $agendamento->jornada->lotacao->infraestrutura->unidade->nome_fantasia
|
|
],
|
|
'infraestrutura' => [
|
|
'nome' => $agendamento->jornada->lotacao->infraestrutura->nome,
|
|
'endereco' => $agendamento->jornada->lotacao->infraestrutura->endereco->completo,
|
|
'telefone' => MaskUtil::getPhoneMasked($agendamento->jornada->lotacao->infraestrutura->telefone),
|
|
],
|
|
'paciente' => [
|
|
'nome' => $agendamento->paciente->cidadao->nome,
|
|
'nome_social' => $agendamento->paciente->cidadao->nome_social,
|
|
'prontuario' => $agendamento->paciente->prontuario,
|
|
],
|
|
'tipo' => [
|
|
'nome' => $agendamento->tipo->nome,
|
|
],
|
|
'data' => $agendamento->jornada->data->format('d/m/Y'),
|
|
'diaSemana' => DiaSemana::findOrFail($agendamento->jornada->dia_semana)->descricao,
|
|
'horario' => $agendamento->horario->format('H:i'),
|
|
'usuario' => [
|
|
'nome' => $agendamento->jornada->lotacao->usuario->cidadao->nome,
|
|
],
|
|
'especialidade' => [
|
|
'nome' => $agendamento->jornada->especialidade->nome,
|
|
'mensagem_protocolo_agendamento' => $agendamento->jornada->especialidade->mensagem_protocolo_agendamento,
|
|
],
|
|
'regulacaoMensagemComprovanteAgendamento' => is_null($agendamento->regulacaoSolicitacao)
|
|
? null
|
|
: RegulacaoParametrizacao::first()->mensagem_comprovante_agendamento ?? null,
|
|
'regulacaoProtocoloFechamento' => is_null($agendamento->regulacaoSolicitacao)
|
|
? null
|
|
: $agendamento->regulacaoSolicitacao->numero ?? null,
|
|
'observacao' => $agendamento->observacao,
|
|
'usuarioAgendamento' => [
|
|
'nome' => $agendamento->createdLotacao->usuario->cidadao->nome,
|
|
'nome_social' => $agendamento->createdLotacao->usuario->cidadao->nome_social,
|
|
'data_hora' => $agendamento->created_at->format('d/m/Y \à\s H:i'),
|
|
'unidade' => $agendamento->createdCentroCusto->infraestrutura->unidade->nome_fantasia,
|
|
'infraestrutura' => $agendamento->createdCentroCusto->infraestrutura->nome,
|
|
'setor' => $agendamento->createdCentroCusto->setor->nome,
|
|
],
|
|
];
|
|
}
|
|
|
|
public static function getPrintDataExterno($id)
|
|
{
|
|
|
|
$solicitacao = RegulacaoSolicitacao::findOrFail($id);
|
|
|
|
$tipo = $solicitacao->prestadorExterno->destino->tipo->descricao ?? '';
|
|
$logradouro = $solicitacao->prestadorExterno->destino->nome_logradouro ?? '';
|
|
$numero = $solicitacao->prestadorExterno->destino->numero_logradouro ? $solicitacao->prestadorExterno->destino->numero_logradouro : 'S/N';
|
|
$bairro = $solicitacao->prestadorExterno->destino->nome_bairro;
|
|
$municipio = $solicitacao->prestadorExterno->destino->municipio->nome ?? '';
|
|
$uf = $solicitacao->prestadorExterno->destino->municipio->estado->uf ?? '';
|
|
|
|
$completo = "{$tipo} {$logradouro}, {$numero} - {$bairro}, {$municipio} - {$uf}";
|
|
|
|
return [
|
|
'isPrintExterno' => true,
|
|
'unidade' => [
|
|
'nome_fantasia' => null,
|
|
],
|
|
'infraestrutura' => [
|
|
'nome' => $solicitacao->prestadorExterno->destino->descricao_destino,
|
|
'endereco' => $completo,
|
|
'telefone' => MaskUtil::getPhoneMasked($solicitacao->prestadorExterno->destino->numero_telefone_comercial),
|
|
],
|
|
'paciente' => [
|
|
'nome' => $solicitacao->paciente->cidadao->nome,
|
|
'nome_social' => $solicitacao->paciente->cidadao->nome_social,
|
|
'prontuario' => $solicitacao->paciente->prontuario,
|
|
],
|
|
'tipo' => [
|
|
'nome' => 'CONSULTA',
|
|
],
|
|
'data' => $solicitacao->data_agendada->format('d/m/Y'),
|
|
'diaSemana' => DiaSemana::findOrFail($solicitacao->data_agendada->dayOfWeek + 1)->descricao,
|
|
'horario' => $solicitacao->hora_agendada->format('H:i'),
|
|
'usuario' => [
|
|
'nome' => $solicitacao->lotacaUsuario->usuario->cidadao->nome,
|
|
],
|
|
'especialidade' => [
|
|
'nome' => $solicitacao->itens()->first()->especialidade->nome,
|
|
'mensagem_protocolo_agendamento' => $solicitacao->itens()->first()->especialidade->mensagem_protocolo_agendamento,
|
|
],
|
|
'regulacaoMensagemComprovanteAgendamento' => RegulacaoParametrizacao::first()->mensagem_comprovante_agendamento ?? null,
|
|
'regulacaoProtocoloFechamento' => $solicitacao->numero ?? null,
|
|
'observacao' => $solicitacao->observacao,
|
|
'usuarioAgendamento' => [
|
|
'nome' => $solicitacao->createdLotacao->usuario->cidadao->nome,
|
|
'data_hora' => $solicitacao->created_at->format('d/m/Y \à\s H:i'),
|
|
'unidade' => $solicitacao->createdCentroCusto->infraestrutura->unidade->nome_fantasia,
|
|
'infraestrutura' => $solicitacao->createdCentroCusto->infraestrutura->nome,
|
|
'setor' => $solicitacao->createdCentroCusto->setor->nome,
|
|
],
|
|
];
|
|
}
|
|
|
|
private static function getPermissoesAtualizacaoCadastroPaciente()
|
|
{
|
|
$parametrizacao = CnsService::getParametrizacao();
|
|
|
|
if (!is_null($parametrizacao)) {
|
|
$lotacao = self::getCurrentLotacao();
|
|
|
|
return DB::table('cadastro_parametrizacao_permissao_usuario')
|
|
->select([
|
|
'municipe',
|
|
'provisorio',
|
|
'outro_municipio',
|
|
])
|
|
->where('infraestrutura_id', $lotacao->infraestrutura_id)
|
|
->where('usuario_id', $lotacao->usuario_id)
|
|
->get()
|
|
->first();
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static function getQuantidadeDemandaEspontanea($params)
|
|
{
|
|
return DemandaEspontanea::whereHas('jornada', fn ($q) =>
|
|
$q->whereDate('data', '>=', Carbon::now())
|
|
->whereHas('lotacao', fn ($q) => $q
|
|
->where('infraestrutura_id', $params->infraestrutura_id)
|
|
->where('ocupacao_id', $params->ocupacao_id)
|
|
->where('usuario_id', $params->usuario_id)
|
|
)
|
|
->where('especialidade_id', $params->especialidade_id)
|
|
->whereHas('especialidade', fn ($q) =>
|
|
self::setCadastroWhereEspecialidadePaciente($q, $params->paciente_id)
|
|
->when($params->paciente_nao_municipe, fn ($q) => $q
|
|
->where('permite_agendamento_nao_municipe', true)
|
|
)
|
|
)
|
|
)
|
|
->count();
|
|
}
|
|
|
|
public static function createAgendamentoDemandaEspontanea($pacienteId)
|
|
{
|
|
$agendamentosDemandas = self::getAgendamentosDemandasEspontaneas((object) [
|
|
'paciente_id' => $pacienteId,
|
|
'periodo' => [
|
|
'start' => Carbon::now()->subYear()->format('d/m/Y'),
|
|
'end' => Carbon::now()->format('d/m/Y'),
|
|
],
|
|
'origem' => null,
|
|
]);
|
|
|
|
$itens = $agendamentosDemandas['itens'];
|
|
|
|
$formFilters = [
|
|
'origens' => [],
|
|
];
|
|
|
|
$modelFilters = [
|
|
'periodo' => ['start' => null, 'end' => null],
|
|
'origem' => null
|
|
];
|
|
|
|
if ($itens->isNotEmpty()) {
|
|
$filters = self::getAgendamentoDemandaEspontaneaFilters($pacienteId, $itens);
|
|
|
|
$formFilters['origens'] = $filters->form['origens'];
|
|
$modelFilters['periodo'] = $filters->model['periodo'];
|
|
}
|
|
|
|
return [
|
|
'form' => $formFilters,
|
|
'model' => $modelFilters,
|
|
'itens' => $itens,
|
|
'totalizadores' => $agendamentosDemandas['totalizadores'],
|
|
];
|
|
}
|
|
|
|
private static function getAgendamentoDemandaEspontaneaFilters($pacienteId, $itens)
|
|
{
|
|
$datas = collect();
|
|
|
|
$itens->each(fn ($agendamento) => $datas
|
|
->push(Carbon::createFromFormat('Y-m-d', $agendamento->data))
|
|
);
|
|
|
|
$datas = $datas->sort();
|
|
|
|
$periodo = [
|
|
'start' => $datas->first()->copy()->startOfDay(),
|
|
'end' => $datas->last()->copy()->endOfDay(),
|
|
];
|
|
|
|
$params = (object) [
|
|
'paciente_id' => $pacienteId,
|
|
'periodo' => $periodo,
|
|
];
|
|
|
|
return (object) [
|
|
'form' => [
|
|
'origens' => self::getAgendamentoDemandaEspontaneaOrigens($params),
|
|
],
|
|
'model' => [
|
|
'periodo' => [
|
|
'start' => $periodo['start']->format('d/m/Y'),
|
|
'end' => $periodo['end']->format('d/m/Y'),
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
public static function getAgendamentosDemandasEspontaneas($params)
|
|
{
|
|
$params->periodo = [
|
|
Carbon::createFromFormat('d/m/Y', $params->periodo['start'])->startOfDay(),
|
|
Carbon::createFromFormat('d/m/Y', $params->periodo['end'])->endOfDay(),
|
|
];
|
|
|
|
$getAgendamentosBuilder = fn () => DB::table('ambulatorio_agendamento as agendamento')
|
|
->join('ambulatorio_agendamento_status as status', 'status.id', 'agendamento.status_id')
|
|
->join('ambulatorio_agendamento_tipo as tipo', 'tipo.id', 'agendamento.tipo_id')
|
|
->join('ambulatorio_jornada as jornada', 'jornada.id', 'agendamento.jornada_id')
|
|
->join('cadastro_lotacao as lotacao', 'lotacao.id', 'jornada.lotacao_id')
|
|
->join('cadastro_infraestrutura as infraestrutura', 'infraestrutura.id', 'lotacao.infraestrutura_id')
|
|
->join('cadastro_unidade as unidade', 'unidade.id', 'infraestrutura.unidade_id')
|
|
->join('cadastro_usuario as usuario', 'usuario.id', 'lotacao.usuario_id')
|
|
->join('cadastro_cidadao as cidadao', 'cidadao.id', 'usuario.cidadao_id')
|
|
->join('sigtap.ocupacao as ocupacao', 'ocupacao.id', 'lotacao.ocupacao_id')
|
|
->join('cadastro_especialidade as especialidade', 'especialidade.id', 'jornada.especialidade_id')
|
|
->where('agendamento.paciente_id', $params->paciente_id)
|
|
->whereBetween('jornada.data', $params->periodo)
|
|
->select(DB::raw("
|
|
'Consulta agendada' as origem,
|
|
unidade.nome_fantasia as unidade,
|
|
COALESCE(infraestrutura.nome, unidade.nome_fantasia) as infraestrutura,
|
|
cidadao.nome as usuario,
|
|
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as ocupacao,
|
|
especialidade.nome as especialidade,
|
|
tipo.nome as tipo,
|
|
jornada.data,
|
|
DATE_FORMAT(agendamento.horario, '%H:%i') as horario,
|
|
status.id as status_id,
|
|
status.nome as status
|
|
"));
|
|
|
|
$getDemandasEspontaneasBuilder = fn () => DB::table('ambulatorio_demanda_espontanea as demanda_espontanea')
|
|
->join('ambulatorio_atendimento as atendimento', 'atendimento.demanda_espontanea_id', 'demanda_espontanea.id')
|
|
->join('painel_senha_fila as fila', 'fila.id', 'atendimento.fila_id')
|
|
->join('cadastro_lotacao as lotacao', 'lotacao.id', 'demanda_espontanea.created_lotacao_id')
|
|
->join('cadastro_infraestrutura as infraestrutura', 'infraestrutura.id', 'lotacao.infraestrutura_id')
|
|
->join('cadastro_unidade as unidade', 'unidade.id', 'infraestrutura.unidade_id')
|
|
->leftJoin('cadastro_usuario as usuario', 'usuario.id', 'demanda_espontanea.usuario_id')
|
|
->leftJoin('cadastro_cidadao as cidadao', 'cidadao.id', 'usuario.cidadao_id')
|
|
->leftJoin('sigtap.ocupacao as ocupacao', 'ocupacao.id', 'demanda_espontanea.ocupacao_id')
|
|
->leftJoin('cadastro_especialidade as especialidade', 'especialidade.id', 'demanda_espontanea.especialidade_id')
|
|
->where('demanda_espontanea.paciente_id', $params->paciente_id)
|
|
->whereBetween('demanda_espontanea.data', $params->periodo)
|
|
->select(DB::raw("
|
|
'Demanda espontânea' as origem,
|
|
unidade.nome_fantasia as unidade,
|
|
COALESCE(infraestrutura.nome, unidade.nome_fantasia) as infraestrutura,
|
|
cidadao.nome as usuario,
|
|
CONCAT(ocupacao.codigo, ' - ', ocupacao.nome) as ocupacao,
|
|
especialidade.nome as especialidade,
|
|
'CONSULTA' as tipo,
|
|
demanda_espontanea.data,
|
|
DATE_FORMAT(demanda_espontanea.created_at, '%H:%i') as horario,
|
|
IF(fila.evadido = 1,
|
|
" . AgendamentoStatusEnum::EVADIDO . ",
|
|
IF(atendimento.finalizado_em IS NULL, 'em-aberto', " . AgendamentoStatusEnum::REALIZADO . ")
|
|
) as status_id,
|
|
IF(fila.evadido = 1, 'EVADIDO', IF(atendimento.finalizado_em IS NULL, 'EM ABERTO', 'REALIZADO')) as status
|
|
"));
|
|
|
|
$builder = null;
|
|
|
|
if ($params->origem === 'consulta-agendada') {
|
|
$builder = $getAgendamentosBuilder();
|
|
}
|
|
else if ($params->origem === 'demanda-espontanea') {
|
|
$builder = $getDemandasEspontaneasBuilder();
|
|
}
|
|
else {
|
|
$builder = $getAgendamentosBuilder()->union($getDemandasEspontaneasBuilder());
|
|
}
|
|
|
|
self::setAgendamentosDemandasEspontaneasOrderBy($builder);
|
|
|
|
$itens = $builder->get();
|
|
|
|
$totalizadores = (object) [
|
|
'agendado' => $itens->where('status_id', AgendamentoStatusEnum::AGENDADO)->count(),
|
|
'realizado' => $itens->where('status_id', AgendamentoStatusEnum::REALIZADO)->count(),
|
|
'reagendado_pelo_paciente' => $itens->where('status_id', AgendamentoStatusEnum::REAGENDADO_PELO_PACIENTE)->count(),
|
|
'reagendado_pelo_medico' => $itens->where('status_id', AgendamentoStatusEnum::REAGENDADO_PELO_MEDICO)->count(),
|
|
'cancelado_pelo_paciente' => $itens->where('status_id', AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE)->count(),
|
|
'cancelado_pelo_medico' => $itens->where('status_id', AgendamentoStatusEnum::CANCELADO_PELO_MEDICO)->count(),
|
|
'falta_paciente' => $itens->where('status_id', AgendamentoStatusEnum::FALTA_DO_PACIENTE)->count(),
|
|
'falta_medico' => $itens->where('status_id', AgendamentoStatusEnum::FALTA_DO_MEDICO)->count(),
|
|
'em_aberto' => $itens->where('status_id', 'em-aberto')->count(),
|
|
'evadido' => $itens->where('status_id', AgendamentoStatusEnum::EVADIDO)->count(),
|
|
'geral' => $itens->count(),
|
|
];
|
|
|
|
return compact('itens', 'totalizadores');
|
|
}
|
|
|
|
private static function setAgendamentosDemandasEspontaneasOrderBy($builder)
|
|
{
|
|
$columns = [
|
|
'origem' => 'origem',
|
|
'unidade' => 'unidade',
|
|
'infraestrutura' => 'infraestrutura',
|
|
'usuario' => 'usuario',
|
|
'ocupacao' => 'ocupacao',
|
|
'especialidade' => 'especialidade',
|
|
'tipo' => 'tipo',
|
|
'data' => 'data',
|
|
'horario' => 'horario',
|
|
'status' => 'status',
|
|
];
|
|
|
|
if (is_null(request()->sort_by)) {
|
|
|
|
$builder->orderByRaw(join(', ', $columns));
|
|
|
|
return;
|
|
}
|
|
|
|
$column = $columns[request()->sort_by];
|
|
$direction = DataUtil::getBooleanValueFromStringBoolean(request()->sort_desc) ? 'DESC' : 'ASC';
|
|
|
|
unset($columns[request()->sort_by]);
|
|
|
|
$builder->orderByRaw(
|
|
"{$column} {$direction}, " . join(', ', $columns)
|
|
);
|
|
}
|
|
}
|