init commit
All checks were successful
build-api-image / build (push) Successful in 51s

This commit is contained in:
Antonio Lopes dos Santos
2026-08-04 16:52:02 -03:00
commit afec302c3e
11594 changed files with 1636728 additions and 0 deletions

View File

@@ -0,0 +1,693 @@
<?php
namespace App\Services\Imunizacao;
use App\Enums\Administracao\Modulo;
use App\Enums\PainelSenha\Status;
use App\Events\PainelSenha\FilaEvent;
use App\Models\Cadastro\Estabelecimento\CentroCusto;
use App\Models\Cadastro\SujeitoAtencao\Paciente;
use App\Models\PainelSenha\CentroCustoCompartilhado;
use App\Models\PainelSenha\Fila;
use App\Models\PainelSenha\OpcaoEntrada;
use App\Models\PainelSenha\Prioridade;
use App\Services\Administracao\ModuloService;
use App\Services\Farmacia\FilaAtendimentoService AS FarmaciaFilaAtendimentoService;
use App\Services\Geral\AgeService;
use App\Services\PainelSenha\FilaAtendimentoService AS PainelSenhaFilaAtendimentoService;
use App\Services\Service;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class FilaAtendimentoService extends Service
{
public static function index($centroCusto = null)
{
$centroCusto = $centroCusto ?? self::getCurrentCentroCusto();
return DB::table('painel_senha_fila')
->select([
'painel_senha_fila.id',
'painel_senha_opcao_entrada.id AS opcao_entrada_id',
'painel_senha_opcao_entrada.nome AS opcao_entrada_nome',
'painel_senha_opcao_entrada_destino.id AS opcao_entrada_destino_id',
'painel_senha_status.id AS status_id',
'painel_senha_status.nome AS status_nome',
'painel_senha_prioridade.id AS prioridade_id',
'painel_senha_prioridade.nome AS prioridade_nome',
'cadastro_paciente.id AS paciente_id',
'cadastro_cidadao.nome AS paciente_nome',
DB::raw("DATE_FORMAT(cadastro_cidadao.data_nascimento, '%d/%m/%Y') AS paciente_data_nascimento"),
DB::raw("LPAD(cadastro_paciente.prontuario, 6, '0') AS paciente_prontuario"),
DB::raw("CONCAT(painel_senha_opcao_entrada.sigla, painel_senha_fila.senha) AS senha"),
DB::raw("DATE_FORMAT(painel_senha_fila.created_at, '%H:%i') AS horario_chegada"),
'painel_senha_fila.emitido_em',
])
->addSelect([
'chamadas' => function ($query) {
$query->select(DB::raw("COALESCE(COUNT(painel_senha_chamada.id), 0)"))
->from('painel_senha_chamada')
->whereColumn('painel_senha_chamada.fila_id', 'painel_senha_fila.id')
->whereColumn('painel_senha_chamada.status_id', 'painel_senha_fila.status_id');
},
])
->join('painel_senha_opcao_entrada', 'painel_senha_opcao_entrada.id', 'painel_senha_fila.opcao_entrada_id')
->join('painel_senha_status', 'painel_senha_status.id', 'painel_senha_fila.status_id')
->leftJoin('painel_senha_prioridade', 'painel_senha_prioridade.id', 'painel_senha_fila.prioridade_id')
->leftJoin('cadastro_paciente', 'cadastro_paciente.id', 'painel_senha_fila.paciente_id')
->leftJoin('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_paciente.cidadao_id')
->leftJoin('painel_senha_opcao_entrada AS painel_senha_opcao_entrada_destino', 'painel_senha_opcao_entrada_destino.id', 'painel_senha_fila.opcao_entrada_destino_id')
->whereNull('painel_senha_fila.deleted_at')
->where('painel_senha_fila.evadido', false)
->where('painel_senha_fila.finalizado', false)
->where(fn ($q) => $q
->where(fn ($q) => $q
->whereNull('painel_senha_fila.opcao_entrada_destino_id')
->where('painel_senha_opcao_entrada.modulo_id', ModuloService::getId(Modulo::IMUNIZACAO))
->where(fn ($q) => $q
->where('painel_senha_opcao_entrada.centro_custo_id', $centroCusto->id)
->orWhereExists(fn ($q) => $q->select(DB::raw(1))
->from('painel_senha_centro_custo_compartilhado')
->where('painel_senha_centro_custo_compartilhado.centro_custo_id', $centroCusto->id)
->whereColumn('painel_senha_centro_custo_compartilhado.opcao_entrada_id', 'painel_senha_opcao_entrada.id')
)
)
)
->orWhere(fn ($q) => $q
->whereNotNull('painel_senha_fila.opcao_entrada_destino_id')
->where('painel_senha_opcao_entrada_destino.modulo_id', ModuloService::getId(Modulo::IMUNIZACAO))
->where(fn ($q) => $q
->where('painel_senha_opcao_entrada_destino.centro_custo_id', $centroCusto->id)
->orWhereExists(fn ($q) => $q->select(DB::raw(1))
->from('painel_senha_centro_custo_compartilhado')
->where('painel_senha_centro_custo_compartilhado.centro_custo_id', $centroCusto->id)
->whereColumn('painel_senha_centro_custo_compartilhado.opcao_entrada_id', 'painel_senha_opcao_entrada_destino.id')
)
)
)
)
->orderByDesc('painel_senha_prioridade.grau')
->orderBy('painel_senha_fila.atualizado_em')
->get()
->map(function($query) {
$query->tempo_espera = self::getTempoEspera($query->id);
$query->paciente_idade = isset($query->paciente_data_nascimento) ? AgeService::getFormattedAge(Carbon::createFromFormat('d/m/Y', $query->paciente_data_nascimento)) : null;
return $query;
});
}
public static function create()
{
return [
'form' => [
'opcoes_entrada' => self::getOpcoesEntrada(),
'prioridades' => self::getPrioridades(),
],
'model' => [
'paciente_id' => null,
'opcao_entrada_id' => null,
'prioridade_id' => null,
],
];
}
public static function createEncaminhamento($filaId)
{
$fila = Fila::findOrFail($filaId);
return [
'form' => [
'modulos_encaminhamento' => self::getModulosEncaminhamento($fila),
'centros_custo_encaminhamento' => [],
'opcoes_entrada_encaminhamento' => [],
'prioridades' => Prioridade::orderBy('nome')->get(['id', 'nome']),
],
'model' => [
'modulo_encaminhamento_id' => null,
'centro_custo_encaminhamento_id' => null,
'opcao_entrada_encaminhamento_id' => null,
'prioridade_id' => $fila->prioridade_id ?? null,
],
];
}
public static function listEncaminhamento()
{
$params = (object) request()->all();
switch (request()->listar) {
case 'centros-custo-encaminhamento': {
return [
'centros_custo_encaminhamento' => self::getCentrosCustoEncaminhamento($params),
'opcoes_entrada_encaminhamento' => [],
];
}
case 'opcoes-entrada-encaminhamento': {
return [
'opcoes_entrada_encaminhamento' => self::getOpcoesEntradaEncaminhamento($params),
];
}
}
}
private static function getModulosEncaminhamento($fila)
{
return DB::table('administracao_modulo AS modulo')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('painel_senha_opcao_entrada AS opcao_entrada')
->join(
'painel_senha_opcao_entrada_destino AS opcao_entrada_destino',
'opcao_entrada_destino.opcao_entrada_destino_id',
'opcao_entrada.id'
)
->whereColumn('opcao_entrada.modulo_id', 'modulo.id')
->where('opcao_entrada_destino.opcao_entrada_origem_id', $fila->opcaoEntradaAtual->id)
)
->select(
'modulo.id',
'modulo.nome'
)
->orderBy('modulo.nome')
->get();
}
private static function getCentrosCustoEncaminhamento($params)
{
return DB::table('cadastro_centro_custo AS centro_custo')
->join('cadastro_setor AS setor', 'setor.id', 'centro_custo.setor_id')
->whereExists(fn ($q) => $q
->selectRaw(1)
->from('painel_senha_opcao_entrada AS opcao_entrada')
->join(
'painel_senha_opcao_entrada_destino AS opcao_entrada_destino',
'opcao_entrada_destino.opcao_entrada_destino_id',
'opcao_entrada.id'
)
->whereColumn('opcao_entrada.centro_custo_id', 'centro_custo.id')
->where('opcao_entrada_destino.opcao_entrada_origem_id', $params->opcao_entrada_origem_id)
->where('opcao_entrada.modulo_id', $params->modulo_id)
)
->select(
'centro_custo.id',
'setor.nome AS setor_nome'
)
->orderBy('setor.nome')
->get();
}
private static function getOpcoesEntradaEncaminhamento($params)
{
return DB::table('painel_senha_opcao_entrada AS opcao_entrada')
->join(
'painel_senha_opcao_entrada_destino AS opcao_entrada_destino',
'opcao_entrada_destino.opcao_entrada_destino_id',
'opcao_entrada.id'
)
->where('opcao_entrada_destino.opcao_entrada_origem_id', $params->opcao_entrada_origem_id)
->where('opcao_entrada.modulo_id', $params->modulo_id)
->where('opcao_entrada.centro_custo_id', $params->centro_custo_id)
->select(
'opcao_entrada.id',
'opcao_entrada.nome',
'opcao_entrada.prioridade_obrigatoria'
)
->orderBy('opcao_entrada.nome')
->get();
}
public static function store()
{
self::validateStore();
$centroCusto = self::getCurrentCentroCusto();
$senha = (
Fila::where('opcao_entrada_id', request()->opcao_entrada_id)
->whereRaw('emitido_em = CURRENT_DATE')
->max('senha') ?? 0
) + 1;
$fila = Fila::create([
'paciente_id' => request()->paciente_id,
'centro_custo_id' => $centroCusto->id,
'opcao_entrada_id' => request()->opcao_entrada_id,
'prioridade_id' => request()->prioridade_id,
'status_id' => Status::EM_ESPERA,
'senha' => $senha,
]);
self::dispatch($fila->opcaoEntradaAtual->id, $fila->centro_custo_id);
return $fila;
}
public static function edit($id)
{
$fila = Fila::findOrFail($id);
return [
'form' => [
'opcoes_entrada' => self::getOpcoesEntrada(),
'prioridades' => self::getPrioridades(),
],
'model' => [
'id' => $fila->id,
'paciente' => $fila->paciente ? [
'id' => $fila->paciente->id,
'nome' => $fila->paciente->cidadao->nome,
'cns' => $fila->paciente->cidadao->cns,
] : null,
'opcao_entrada_id' => $fila->opcao_entrada_id,
'prioridade_id' => $fila->prioridade_id,
],
];
}
public static function update($id)
{
self::validateUpdate();
$fila = Fila::findOrFail($id);
$fila->update([
'paciente_id' => request()->paciente_id,
'prioridade_id' => request()->prioridade_id,
]);
self::dispatch($fila->opcaoEntradaAtual->id, $fila->centro_custo_id);
return $fila->fresh();
}
public static function list()
{
return [
'additionals' => [
'sala_vacinacao_logada' => self::getSalaVacinacaoLogada(),
],
'form' => [
'tempos_espera' => self::getTemposEspera(),
'opcoes_entrada' => self::getOpcoesEntrada(),
'prioridades' => self::getPrioridades(),
'status' => self::getStatus(),
'salas' => self::getSalas(),
'telas' => self::getTelas(),
],
'model' => [
'tempo_espera_id' => null,
'opcao_entrada_id' => null,
'prioridade_id' => null,
'status_id' => Status::EM_ESPERA,
'fila' => self::index(),
],
];
}
public static function autocompletePaciente()
{
return DB::table('cadastro_paciente')
->select([
'cadastro_paciente.id',
'cadastro_cidadao.nome',
'cadastro_cidadao.cns',
])
->join('cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_paciente.cidadao_id');
}
public static function evade($id)
{
$fila = Fila::findOrFail($id);
self::validateEvade();
$fila->update([
'evadido' => true,
'motivo_evasao' => request()->motivo,
'motivo_cancelamento_evasao' => null,
'finalizado' => true,
]);
self::dispatch($fila->opcaoEntradaAtual->id, $fila->centro_custo_id);
}
public static function answer($id)
{
$fila = Fila::findOrFail($id);
$fila->update(['status_id' => Status::EM_ATENDIMENTO]);
self::dispatch($fila->opcaoEntradaAtual->id, $fila->centro_custo_id);
}
public static function sendBack($id)
{
$fila = Fila::findOrFail($id);
$fila->update(['status_id' => Status::EM_ESPERA]);
self::dispatch($fila->opcaoEntradaAtual->id, $fila->centro_custo_id);
}
public static function forward($id)
{
$fila = Fila::findOrFail($id);
self::validateForward();
$opcaoEntradaFrom = $fila->opcaoEntradaAtual;
$centroCustoFrom = CentroCusto::findOrFail($fila->centro_custo_id);
$opcaoEntradaTo = OpcaoEntrada::findOrFail(request()->opcao_entrada_encaminhamento_id);
$centroCustoTo = $opcaoEntradaTo->centroCusto;
$fila->update([
'centro_custo_id' => $centroCustoTo->id,
'opcao_entrada_destino_id' => $opcaoEntradaTo->id,
'prioridade_id' => request()->prioridade_id,
'status_id' => Status::EM_ESPERA,
]);
self::dispatch($opcaoEntradaFrom->id, $centroCustoFrom->id);
if ($opcaoEntradaTo->modulo_id === ModuloService::getId(Modulo::PAINEL_SENHA)) {
PainelSenhaFilaAtendimentoService::dispatch($opcaoEntradaTo->id, $centroCustoTo->id);
}
else if ($opcaoEntradaTo->modulo_id === ModuloService::getId(Modulo::FARMACIA)) {
FarmaciaFilaAtendimentoService::dispatch($opcaoEntradaTo->id, $centroCustoTo->id);
}
else if ($opcaoEntradaTo->modulo_id === ModuloService::getId(Modulo::IMUNIZACAO)) {
self::dispatch($opcaoEntradaTo->id, $centroCustoTo->id);
}
}
public static function finalize($id)
{
$fila = Fila::findOrFail($id);
$fila->update(['finalizado' => true]);
self::dispatch($fila->opcaoEntradaAtual->id, $fila->centro_custo_id);
}
public static function dispatch($opcaoEntradaId, $centroCustoId)
{
$centroCusto = CentroCusto::findOrFail($centroCustoId);
FilaEvent::dispatch(
$centroCusto->setor->tipo_id,
$centroCusto->id,
Modulo::IMUNIZACAO,
self::index($centroCusto)
);
CentroCustoCompartilhado::where('opcao_entrada_id', $opcaoEntradaId)
->get()
->each(function ($item) {
$centroCusto = CentroCusto::findOrFail($item->centro_custo_id);
FilaEvent::dispatch(
$centroCusto->setor->tipo_id,
$centroCusto->id,
Modulo::IMUNIZACAO,
self::index($centroCusto)
);
});
CentroCustoCompartilhado::query()
->join(
'painel_senha_opcao_entrada',
'painel_senha_opcao_entrada.id',
'painel_senha_centro_custo_compartilhado.opcao_entrada_id'
)
->where('painel_senha_centro_custo_compartilhado.centro_custo_id', $centroCustoId)
->whereNull('painel_senha_opcao_entrada.deleted_at')
->get()
->each(function ($item) {
$centroCusto = OpcaoEntrada::findOrFail($item->opcao_entrada_id)->centroCusto;
FilaEvent::dispatch(
$centroCusto->setor->tipo_id,
$centroCusto->id,
Modulo::IMUNIZACAO,
self::index($centroCusto)
);
});
}
private static function validateStore()
{
request()->validate([
'paciente_id' => [
'required',
'integer',
Rule::exists(Paciente::class, 'id'),
],
'opcao_entrada_id' => [
'required',
'integer',
Rule::exists(OpcaoEntrada::class, 'id'),
],
'prioridade_id' => [
'nullable',
Rule::requiredIf(fn () => OpcaoEntrada::find(request()->opcao_entrada_id)
->prioridade_obrigatoria ?? false
),
Rule::exists(Prioridade::class, 'id'),
],
]);
}
private static function validateUpdate()
{
request()->validate([
'paciente_id' => [
'required',
'integer',
Rule::exists(Paciente::class, 'id'),
],
'prioridade_id' => [
'nullable',
Rule::requiredIf(fn () => OpcaoEntrada::find(request()->opcao_entrada_id)
->prioridade_obrigatoria ?? false
),
Rule::exists(Prioridade::class, 'id'),
],
]);
}
private static function validateForward()
{
request()->validate([
'opcao_entrada_encaminhamento_id' => [
'required',
'integer',
Rule::exists(OpcaoEntrada::class, 'id'),
],
'prioridade_id' => [
'nullable',
Rule::requiredIf(fn () => OpcaoEntrada::find(request()->opcao_entrada_encaminhamento_id)
->prioridade_obrigatoria ?? false
),
Rule::exists(Prioridade::class, 'id'),
],
]);
}
private static function validateEvade()
{
request()->validate([
'motivo' => [
'nullable',
'string',
'max:500',
],
]);
}
private static function getSalaVacinacaoLogada()
{
return DB::table('imunizacao_sala_vacinacao')
->select([
'imunizacao_sala_vacinacao.id',
'cadastro_infraestrutura.unidade_id',
'imunizacao_sala_vacinacao.responsavel',
'imunizacao_sala_vacinacao.permite_aplicacao',
'imunizacao_sala_vacinacao.cria_ficha_ab'
])
->join('cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'imunizacao_sala_vacinacao.infraestrutura_id')
->where('imunizacao_sala_vacinacao.ativo', true)
->where('cadastro_infraestrutura.id', auth()->payload()->get('infraestrutura_id'))
->first();
}
private static function getTempoEspera($filaId)
{
$tempoEsperaTotal = DB::table('painel_senha_fila_historico')
->select([
'painel_senha_fila_historico.created_at',
'painel_senha_fila_historico.status_id',
])
->where('painel_senha_fila_historico.fila_id', $filaId)
->distinct()
->get()
->reduce(function ($count, $query) use ($filaId) {
if ($query->status_id === Status::EM_ESPERA) {
$proximo = DB::table('painel_senha_fila_historico')
->where('fila_id', $filaId)
->where('created_at', '>', $query->created_at)
->select('created_at')
->first();
return $count + Carbon::create($query->created_at)->diffInMinutes($proximo->created_at ?? Carbon::now());
}
return $count;
}, 1);
$centroCustoLogado = self::getCurrentCentroCusto();
$tempoEspera = DB::table('painel_senha_tempo_espera')
->select(
'id',
'cor'
)
->whereNull('deleted_at')
->where('tempo', '<=', $tempoEsperaTotal)
->where('infraestrutura_id', $centroCustoLogado->infraestrutura_id)
->orderByDesc('tempo')
->first();
if (is_null($tempoEspera)) {
$tempoEspera = DB::table('painel_senha_tempo_espera')
->select(
'id',
'cor'
)
->whereNull('deleted_at')
->where('tempo', '>=', $tempoEsperaTotal)
->where('infraestrutura_id', $centroCustoLogado->infraestrutura_id)
->orderBy('tempo')
->first();
}
$tempoEsperaTotal = Carbon::now()->subMinutes($tempoEsperaTotal)->diff(Carbon::now());
return [
'id' => $tempoEspera->id ?? null,
'cor' => $tempoEspera->cor ?? null,
'total' => [
'dias' => (int) $tempoEsperaTotal->format('%d') > 0 ? (int) $tempoEsperaTotal->format('%d') : null,
'horas' => (int) $tempoEsperaTotal->format('%h') ?? null,
'minutos' => (int) $tempoEsperaTotal->format('%i') ?? null,
],
];
}
private static function getTemposEspera()
{
return DB::table('painel_senha_tempo_espera')
->select([
'painel_senha_tempo_espera.id',
DB::raw("CONCAT(painel_senha_tempo_espera.tempo, ' MINUTO(S)') AS minutos"),
])
->whereNull('painel_senha_tempo_espera.deleted_at')
->whereExists(fn ($q) => $q->select(DB::raw(1))
->from('cadastro_infraestrutura')
->whereNull('cadastro_infraestrutura.deleted_at')
->whereExists(fn ($q) => $q->select(DB::raw(1))
->from('cadastro_centro_custo')
->whereNull('cadastro_centro_custo.deleted_at')
->where('cadastro_centro_custo.id', self::getCurrentCentroCusto()->id)
->whereColumn('cadastro_centro_custo.infraestrutura_id', 'cadastro_infraestrutura.id')
)
->whereColumn('cadastro_infraestrutura.id', 'painel_senha_tempo_espera.infraestrutura_id')
)
->orderBy('painel_senha_tempo_espera.tempo')
->get();
}
private static function getOpcoesEntrada()
{
$centroCusto = self::getCurrentCentroCusto();
return DB::table('painel_senha_opcao_entrada')
->select([
'painel_senha_opcao_entrada.id',
'painel_senha_opcao_entrada.nome',
'painel_senha_opcao_entrada.prioridade_obrigatoria',
])
->whereNull('painel_senha_opcao_entrada.deleted_at')
->where('painel_senha_opcao_entrada.modulo_id', ModuloService::getId(Modulo::IMUNIZACAO))
->where(fn ($q) => $q->where('painel_senha_opcao_entrada.centro_custo_id', $centroCusto->id)
->orWhereExists(fn ($q) => $q->select(DB::raw(1))
->from('painel_senha_centro_custo_compartilhado')
->where('painel_senha_centro_custo_compartilhado.centro_custo_id', $centroCusto->id)
->whereColumn('painel_senha_centro_custo_compartilhado.opcao_entrada_id', 'painel_senha_opcao_entrada.id')
)
)
->orderBy('painel_senha_opcao_entrada.nome')
->get();
}
private static function getPrioridades()
{
return DB::table('painel_senha_prioridade')
->select([
'painel_senha_prioridade.id',
'painel_senha_prioridade.nome',
])
->orderBy('painel_senha_prioridade.nome')
->get();
}
private static function getStatus()
{
return DB::table('painel_senha_status')
->select([
'id',
'nome',
])
->orderBy('painel_senha_status.nome')
->get();
}
private static function getSalas()
{
return DB::table('cadastro_sala')
->select([
'cadastro_sala.id',
'cadastro_sala.nome',
])
->whereNull('cadastro_sala.deleted_at')
->where('centro_custo_id', self::getCurrentCentroCusto()->id)
->orderBy('cadastro_sala.nome')
->get();
}
private static function getTelas()
{
return DB::table('painel_senha_tela')
->select([
'painel_senha_tela.id',
'painel_senha_tela.nome',
])
->whereNull('painel_senha_tela.deleted_at')
->whereExists(fn ($q) => $q->select(DB::raw(1))
->from('painel_senha_opcao_chamada')
->whereNull('painel_senha_opcao_chamada.deleted_at')
->where('painel_senha_opcao_chamada.centro_custo_id', self::getCurrentCentroCusto()->id)
->whereColumn('painel_senha_opcao_chamada.tela_id', 'painel_senha_tela.id')
)
->orderBy('painel_senha_tela.nome')
->get();
}
}