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') ->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, CONCAT(municipio.nome, ' / ', estado.uf) as municipio_uf, 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() { $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(request()->paciente_id, fn ($q, $id) => $q->where('agendamento.paciente_id', $id)) ->whereDate('jornada.data', '<', Carbon::today()) ->when(request()->periodo, fn ($q, $periodo) => $q ->whereBetween('jornada.data', [ Carbon::createFromFormat('d/m/Y', $periodo['start'])->startOfDay(), Carbon::createFromFormat('d/m/Y', $periodo['end'])->endOfDay(), ]) ) ->when(request()->inicio && request()->fim, fn ($q) => $q ->whereBetween('agendamento.horario', [request()->inicio, request()->fim]) ) ->when(request()->unidade_id, fn ($q, $id) => $q->where('unidade.id', $id)) ->when(request()->infraestrutura_id, fn ($q, $id) => $q->where('infraestrutura.id', $id)) ->when(request()->ocupacao_id, fn ($q, $id) => $q->where('ocupacao.id', $id)) ->when(request()->especialidade_id, fn ($q, $id) => $q->where('especialidade.id', $id)) ->when(request()->usuario_id, fn ($q, $id) => $q->where('usuario.id', $id)) ->when(request()->tipo_id, fn ($q, $id) => $q->where('tipo.id', $id)) ->when(request()->status_id, fn ($q, $id) => $q->where('status.id', $id)) ->select(DB::raw(" agendamento.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) { $agendamento->permite_exclusao = !$agendamento->has_atendimento && $agendamento->status_id === AgendamentoStatusEnum::AGENDADO; unset($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(); $cadastroParametrizacao = Parametrizacao::first(); return [ 'additionals' => [ 'data_ontem' => Carbon::yesterday()->format('d/m/Y'), 'avisa_cns_provisorio' => self::avisaCnsProvisorio($parametrizacao, $paciente), 'cadastro_paciente_vencido' => ($parametrizacao->bloqueia_paciente_temporario ?? false) && PacienteController::isCadastroPacienteVencido($paciente->id), 'cns_valido' => Cns::isValid($paciente->cidadao->cns), 'avisa_cns_temporario_invalido' => $cadastroParametrizacao->exibe_alerta_paciente_cns_temporario_invalido ?? false, 'permissoes_atualizacao_cadastro_paciente' => self::getPermissoesAtualizacaoCadastroPaciente(), ], 'form' => [ '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), 'unidades' => [], 'infraestruturas' => [], 'ocupacoes' => [], 'especialidades' => [], 'usuarios' => [], 'tipos' => [], 'status' => [], ], 'model' => [ '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, ] ]; } private static function avisaCnsProvisorio($parametrizacao, $paciente) { return $parametrizacao->avisa_cns_provisorio && 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(), 'form' => [ 'feriados' => self::getFeriados(), 'datas_com_agendamento' => self::getCadastroDatasComAgendamento($params), 'unidades' => self::getCadastroUnidades($params), 'infraestruturas' => [], 'ocupacoes' => [], 'especialidades' => [], 'usuarios' => [], 'tipos' => [], 'datas' => [], 'datas_bloqueadas' => [], 'horarios' => [], 'horarios_com_situacao' => [], 'quantidade_demanda_espontanea' => null, ], 'model' => [ 'unidade_id' => null, 'infraestrutura_id' => null, 'ocupacao_id' => null, 'especialidade_id' => null, 'usuario_id' => null, 'tipo_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, 'tipo_id' => $agendamento->tipo_id, 'data' => $agendamento->jornada->data->format('d/m/Y'), ]; 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), 'usuarios' => self::getCadastroUsuarios($params), 'tipos' => self::getCadastroTipos($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), ], '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, 'tipo_id' => $agendamento->tipo_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 [ '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) { $agendamentosAmbulatorio = Agendamento::where('paciente_id', $params->paciente_id) ->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, ]); return [ 'ambulatorio' => $agendamentosAmbulatorio, ]; } public static function list() { switch (request()->origem) { case 'busca': { return self::getDadosListBusca(); } case 'cadastro': { return self::getDadosListCadastro(); } } } 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 ->whereDate('data', '<', Carbon::today()) ->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 ->whereDate('data', '<', Carbon::today()) ->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') ->whereDate('jornada.data', '<', Carbon::today()) ->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 ->whereDate('data', '<', Carbon::today()) ->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 ->whereDate('data', '<', Carbon::today()) ->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 ->whereDate('data', '<', Carbon::today()) ->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 ->whereDate('data', '<', Carbon::today()) ->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(); $paciente = Paciente::setEagerLoads([])->where('id', $params->paciente_id)->first(); $params->paciente_nao_municipe = $paciente->classificacao_id !== Classificacao::MUNICIPE; switch (request()->listar) { case 'unidades': { return [ 'unidades' => self::getCadastroUnidades($params), 'infraestruturas' => [], 'ocupacoes' => [], 'especialidades' => [], 'usuarios' => [], 'tipos' => [], 'datas' => [], 'horarios' => [], ]; } case 'infraestruturas': { return [ 'infraestruturas' => self::getCadastroInfraestruturas($params), 'ocupacoes' => [], 'especialidades' => [], 'usuarios' => [], 'tipos' => [], 'datas' => [], 'horarios' => [], ]; } case 'ocupacoes': { return [ 'ocupacoes' => self::getCadastroOcupacoes($params), 'especialidades' => [], 'usuarios' => [], 'tipos' => [], 'datas' => [], 'horarios' => [], ]; } case 'especialidades': { return [ 'especialidades' => self::getCadastroEspecialidades($params), 'usuarios' => [], 'tipos' => [], 'datas' => [], 'horarios' => [], ]; } case 'usuarios': { return [ 'usuarios' => self::getCadastroUsuarios($params), 'tipos' => [], 'datas' => [], 'horarios' => [], ]; } case 'tipos': { return [ 'tipos' => self::getCadastroTipos($params), 'datas' => [], 'horarios' => [], ]; } case 'datas': { return [ 'datas' => self::getCadastroDatas($params), 'datas_bloqueadas' => self::getCadastroDatasBloqueadas($params), 'datas_com_agendamento' => self::getCadastroDatasComAgendamento($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, ), ], ]; } } } 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']); } private static function getCadastroUsuarios($params) { 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 ->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 getCadastroTipos($params) { $tipos = collect(); $hasJornada = function ($campoQuantidade) use ($params) { return Jornada::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) ) ) ->whereHas('lotacao', fn ($q) => $q ->where('infraestrutura_id', $params->infraestrutura_id) ->where('ocupacao_id', $params->ocupacao_id) ->where('usuario_id', $params->usuario_id) ) ->exists(); }; if ($hasJornada('quantidade_consulta')) { $tipos->push(AgendamentoTipo::find(AgendamentoTipoEnum::CONSULTA)); } if ($hasJornada('quantidade_retorno')) { $tipos->push(AgendamentoTipo::find(AgendamentoTipoEnum::RETORNO)); } return $tipos; } private static function getCadastroDatas($params) { $campoQuantidade = self::getCampoQuantidade($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}) 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(); }) ->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('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)->startOfDay(); 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', '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)}, '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(); if ($quantidade < $jornada->{self::getCampoQuantidade($tipoId)}) { $data = $jornada->inicio->copy(); self::setHorarioJornadaDinamica( $horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data ); } } 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) { $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 ); } 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 < $jornada->{self::getCampoQuantidade($tipoId)}) { $data->addMinutes($jornada->{self::getCampoTempo($tipoId)}); self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data); } } } else { if ($agendamento->tipo_id == $tipoId) { $data->addMinutes($jornada->{self::getCampoTempo($tipoId)}); self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data); } else { $data = $agendamento->horario->copy()->addMinutes($jornada->{self::getCampoTempo($tipoId, true)}); self::setHorarioJornadaDinamica($horarios, $agendamentos, $jornada, $tipoId, $quantidade, $data); } } } 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', ]) ->map(fn ($jornada) => [ 'inicio' => $jornada->inicio->format('H:i'), 'fim' => $jornada->fim->format('H:i'), '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 getCampoQuantidade($tipoId) { if ($tipoId == AgendamentoTipoEnum::CONSULTA) { return 'quantidade_consulta'; } else if ($tipoId == AgendamentoTipoEnum::RETORNO) { return 'quantidade_retorno'; } } 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 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, ]; } public static function store() { self::validateStore(); $agendamento = new Agendamento(); DB::transaction(function () use ($agendamento) { $jornada = Jornada::findOrFail(request()->jornada_id); self::validateProcedimentoGrupo(request()->paciente_id, $jornada->id); self::validateConflito( request()->paciente_id, $jornada->id, request()->horario, request()->tipo_id, request()->motivo_agendamento_excedente ); $agendamento->fill([ 'jornada_id' => $jornada->id, 'tipo_id' => request()->tipo_id, 'horario' => request()->horario, 'paciente_id' => request()->paciente_id, 'motivo_agendamento_excedente' => request()->motivo_agendamento_excedente, 'observacao' => request()->observacao, 'status_id' => AgendamentoStatusEnum::AGENDADO, ]); $agendamento->save(); }); return $agendamento->fresh(); } private static function validateStore() { request()->validate([ 'paciente_id' => [ 'required', Rule::exists(Paciente::class, 'id'), ], 'jornada_id' => [ 'required', Rule::exists(Jornada::class, 'id'), ], 'tipo_id' => [ 'required', Rule::exists(AgendamentoTipo::class, 'id'), ], 'horario' => [ 'required', 'date_format:H:i', ], 'observacao' => [ 'nullable', 'string', 'max:500', ], 'motivo_agendamento_excedente' => [ 'nullable', 'string', 'max:500', ], ]); } 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, $agendamentoTipoId = null, $motivoAgendamentoExcedente = null ) { if (!empty($motivoAgendamentoExcedente)) { return; } $paciente = Paciente::findOrFail($pacienteId); $jornada = Jornada::findOrFail($jornadaId); $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' => $agendamentoTipoId, ]; $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(); } } private static function getStatusLiberamHorario() { return [ AgendamentoStatusEnum::REAGENDADO_PELO_PACIENTE, AgendamentoStatusEnum::REAGENDADO_PELO_MEDICO, AgendamentoStatusEnum::CANCELADO_PELO_PACIENTE, AgendamentoStatusEnum::CANCELADO_PELO_MEDICO, ]; } 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 retroativo'], ); } $agendamento->delete(); }); } public static function getPrintData($id) { $agendamento = Agendamento::findOrFail($id); return [ '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, '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, ], 'observacao' => $agendamento->observacao, 'usuarioAgendamento' => [ 'nome' => $agendamento->createdLotacao->usuario->cidadao->nome, '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, ], ]; } 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) { if (empty($params->data)) { return 0; } $data = Carbon::createFromFormat('d/m/Y', $params->data)->startOfDay(); return DemandaEspontanea::whereHas('jornada', fn ($q) => $q->whereDate('data', $data) ->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(); } }