Files
rkm-conectasus-ci-sandbox/api/app/Services/ExameImagem/ReagendamentoCancelamentoExameService.php
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

862 lines
34 KiB
PHP

<?php
namespace App\Services\ExameImagem;
use App\Enums\Administracao\Modulo;
use App\Enums\ExameImagem\Fechamento\Status;
use App\Enums\ExameImagem\Jornada\Tipo as JornadaTipo;
use App\Enums\ExameImagem\Parametrizacao\ControleJornada\Tipo as ControleJornadaTipo;
use App\Enums\ExameImagem\Tipo as ExameImagemTipo;
use App\Exceptions\ExameImagem\ExceededCotaAgendamentoException;
use App\Exceptions\ExameImagem\ExceededJornadaException;
use App\Models\Cadastro\Estabelecimento\Unidade;
use App\Models\Cadastro\Feriado\Feriado;
use App\Models\Cadastro\Grupo\Grupo;
use App\Models\Cadastro\SujeitoAtencao\Usuario;
use App\Models\ExameImagem\Agendamento\Agendamento;
use App\Models\ExameImagem\Agendamento\AgendamentoExame;
use App\Models\ExameImagem\CotaPrestador;
use App\Models\ExameImagem\Jornada\Jornada;
use App\Models\ExameImagem\Jornada\SemanaJornada;
use App\Models\ExameImagem\Parametrizacao;
use App\Services\Service;
use App\Utils\MaskUtil;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class ReagendamentoCancelamentoExameService extends Service
{
public static function datatable()
{
$gerenciamentoJornadas = DB::table('cadastro_usuario')
->select(
'cadastro_usuario.id',
'cadastro_usuario.cidadao_id',
'cadastro_cidadao.nome',
'cadastro_cidadao.cpf',
'cadastro_usuario.bloqueado',
'cadastro_lotacao.usuario_id',
'exame_imagem_parametrizacao_ocupacao.ocupacao_id',
'ocupacao.nome AS ocupacao_nome',
DB::raw('DATE_FORMAT(cadastro_cidadao.data_nascimento, "%d/%m/%Y") as data_nascimento'),
'cadastro_unidade.nome_fantasia'
)
->join(
'cadastro_cidadao',
'cadastro_cidadao.id',
'cadastro_usuario.cidadao_id'
)
->join(
'cadastro_lotacao',
'cadastro_lotacao.usuario_id',
'cadastro_usuario.id'
)
->join(
'sigtap.ocupacao AS ocupacao',
'ocupacao.id',
'cadastro_lotacao.ocupacao_id'
)
->join(
'exame_imagem_parametrizacao_ocupacao',
'exame_imagem_parametrizacao_ocupacao.ocupacao_id',
'cadastro_lotacao.ocupacao_id'
)
->join(
'cadastro_infraestrutura',
'cadastro_infraestrutura.id',
'cadastro_lotacao.infraestrutura_id'
)
->join(
'cadastro_unidade',
'cadastro_unidade.id',
'cadastro_infraestrutura.unidade_id'
)
->where('cadastro_usuario.bloqueado', '=', '0')
->whereNull('cadastro_lotacao.deleted_at')
->whereNull('exame_imagem_parametrizacao_ocupacao.deleted_at')
->groupBy('cadastro_usuario.id');
return $gerenciamentoJornadas;
}
public static function edit($usuarioId)
{
$usuario = Usuario::findOrFail($usuarioId);
return [
'form' => self::getFormData($usuario),
'model' => self::getModelData(),
];
}
private static function getFormData($usuario)
{
return [
'data_atual' => Carbon::now()->format('Y-m-d'),
'usuario' => self::getUsuarioData($usuario),
'origem' => [
'feriados' => self::getFeriados(),
'unidades' => [],
'infraestruturas' => [],
'prestadores' => [],
'agendamentos' => [],
'grupos' => [],
],
'destino' => [
'unidades' => [],
'infraestruturas' => [],
'prestadores' => [],
'grupos' => [],
'usuarios' => [],
'jornadas' => [],
],
'unidadesParametrizadas' => Parametrizacao::where('executante', true)
->orderBy('unidade_id')
->whereExists(function ($query) use ($usuario) {
$query->select(DB::raw(1))
->from('exame_imagem_jornada')
->where('usuario_id', $usuario->id)
->whereColumn('exame_imagem_jornada.unidade_id', 'exame_imagem_parametrizacao_unidade.unidade_id')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
});
})
->get()
->map(fn ($query) => [
'id' => $query->id,
'unidade_id' => $query->unidade_id,
'nome_fantasia' => $query->unidade->nome_fantasia,
'infraestruturas' => $query->unidade->infraestruturas->sortBy('nome')->map(fn ($infraestrutura) => [
'id' => $infraestrutura->id,
'nome' => $infraestrutura->nome,
'principal' => $infraestrutura->principal,
])->values()
]),
'exames' => [],
'dias_semana' => SemanaJornada::orderBy('id')
->get()
->map(fn ($semanaJornadas) => [
'id' => $semanaJornadas->id,
'nome' => $semanaJornadas->nome,
'disabled' => true,
]),
'prestadores' => [],
];
}
public static function getGrupos($request) {
return Grupo::whereExists(function ($query) use ($request) {
$query->select(DB::raw(1))
->from('exame_imagem_jornada')
->where('usuario_id', $request->profissional_id)
->where('infraestrutura_id', $request->infraestrutura_id)
->where('prestador_id', $request->prestador_id)
->whereColumn('exame_imagem_jornada.exame_id', 'cadastro_grupo.id')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
});
})
->get()
->map(function ($query) {
return [
'id' => $query->id,
'nome' => $query->nome,
];
})
->values();
}
public static function getPrestadores($request) {
return Unidade::whereHas('parametrizacaoExameImagem', function ($query) use ($request) {
$query->where('prestador', true)
->whereExists(function ($query) use ($request) {
$query->select(DB::raw(1))
->from('exame_imagem_jornada')
->where('usuario_id', $request->profissional_id)
->where('infraestrutura_id', $request->infraestrutura_id)
->whereColumn('exame_imagem_jornada.prestador_id', 'exame_imagem_parametrizacao_unidade.id')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
});
});
})
->orderBy('nome_fantasia')
->get()
->map(fn ($unidade) => [
'unidade_id' => $unidade->id,
'nome_fantasia' => $unidade->nome_fantasia,
'prestador' => $unidade->parametrizacaoExameImagem->prestador,
'prestador_id' => $unidade->parametrizacaoExameImagem->id,
])
->unique('unidade_id')
->values();
}
private static function getFeriados()
{
return Feriado::whereHas('modulos', fn ($q) => $q
->where('identificador', Modulo::EXAME_IMAGEM)
)
->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 getUsuarioData($usuario)
{
$cidadao = $usuario->cidadao()->setEagerLoads([])->first(['nome', 'data_nascimento', 'cns', 'cpf']);
$ocupacao = DB::table('cadastro_usuario')
->select(
'exame_imagem_parametrizacao_ocupacao.ocupacao_id',
'ocupacao.nome AS ocupacao_nome',
)
->join(
'cadastro_lotacao',
'cadastro_lotacao.usuario_id',
'cadastro_usuario.id'
)
->join(
'sigtap.ocupacao AS ocupacao',
'ocupacao.id',
'cadastro_lotacao.ocupacao_id'
)
->join(
'exame_imagem_parametrizacao_ocupacao',
'exame_imagem_parametrizacao_ocupacao.ocupacao_id',
'cadastro_lotacao.ocupacao_id'
)
->where('cadastro_usuario.id', $usuario->id)
->whereNull('cadastro_lotacao.deleted_at')
->whereNull('exame_imagem_parametrizacao_ocupacao.deleted_at')
->first();
return [
'id' => $usuario->id,
'nome' => $cidadao->nome,
'data_nascimento' => is_null($cidadao->data_nascimento)
? null : (new Carbon($cidadao->data_nascimento))->format('d/m/Y'),
'cns' => MaskUtil::getCnsMasked($cidadao->cns),
'cpf' => MaskUtil::getCpfMasked($cidadao->cpf),
'ocupacao' => $ocupacao->ocupacao_nome,
];
}
public static function getJornadas($request)
{
$dataAtual = Carbon::today();
$proximoMes = $dataAtual->copy()->addMonths(1);
$ultimoDiaProximoMes = $proximoMes->copy()->endOfMonth();
$agendamentos = Agendamento::with([
'jornada',
'paciente.cidadao.telefones',
'createdLotacao.usuario.cidadao',
'agendamentoExame.exame.procedimento'
])
->where('profissional_id', $request->profissional_id)
->whereHas('agendamentoExame', function($query) {
$query->where('status_id', Status::AGENDADO)
->orWhereNull('status_id');
})
->whereNull('regulacao_solicitacao_id')
->where('unidade_id', $request->unidade_id)
->where('exame_id', $request->exame_id)
->when($request->filled('data'), function ($query) use ($request) {
$query->where('data', $request->data);
}, function ($query) use ($dataAtual) {
$query->where('data', '>=', $dataAtual->format('Y-m-d'));
})
->get()
->map(function ($agendamento) {
return [
'alterar' => false,
'id' => $agendamento->id,
'agendamento_numero' => $agendamento->agendamento_numero,
'controle_jornada_id' => optional($agendamento->jornada)->controle_jornada_id,
'data' => optional($agendamento->data)->format('d/m/Y'),
'data_menstruacao' => optional($agendamento->data_menstruacao)->format('Y-m-d'),
'hora_exame' => optional($agendamento->hora_exame)->format('H:i'),
'paciente_telefones' => $agendamento->paciente->cidadao->telefones->map(fn ($t) => MaskUtil::getPhoneMasked($t->numero))->all(),
'usuario' => optional($agendamento->createdLotacao->usuario->cidadao)->nome,
'paciente' => [
'nome' => optional($agendamento->paciente->cidadao)->nome,
'nome_social' => optional($agendamento->paciente->cidadao)->nome_social,
'data_nascimento' => optional($agendamento->paciente->cidadao->data_nascimento)->format('d/m/Y'),
'prontuario' => $agendamento->paciente->prontuario,
],
'incluido' => $agendamento->agendamentoExame->map(function ($exame) use ($agendamento) {
return [
'id' => $exame->id,
'exame_id' => $exame->exame_id,
'nome' => $exame->exame->nome,
'codigo' => $exame->exame->codigo,
'hora_exame' => optional($agendamento->hora_exame)->format('H:i'),
'observacao' => $exame->exame->observacao,
'valor' => $exame->exame->valor_sigtap
? optional($exame->exame->procedimento)->valor_servico_ambilatorial
: $exame->exame->valor,
];
})->values(),
];
})->sortBy('data')->values();
$jornadas = Jornada::where('unidade_id', $request->unidade_id)
->where('usuario_id', $request->profissional_id)
->where('exame_id', $request->exame_id)
->where('prestador_id', $request->prestador_id)
->where(function ($query) use ($dataAtual, $ultimoDiaProximoMes) {
$query->where('data', '>=', $dataAtual)
->orWhereBetween('data', [$dataAtual, $ultimoDiaProximoMes]);
})
->get()
->map(fn ($jornada) => [
'jornada_id' => $jornada->id,
'unidade_id' => $jornada->unidade_id,
'controle_jornada_id' => $jornada->controle_jornada_id,
'jornada_id' => $jornada->id,
'exame_id' => $jornada->exame_id,
'exame_nome' => $jornada->grupo->nome,
'profissional_id' => $jornada->usuario_id,
'profissional_nome' => $jornada->usuario->nome,
'prestador_id' => $jornada->prestador_id,
'prestador_nome' => $jornada->unidade->nome_fantasia,
'unidade_id' => $jornada->unidade_id,
'unidade_nome' => $jornada->unidade->nome_fantasia,
'infraestrutura_id' => $jornada->infraestrutura_id,
'infraestrutura_nome' => $jornada->infraestrutura->nome,
'semana_id' => $jornada->semana_id,
'data' => (new Carbon($jornada->data))->format('d/m/Y') ?? null,
'vagas' => $jornada->vagas ?? null,
'tipo_id' => $jornada->tipo_id,
'tempo_atendimento' => $jornada->tempo_atendimento,
'selecionado' => false,
'hora_inicial' => (new Carbon($jornada->hora_inicial))->format('H:i') ?? null,
'hora_fim' => (new Carbon($jornada->hora_fim))->format('H:i') ?? null,
'status_id' => $jornada->status_id,
'status_nome' => $jornada->status->nome,
])
->sortBy('data')
->sortBy('hora_inicial')
->values();
return [
'agendamentos' => $agendamentos,
'jornadas' => $jornadas,
];
}
public static function getJornadasDestino($request)
{
$dataAtual = Carbon::today();
$proximoMes = $dataAtual->copy()->addMonths(1);
$ultimoDiaProximoMes = $proximoMes->copy()->endOfMonth();
if ($request->field === 'unidade') {
$resultado = Jornada::where(function ($query) use ($dataAtual, $ultimoDiaProximoMes) {
$query->where('data', '>=', $dataAtual)
->orWhereBetween('data', [$dataAtual, $ultimoDiaProximoMes]);
})
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
})
->groupBy('unidade_id')
->get()
->map(fn ($jornada) => [
'id' => $jornada->unidade_id,
'nome_fantasia' => $jornada->unidade->nome_fantasia,
]);
}
if ($request->field === 'infraestrutura') {
$resultado = Jornada::when($request->filled('unidade_id'), function ($query) use ($request) {
$query->where('unidade_id', $request->unidade_id);
})
->where(function ($query) use ($dataAtual, $ultimoDiaProximoMes) {
$query->where('data', '>=', $dataAtual)
->orWhereBetween('data', [$dataAtual, $ultimoDiaProximoMes]);
})
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
})
->groupBy('infraestrutura_id')
->get()
->map(fn ($jornada) => [
'id' => $jornada->infraestrutura_id,
'nome' => $jornada->infraestrutura->nome,
]);
}
if ($request->field === 'prestador') {
$resultado = Jornada::when($request->filled('unidade_id'), function ($query) use ($request) {
$query->where('unidade_id', $request->unidade_id);
})
->when($request->filled('infraestrutura_id'), function ($query) use ($request) {
$query->where('infraestrutura_id', $request->infraestrutura_id);
})
->where(function ($query) use ($dataAtual, $ultimoDiaProximoMes) {
$query->where('data', '>=', $dataAtual)
->orWhereBetween('data', [$dataAtual, $ultimoDiaProximoMes]);
})
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
})
->groupBy('prestador_id')
->get()
->map(fn ($jornada) => [
'id' => $jornada->prestador_id,
'nome' => $jornada->prestador->unidade->nome_fantasia,
]);
}
if ($request->field === 'grupo') {
$resultado = Jornada::when($request->filled('unidade_id'), function ($query) use ($request) {
$query->where('unidade_id', $request->unidade_id);
})
->when($request->filled('infraestrutura_id'), function ($query) use ($request) {
$query->where('infraestrutura_id', $request->infraestrutura_id);
})
->when($request->filled('prestador_id'), function ($query) use ($request) {
$query->where('prestador_id', $request->prestador_id);
})
->where(function ($query) use ($dataAtual, $ultimoDiaProximoMes) {
$query->where('data', '>=', $dataAtual)
->orWhereBetween('data', [$dataAtual, $ultimoDiaProximoMes]);
})
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
})
->groupBy('exame_id')
->get()
->map(fn ($jornada) => [
'id' => $jornada->exame_id,
'nome' => $jornada->grupo->nome,
]);
}
if ($request->field === 'usuario') {
$resultado = Jornada::when($request->filled('unidade_id'), function ($query) use ($request) {
$query->where('unidade_id', $request->unidade_id);
})
->when($request->filled('infraestrutura_id'), function ($query) use ($request) {
$query->where('infraestrutura_id', $request->infraestrutura_id);
})
->when($request->filled('prestador_id'), function ($query) use ($request) {
$query->where('prestador_id', $request->prestador_id);
})
->where(function ($query) use ($dataAtual, $ultimoDiaProximoMes) {
$query->where('data', '>=', $dataAtual)
->orWhereBetween('data', [$dataAtual, $ultimoDiaProximoMes]);
})
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('exame_imagem_agendamento')
->whereColumn('exame_imagem_agendamento.jornada_id', 'exame_imagem_jornada.id');
})
->groupBy('usuario_id')
->get()
->map(fn ($jornada) => [
'id' => $jornada->usuario_id,
'nome' => $jornada->usuario->nome,
]);
}
return $resultado;
}
public static function reschedule()
{
self::validateReschedule();
DB::transaction(function () {
collect(request()->agendamentos)->each(function ($agendamento) {
$id = $agendamento['id'];
$agendamentoAnterior = Agendamento::findOrFail($id);
$jornada = Jornada::findOrFail(request()->jornada_id);
if (!request()->supervisor_id) {
if ($jornada->tipo_id === ExameImagemTipo::QUANTIDADE) {
self::getSaldoUnidadeQuantidade($jornada, $agendamentoAnterior);
} else {
self::getSaldoUnidadeValor($jornada, $agendamentoAnterior);
}
self::handleJornada($jornada, $agendamentoAnterior);
}
$agendamentoAnterior->agendamentoExame()->update(['status_id' => Status::REAGENDADO]);
$nextHorario = self::getNextHorario($jornada);
$reagendamento = new Agendamento();
$reagendamento->agendamento_numero = now()->timestamp * 1000;;
$reagendamento->paciente_id = $agendamentoAnterior['paciente_id'];
$reagendamento->jornada_id = $jornada->id;
$reagendamento->medico_id = $agendamentoAnterior['medico_id'];
$reagendamento->profissional_id = $jornada->usuario_id;
$reagendamento->data = $jornada->data;
$reagendamento->exame_id = $jornada->exame_id;
$reagendamento->hora_exame = $nextHorario->horario;
$reagendamento->unidade_id = $jornada->unidade_id;
$reagendamento->unidade_solicitante_id = $agendamentoAnterior['unidade_solicitante_id'];
$reagendamento->infraestrutura_solicitante_id = $agendamentoAnterior['infraestrutura_solicitante_id'];
$reagendamento->infraestrutura_id = $jornada->infraestrutura_id;
$reagendamento->nome_responsavel = $agendamentoAnterior['nome_responsavel'];
$reagendamento->observacao = $agendamentoAnterior['observacao'];
$reagendamento->gestante = $agendamentoAnterior['gestante'];
$reagendamento->urgente = $agendamentoAnterior['urgente'];
$reagendamento->supervisor_id = request()->supervisor_id;
$reagendamento->retroativo = $agendamentoAnterior['retroativo'];
$reagendamento->agendador_id = $agendamentoAnterior['agendador_id'];
$reagendamento->save();
$paciente_id = $reagendamento->paciente_id;
$agendamento_id = $reagendamento->id;
foreach ($agendamentoAnterior->agendamentoExame as $param_exame) {
$exame = new AgendamentoExame();
$exame->agendamento_id = $agendamento_id;
$exame->exame_id = $param_exame['exame_id'];
$exame->paciente_id = $paciente_id;
$exame->status_id = Status::AGENDADO;
$exame->save();
}
});
});
return (object) ['agendamentos_nao_reagendados' => []];
}
private static function getSaldoUnidadeQuantidade($jornada, $agendamentoAnterior)
{
$cotaUnidade = CotaPrestador::where('infraestrutura_id', $jornada->prestador->infraestrutura->id)
->where('cota_tipo_id', ExameImagemTipo::QUANTIDADE)
->where('inicio', '<=', $jornada->data)
->where('fim', '>=', $jornada->data)
->first();
if ($cotaUnidade) {
$totalUnidade = $cotaUnidade->cota_unidade;
if ($jornada->controle_jornada_id == ControleJornadaTipo::EXAME) {
$cotaUtilizada = AgendamentoExame::whereHas('agendamento', function($query) use ($jornada, $cotaUnidade) {
$query->whereHas('jornada', function($query) use ($jornada) {
$query->where('prestador_id', $jornada->prestador_id);
})
->where('data', '>=', $cotaUnidade->inicio)
->where('data', '<=', $cotaUnidade->fim);
})
->count('id') ?? 0;
$cotaUtilizada = $cotaUtilizada + $agendamentoAnterior->agendamentoExame->count();
} else {
$cotaUtilizada = Agendamento::whereHas('jornada', function($query) use ($jornada) {
$query->where('prestador_id', $jornada->prestador_id);
})
->where('data', '>=', $cotaUnidade->inicio)
->where('data', '<=', $cotaUnidade->fim)
->count('id') ?? 0;
}
if (($totalUnidade - $cotaUtilizada) - 1 < 0) {
throw new ExceededCotaAgendamentoException;
}
}
}
private static function getSaldoUnidadeValor($jornada, $agendamentoAnterior)
{
$cotaUnidade = CotaPrestador::where('infraestrutura_id', $jornada->prestador->infraestrutura->id)
->where('cota_tipo_id', ExameImagemTipo::VALOR)
->where('inicio', '<=', $jornada->data)
->where('fim', '>=', $jornada->data)
->first();
if ($cotaUnidade) {
$totalUnidade = $cotaUnidade->cota_valor;
$cotaUtilizada = AgendamentoExame::whereHas('agendamento', function ($query) use ($jornada, $cotaUnidade) {
$query->whereHas('jornada', function ($query) use ($jornada) {
$query->where('prestador_id', $jornada->prestador_id);
})
->whereBetween('data', [$cotaUnidade->inicio, $cotaUnidade->fim]);
})
->whereHas('exame')
->with('exame')
->get()
->sum(fn($agendamentoExame) => $agendamentoExame->exame->valor);
$agendamentoCotaExames = 0;
foreach ($agendamentoAnterior->agendamentoExame as $agendamentoExame) {
$agendamentoCotaExames = $agendamentoCotaExames + $agendamentoExame->exame->valor;
}
if (($totalUnidade - $cotaUtilizada) - $agendamentoCotaExames < 0) {
throw new ExceededCotaAgendamentoException;
}
}
}
private static function handleJornada($jornada, $agendamentoAnterior)
{
if($jornada->controle_jornada_id == ControleJornadaTipo::EXAME){
$agendamentoCadastrado = AgendamentoExame::whereHas('agendamento', function($query) use ($jornada) {
$query->whereHas('jornada', function($query) use ($jornada) {
$query->where('id', $jornada->id);
});
})
->count('id') ?? 0;
$agendamentoCadastrado = $agendamentoCadastrado + $agendamentoAnterior->agendamentoExame->count();
} else {
$agendamentoCadastrado = Agendamento::whereHas('jornada', function($query) use ($jornada) {
$query->where('id', $jornada->id);
})
->count('id') ?? 0;
$agendamentoCadastrado = $agendamentoCadastrado + 1;
}
if ($agendamentoCadastrado > $jornada->vagas) {
throw new ExceededJornadaException;
}
}
private static function getNextHorario($jornada)
{
$nextHorario = (object) [
'horario' => null,
'is_excedente' => false,
];
if ($jornada->tipo_id === JornadaTipo::FIXA) {
$nextHorario->horario = Carbon::parse($jornada->hora_inicial)->format('H:i');
}
else if ($jornada->tipo_id === JornadaTipo::DINAMICA) {
$horarios = collect();
$agendamentos = self::getAgendamentos($jornada->id);
$agendamentos->each(fn ($a) => $a->hora_exame = $jornada->data->copy()->setTimeFromTimeString($a->hora_exame));
$agendamentos
->each(fn ($agendamento) => $horarios->push((object) [
'horario' => $agendamento->hora_exame->format('H:i'),
'quantidade_agendada' => $agendamento->quantidade_agendada,
'quantidade_total' => 1,
]));
$quantidade = $agendamentos->count();
if ($quantidade < $jornada->vagas) {
$data = $jornada->data->copy();
self::setHorarioJornadaDinamica(
$horarios,
$agendamentos,
$jornada,
$quantidade,
$data
);
}
$horarios = $horarios->sortBy('horario')->values();
$horario = $horarios->where('quantidade_agendada', 0)->first();
if (is_null($horario)) {
$horario = $horarios->last();
}
$nextHorario->horario = $horario->horario;
}
return $nextHorario;
}
private static function getStatusLiberamHorario()
{
return [
Status::REAGENDADO,
Status::CANCELADO,
];
}
private static function setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $quantidade, $data)
{
$agendamento = $agendamentos->where('horario', $data)->first();
if (is_null($agendamento)) {
$final = $data->copy()->addMinutes($jornada->tempo_atendimento);
$agendamento = $agendamentos
->where('horario', '>', $data)
->where('horario', '<', $final)
->first();
if ($agendamento) {
self::setHorarioJornadaDinamica(
$horarios,
$agendamentos,
$jornada,
$quantidade,
$agendamento->horario
);
}
else {
$horarios->push((object) [
'horario' => $data->format('H:i'),
'quantidade_agendada' => 0,
'quantidade_total' => 1,
]);
if (++$quantidade < $jornada->vagas) {
$data->addMinutes($jornada->tempo_atendimento);
self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $quantidade, $data);
}
}
}
else {
$data->addMinutes($jornada->tempo_atendimento);
self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $quantidade, $data);
}
}
public static function cancel()
{
DB::transaction(function () {
collect(request()->agendamentos)->each(function ($id) {
$agendamento = Agendamento::findOrFail($id);
$agendamento->agendamentoExame()->update(['status_id' => Status::CANCELADO]);
});
});
}
private static function validateReschedule()
{
request()->validate([
'agendamentos' => [
'required',
'array',
],
'agendamentos.*.id' => [
'required',
'integer',
Rule::exists(Agendamento::class, 'id'),
],
'jornada_id' => [
'required',
'integer',
Rule::exists(Jornada::class, 'id'),
],
'motivo_agendamento_excedente' => [
'nullable',
'string',
'max:500',
]
]);
}
private static function getAgendamentos($jornadaId)
{
return Agendamento::where('jornada_id', $jornadaId)
->whereHas('agendamentoExame', function ($query) {
$query->whereNotIn('status_id', self::getStatusLiberamHorario());
})
->groupBy('hora_exame')
->orderBy('hora_exame')
->select('hora_exame', DB::raw('COUNT(id) as quantidade_agendada'))
->get();
}
private static function getModelData()
{
return [
'origem' => [
'unidade_id' => null,
'infraestrutura_id' => null,
'ocupacao_id' => null,
'especialidade_id' => null,
'data' => null,
'grupo_id' => null,
'prestador_id' => null,
],
'destino' => [
'unidade_id' => null,
'infraestrutura_id' => null,
'prestador_id' => null,
'grupo_id' => null,
'usuario_id' => null,
'agendamentos' => [],
'jornada_id' => null,
'motivo_agendamento_excedente' => null,
],
'cancelamento' => [
'agendamentos' => [],
'motivo' => null,
]
];
}
}