619 lines
24 KiB
PHP
619 lines
24 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Mobile\ConectaCidadao\Agendamento;
|
|
|
|
use App\Enums\Administracao\Modulo as ModuloEnum;
|
|
use App\Enums\Ambulatorio\AgendamentoStatus as AgendamentoStatusEnum;
|
|
use App\Enums\Ambulatorio\AgendamentoTipo as AgendamentoTipoEnum;
|
|
use App\Models\Ambulatorio\Agendamento;
|
|
use App\Models\Ambulatorio\Jornada;
|
|
use App\Models\Cadastro\Feriado\Feriado;
|
|
use App\Services\Ambulatorio\AgendamentoService as AmbulatorioAgendamentoService;
|
|
use App\Services\Ambulatorio\ParametrizacaoService;
|
|
use App\Services\Service;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class AgendamentoService extends Service
|
|
{
|
|
public static function especialidades()
|
|
{
|
|
request()->validate(
|
|
[
|
|
'unidade_id' => 'required|integer',
|
|
]
|
|
);
|
|
|
|
$unidadeId = request()->unidade_id;
|
|
$paciente = auth('mobile')->user();
|
|
|
|
$especialidades = DB::table('cadastro_especialidade as especialidade')
|
|
->where('especialidade.permite_integracao_conectasus_cidadao', true)
|
|
->whereExists(function ($query) use ($unidadeId) {
|
|
$query->select(DB::raw(1))
|
|
->from('ambulatorio_jornada as jornada')
|
|
->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')
|
|
->whereColumn('jornada.especialidade_id', 'especialidade.id')
|
|
->where('unidade.id', $unidadeId)
|
|
->whereNull('jornada.situacao_id')
|
|
->whereDate('jornada.data', '>=', Carbon::today())
|
|
->where(function ($q) {
|
|
$q->where('jornada.quantidade_consulta_conectasus_cidadao', '>', 0)
|
|
->orWhere('jornada.quantidade_retorno_conectasus_cidadao', '>', 0);
|
|
});
|
|
})
|
|
->where(fn ($q) => self::filtrarEspecialidadePorPaciente($q, $paciente, 'especialidade'))
|
|
->orderBy('especialidade.nome')
|
|
->get(['especialidade.id', 'especialidade.nome']);
|
|
|
|
return $especialidades->map(function ($especialidade) use ($paciente) {
|
|
$bloqueadoAte = self::validarBloqueioFaltas($paciente->id, $especialidade->id);
|
|
$especialidade->bloqueado_ate = $bloqueadoAte ? $bloqueadoAte->format('Y-m-d') : null;
|
|
|
|
return $especialidade;
|
|
});
|
|
}
|
|
|
|
public static function vagas()
|
|
{
|
|
request()->validate(
|
|
[
|
|
'unidade_id' => 'required|integer',
|
|
'especialidade_id' => 'required|integer',
|
|
]
|
|
);
|
|
|
|
$unidadeId = request()->unidade_id;
|
|
$especialidadeId = request()->especialidade_id;
|
|
$paciente = auth('mobile')->user();
|
|
|
|
$vagas = collect();
|
|
|
|
$feriadoDatas = self::getFeriadoDatas();
|
|
|
|
$jornadas = Jornada::where('especialidade_id', $especialidadeId)
|
|
->whereNull('situacao_id')
|
|
->whereDate('data', '>=', Carbon::today())
|
|
->whereNotIn('data', $feriadoDatas)
|
|
->where(function ($q) {
|
|
$q->where('quantidade_consulta_conectasus_cidadao', '>', 0)
|
|
->orWhere('quantidade_retorno_conectasus_cidadao', '>', 0);
|
|
})
|
|
->whereHas('lotacao', function ($q) use ($unidadeId) {
|
|
$q->whereHas('infraestrutura', function ($q2) use ($unidadeId) {
|
|
$q2->where('unidade_id', $unidadeId);
|
|
});
|
|
})
|
|
->whereHas('especialidade', fn ($q) => self::filtrarEspecialidadePorPaciente($q, $paciente))
|
|
->with(['lotacao.usuario.cidadao'])
|
|
->orderBy('data')
|
|
->orderBy('inicio')
|
|
->get();
|
|
|
|
foreach ($jornadas as $jornada) {
|
|
|
|
self::calcularVagasJornada($vagas, $jornada);
|
|
}
|
|
|
|
return [
|
|
'vagas' => $vagas->sortBy('data_hora')->values(),
|
|
'feriados' => self::getFeriados(),
|
|
];
|
|
}
|
|
|
|
public static function store()
|
|
{
|
|
request()->validate(
|
|
[
|
|
'jornada_id' => 'required|integer|exists:ambulatorio_jornada,id',
|
|
'horario' => 'required|date_format:H:i',
|
|
'observacao' => 'nullable|string|max:500',
|
|
]
|
|
);
|
|
|
|
$paciente = auth('mobile')->user();
|
|
$jornada = Jornada::findOrFail(request()->jornada_id);
|
|
$unidadeJornada = $jornada->lotacao->infraestrutura->unidade;
|
|
|
|
if ($unidadeJornada->id !== $paciente->unidade_id) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'A unidade informada não é a sua unidade de referência.');
|
|
}
|
|
|
|
$especialidadePermitida = self::filtrarEspecialidadePorPaciente(
|
|
$jornada->especialidade()->getQuery(),
|
|
$paciente
|
|
)->exists();
|
|
|
|
if (!$especialidadePermitida) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Você não está elegível para agendar nesta especialidade.');
|
|
}
|
|
|
|
$bloqueadoAte = self::validarBloqueioFaltas($paciente->id, $jornada->especialidade_id);
|
|
|
|
if ($bloqueadoAte) {
|
|
|
|
abort(response()->json([
|
|
'message' => 'Você está temporariamente bloqueado para agendamento nesta especialidade devido a faltas ou cancelamentos.',
|
|
'bloqueado_ate' => $bloqueadoAte->format('Y-m-d'),
|
|
], Response::HTTP_UNPROCESSABLE_ENTITY));
|
|
}
|
|
$dataHoraAgendamento = Carbon::parse($jornada->data->format('Y-m-d') . ' ' . request()->horario);
|
|
|
|
if ($dataHoraAgendamento->isPast()) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Não é possível agendar em horário retroativo.');
|
|
}
|
|
|
|
$ehFeriado = Feriado::whereHas('modulos', fn($q) => $q->where('identificador', ModuloEnum::AMBULATORIO))
|
|
->whereDate('data', $jornada->data->format('Y-m-d'))
|
|
->exists();
|
|
|
|
if ($ehFeriado) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Não é possível agendar em dias de feriado.');
|
|
}
|
|
|
|
self::validarAgendamentoDuplicado($paciente->id, $jornada);
|
|
self::validarVagaDisponivel($jornada, request()->horario);
|
|
|
|
/** @var Agendamento $agendamento */
|
|
$agendamento = DB::transaction(function () use ($jornada, $paciente) {
|
|
$agendamento = new Agendamento();
|
|
|
|
$agendamento->fill([
|
|
'jornada_id' => $jornada->id,
|
|
'tipo_id' => self::getTipoAgendamento(
|
|
$paciente->id,
|
|
$jornada->lotacao->infraestrutura_id,
|
|
$jornada->especialidade_id
|
|
),
|
|
'horario' => request()->horario,
|
|
'paciente_id' => $paciente->id,
|
|
'status_id' => AgendamentoStatusEnum::AGENDADO,
|
|
'origem_agendamento' => 'conectasus_cidadao',
|
|
'observacao' => request()->input('observacao'),
|
|
]);
|
|
|
|
$agendamento->created_lotacao_id = $jornada->lotacao_id;
|
|
$agendamento->created_centro_custo_id = $jornada->created_centro_custo_id;
|
|
$agendamento->updated_lotacao_id = $jornada->lotacao_id;
|
|
$agendamento->updated_centro_custo_id = $jornada->created_centro_custo_id;
|
|
|
|
$agendamento->save();
|
|
|
|
return $agendamento;
|
|
});
|
|
|
|
$agendamento->refresh();
|
|
|
|
$profissionalNome = $jornada->lotacao->usuario->cidadao->nome ?? null;
|
|
|
|
return [
|
|
'id' => $agendamento->id,
|
|
'data_hora' => self::formatarDataHora($jornada->data, $agendamento->horario),
|
|
'especialidade' => $jornada->especialidade->nome,
|
|
'unidade' => $unidadeJornada->nome_fantasia,
|
|
'profissional' => $profissionalNome,
|
|
'status' => 'confirmado',
|
|
];
|
|
}
|
|
|
|
public static function cancelar($id)
|
|
{
|
|
$paciente = auth('mobile')->user();
|
|
$agendamento = Agendamento::findOrFail($id);
|
|
|
|
if ($agendamento->paciente_id !== $paciente->id) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Este agendamento não pertence ao cidadão autenticado.');
|
|
}
|
|
|
|
if ($agendamento->status_id !== AgendamentoStatusEnum::AGENDADO) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Apenas agendamentos com status "Agendado" podem ser cancelados.');
|
|
}
|
|
|
|
$jornada = $agendamento->jornada;
|
|
$dataHoraConsulta = Carbon::parse($jornada->data->format('Y-m-d') . ' ' . $agendamento->horario->format('H:i:s'));
|
|
$horasAntecedencia = 48;
|
|
|
|
if (Carbon::now()->diffInHours($dataHoraConsulta, false) < $horasAntecedencia) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Cancelamento permitido apenas com no mínimo 48 horas de antecedência.');
|
|
}
|
|
|
|
DB::transaction(function () use ($agendamento) {
|
|
$agendamento->update([
|
|
'status_id' => AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE,
|
|
'motivo_cancelamento' => 'Cancelado pelo cidadão via ConectaSUS Cidadão.',
|
|
]);
|
|
});
|
|
|
|
return ['message' => 'Agendamento cancelado com sucesso.'];
|
|
}
|
|
|
|
public static function historico()
|
|
{
|
|
$paciente = auth('mobile')->user();
|
|
$perPage = request()->per_page ?? 15;
|
|
$status = request()->status;
|
|
|
|
$statusMap = [
|
|
'confirmado' => AgendamentoStatusEnum::AGENDADO,
|
|
'cancelado' => [AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE, AgendamentoStatusEnum::CANCELADO_PELO_MEDICO],
|
|
'realizado' => AgendamentoStatusEnum::REALIZADO,
|
|
'falta' => AgendamentoStatusEnum::FALTA_DO_PACIENTE,
|
|
];
|
|
|
|
$query = DB::table('ambulatorio_agendamento as agendamento')
|
|
->join('ambulatorio_jornada as jornada', 'jornada.id', 'agendamento.jornada_id')
|
|
->join('cadastro_especialidade as especialidade', 'especialidade.id', 'jornada.especialidade_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')
|
|
->leftJoin('cadastro_usuario as usuario', 'usuario.id', 'lotacao.usuario_id')
|
|
->leftJoin('cadastro_cidadao as cidadao', 'cidadao.id', 'usuario.cidadao_id')
|
|
->join('ambulatorio_agendamento_status as agendamento_status', 'agendamento_status.id', 'agendamento.status_id')
|
|
->where('agendamento.paciente_id', $paciente->id)
|
|
->when($status && isset($statusMap[$status]), function ($q) use ($status, $statusMap) {
|
|
$valor = $statusMap[$status];
|
|
|
|
if (is_array($valor)) {
|
|
|
|
$q->whereIn('agendamento.status_id', $valor);
|
|
} else {
|
|
|
|
$q->where('agendamento.status_id', $valor);
|
|
}
|
|
})
|
|
->select([
|
|
'agendamento.id',
|
|
DB::raw("CONCAT(DATE_FORMAT(jornada.data, '%Y-%m-%d'), 'T', DATE_FORMAT(agendamento.horario, '%H:%i:%s')) as data_hora"),
|
|
'especialidade.id as especialidade_id',
|
|
'especialidade.nome as especialidade_nome',
|
|
'unidade.id as unidade_id',
|
|
'unidade.nome_fantasia as unidade_nome',
|
|
'cidadao.id as profissional_id',
|
|
'cidadao.nome as profissional_nome',
|
|
'agendamento.status_id',
|
|
'agendamento.origem_agendamento',
|
|
'jornada.data as jornada_data',
|
|
'agendamento.horario',
|
|
])
|
|
->orderByDesc('jornada.data')
|
|
->orderByDesc('agendamento.horario');
|
|
|
|
$paginator = $query->paginate((int) $perPage);
|
|
|
|
$items = collect($paginator->items())->map(function ($item) {
|
|
$statusLabel = self::statusLabel($item->status_id);
|
|
$podeCancelar = self::podeCancelar($item->status_id, $item->jornada_data, $item->horario);
|
|
|
|
return [
|
|
'id' => $item->id,
|
|
'data_hora' => $item->data_hora,
|
|
'especialidade' => [
|
|
'id' => $item->especialidade_id,
|
|
'nome' => $item->especialidade_nome,
|
|
],
|
|
'unidade' => [
|
|
'id' => $item->unidade_id,
|
|
'nome' => $item->unidade_nome,
|
|
],
|
|
'profissional' => $item->profissional_id ? [
|
|
'id' => $item->profissional_id,
|
|
'nome' => $item->profissional_nome,
|
|
] : null,
|
|
'status' => $statusLabel,
|
|
'origem' => $item->origem_agendamento,
|
|
'pode_cancelar' => $podeCancelar,
|
|
];
|
|
});
|
|
|
|
return [
|
|
'data' => $items->toArray(),
|
|
'current_page' => $paginator->currentPage(),
|
|
'last_page' => $paginator->lastPage(),
|
|
'total' => $paginator->total(),
|
|
];
|
|
}
|
|
|
|
private static function calcularVagasJornada($vagas, Jornada $jornada): void
|
|
{
|
|
$data = $jornada->data;
|
|
$inicio = Carbon::parse($data->format('Y-m-d') . ' ' . $jornada->inicio->format('H:i:s'));
|
|
|
|
$profissional = null;
|
|
$usuario = $jornada->lotacao->usuario ?? null;
|
|
|
|
if ($usuario && $usuario->cidadao) {
|
|
|
|
$profissional = [
|
|
'id' => $usuario->cidadao->id,
|
|
'nome' => $usuario->cidadao->nome,
|
|
];
|
|
}
|
|
|
|
$quantidadeSistemaConsulta = $jornada->quantidade_consulta ?? 0;
|
|
$tempoSistemaConsulta = $jornada->tempo_consulta ?? 0;
|
|
$quantidadeSistemaRetorno = $jornada->quantidade_retorno ?? 0;
|
|
$tempoSistemaRetorno = $jornada->tempo_retorno ?? 0;
|
|
|
|
$quantidadeConsulta = $jornada->quantidade_consulta_conectasus_cidadao ?? 0;
|
|
$tempoConsulta = $jornada->tempo_consulta_conectasus_cidadao ?? 0;
|
|
$quantidadeRetorno = $jornada->quantidade_retorno_conectasus_cidadao ?? 0;
|
|
$tempoRetorno = $jornada->tempo_retorno_conectasus_cidadao ?? 0;
|
|
|
|
$statusLiberamHorario = AmbulatorioAgendamentoService::getStatusLiberamHorario();
|
|
|
|
$offsetSistemaConsulta = $quantidadeSistemaConsulta * $tempoSistemaConsulta;
|
|
$offsetSistemaRetorno = $quantidadeSistemaRetorno * $tempoSistemaRetorno;
|
|
|
|
if ($quantidadeConsulta > 0 && $tempoConsulta > 0) {
|
|
|
|
$inicioConsultaApp = $inicio->copy()->addMinutes($offsetSistemaConsulta);
|
|
|
|
self::gerarVagas(
|
|
$vagas,
|
|
$jornada,
|
|
$inicioConsultaApp,
|
|
$quantidadeConsulta,
|
|
$tempoConsulta,
|
|
$profissional,
|
|
$statusLiberamHorario
|
|
);
|
|
}
|
|
|
|
if ($quantidadeRetorno > 0 && $tempoRetorno > 0) {
|
|
|
|
$inicioRetornoApp = $inicio->copy()->addMinutes($offsetSistemaConsulta + $quantidadeConsulta * $tempoConsulta + $offsetSistemaRetorno);
|
|
|
|
self::gerarVagas(
|
|
$vagas,
|
|
$jornada,
|
|
$inicioRetornoApp,
|
|
$quantidadeRetorno,
|
|
$tempoRetorno,
|
|
$profissional,
|
|
$statusLiberamHorario
|
|
);
|
|
}
|
|
}
|
|
|
|
private static function gerarVagas($vagas, Jornada $jornada, Carbon $inicio, int $quantidade, int $tempo, ?array $profissional, array $statusLiberamHorario): void
|
|
{
|
|
$horarioAtual = $inicio->copy();
|
|
|
|
for ($i = 0; $i < $quantidade; $i++) {
|
|
|
|
if ($horarioAtual->isPast()) {
|
|
|
|
$horarioAtual->addMinutes($tempo);
|
|
continue;
|
|
}
|
|
|
|
$horarioStr = $horarioAtual->format('H:i');
|
|
|
|
$agendado = Agendamento::where('jornada_id', $jornada->id)
|
|
->whereTime('horario', $horarioStr)
|
|
->where('origem_agendamento', 'conectasus_cidadao')
|
|
->whereNotIn('status_id', $statusLiberamHorario)
|
|
->exists();
|
|
|
|
if (!$agendado) {
|
|
|
|
$vagas->push([
|
|
'jornada_id' => $jornada->id,
|
|
'horario' => $horarioStr,
|
|
'data_hora' => $jornada->data->format('Y-m-d') . 'T' . $horarioStr . ':00',
|
|
'profissional' => $profissional,
|
|
]);
|
|
}
|
|
|
|
$horarioAtual->addMinutes($tempo);
|
|
}
|
|
}
|
|
|
|
private static function validarBloqueioFaltas(int $pacienteId, int $especialidadeId): ?Carbon
|
|
{
|
|
$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;
|
|
}
|
|
|
|
$dataBase = Carbon::parse($ultimaOcorrencia)->min(Carbon::today());
|
|
$dataMinima = $dataBase->addDays($tempoLiberacao);
|
|
|
|
return Carbon::today()->lt($dataMinima) ? $dataMinima : null;
|
|
}
|
|
|
|
private static function validarAgendamentoDuplicado(int $pacienteId, Jornada $jornada): void
|
|
{
|
|
$especialidade = $jornada->especialidade;
|
|
|
|
if ($especialidade->tratamento || $especialidade->permite_agendamento_mesmo_dia) {
|
|
|
|
return;
|
|
}
|
|
|
|
$existe = Agendamento::where('paciente_id', $pacienteId)
|
|
->where('status_id', AgendamentoStatusEnum::AGENDADO)
|
|
->whereHas('jornada', function ($q) use ($jornada) {
|
|
$q->where('especialidade_id', $jornada->especialidade_id)
|
|
->whereDate('data', '>=', Carbon::today());
|
|
})
|
|
->exists();
|
|
|
|
if ($existe) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Você já possui um agendamento ativo para esta especialidade.');
|
|
}
|
|
}
|
|
|
|
private static function validarVagaDisponivel(Jornada $jornada, string $horario): void
|
|
{
|
|
$statusLiberamHorario = AmbulatorioAgendamentoService::getStatusLiberamHorario();
|
|
|
|
$agendado = Agendamento::where('jornada_id', $jornada->id)
|
|
->whereTime('horario', $horario)
|
|
->where('origem_agendamento', 'conectasus_cidadao')
|
|
->whereNotIn('status_id', $statusLiberamHorario)
|
|
->exists();
|
|
|
|
if ($agendado) {
|
|
|
|
abort(Response::HTTP_UNPROCESSABLE_ENTITY, 'Esta vaga não está mais disponível. Selecione outro horário.');
|
|
}
|
|
}
|
|
|
|
private static function getTipoAgendamento(int $pacienteId, int $infraestruturaId, int $especialidadeId): int
|
|
{
|
|
$ultimaData = self::getUltimoDataAgendamento($pacienteId, $infraestruturaId, $especialidadeId);
|
|
$diasParaRetorno = ParametrizacaoService::getQuantidadeDiasRetorno($infraestruturaId, $especialidadeId);
|
|
|
|
return $diasParaRetorno === 0 || is_null($ultimaData) || Carbon::today()->diff($ultimaData)->days > $diasParaRetorno
|
|
? AgendamentoTipoEnum::CONSULTA
|
|
: AgendamentoTipoEnum::RETORNO;
|
|
}
|
|
|
|
private static function getUltimoDataAgendamento(int $pacienteId, int $infraestruturaId, int $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 statusLabel(int $statusId): string
|
|
{
|
|
switch ($statusId) {
|
|
case AgendamentoStatusEnum::AGENDADO:
|
|
return 'confirmado';
|
|
case AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE:
|
|
case AgendamentoStatusEnum::CANCELADO_PELO_MEDICO:
|
|
return 'cancelado';
|
|
case AgendamentoStatusEnum::FALTA_DO_PACIENTE:
|
|
return 'falta';
|
|
case AgendamentoStatusEnum::REALIZADO:
|
|
return 'realizado';
|
|
default:
|
|
return 'outro';
|
|
}
|
|
}
|
|
|
|
private static function podeCancelar(int $statusId, $jornadaData, $horario): bool
|
|
{
|
|
if ($statusId !== AgendamentoStatusEnum::AGENDADO) {
|
|
return false;
|
|
}
|
|
|
|
$dataHora = Carbon::parse($jornadaData . ' ' . $horario);
|
|
|
|
return Carbon::now()->diffInHours($dataHora, false) >= 48;
|
|
}
|
|
|
|
private static function formatarDataHora($data, $horario): string
|
|
{
|
|
return Carbon::parse($data->format('Y-m-d') . ' ' . $horario->format('H:i:s'))->format('Y-m-d\TH:i:s');
|
|
}
|
|
|
|
private static function getFeriados(): array
|
|
{
|
|
return Feriado::whereHas('modulos', fn($q) => $q->where('identificador', ModuloEnum::AMBULATORIO))
|
|
->whereDate('data', '>=', Carbon::today())
|
|
->orderBy('data')
|
|
->get()
|
|
->map(fn($f) => [
|
|
'data' => Carbon::parse($f->data)->format('Y-m-d'),
|
|
'observacao' => $f->observacao,
|
|
])
|
|
->values()
|
|
->toArray();
|
|
}
|
|
|
|
private static function getFeriadoDatas(): Collection
|
|
{
|
|
return Feriado::whereHas('modulos', fn($q) => $q->where('identificador', ModuloEnum::AMBULATORIO))
|
|
->whereDate('data', '>=', Carbon::today())
|
|
->pluck('data');
|
|
}
|
|
|
|
private static function filtrarEspecialidadePorPaciente($query, $paciente, string $tableAlias = '')
|
|
{
|
|
$alias = $tableAlias ? "{$tableAlias}." : '';
|
|
$cidadao = $paciente->cidadao;
|
|
$idadeAnos = $cidadao->idade['anos'] ?? null;
|
|
$sexoId = $cidadao->sexo_id;
|
|
|
|
return $query
|
|
->when($idadeAnos !== null, fn ($q) => $q
|
|
->where(fn ($q) => $q
|
|
->whereNull("{$alias}idade_minima")
|
|
->orWhere("{$alias}idade_minima", '<=', $idadeAnos)
|
|
)
|
|
->where(fn ($q) => $q
|
|
->whereNull("{$alias}idade_maxima")
|
|
->orWhere("{$alias}idade_maxima", '>=', $idadeAnos)
|
|
)
|
|
)
|
|
->where(fn ($q) => $q
|
|
->whereNull("{$alias}sexo_id")
|
|
->orWhere("{$alias}sexo_id", $sexoId)
|
|
);
|
|
}
|
|
}
|