join( 'pronto_atendimento_plantao_status', 'pronto_atendimento_plantao.status_id', '=', 'pronto_atendimento_plantao_status.id' ) ->join( "cadastro_lotacao", "pronto_atendimento_plantao.lotacao_id", '=', "cadastro_lotacao.id" ) ->join( "cadastro_servico", "pronto_atendimento_plantao.servico_id", '=', "cadastro_servico.id" ) ->join( "cadastro_infraestrutura", "cadastro_lotacao.infraestrutura_id", '=', "cadastro_infraestrutura.id" ) ->join( 'cadastro_unidade', "cadastro_infraestrutura.unidade_id", '=', 'cadastro_unidade.id' ) ->join( "sigtap.ocupacao", "cadastro_lotacao.ocupacao_id", '=', "sigtap.ocupacao.id" ) ->join( "cadastro_usuario", "cadastro_lotacao.usuario_id", '=', "cadastro_usuario.id" ) ->join( "cadastro_cidadao", "cadastro_usuario.cidadao_id", '=', "cadastro_cidadao.id" ) ->leftJoin( "geral_faixa_etaria", "pronto_atendimento_plantao.faixa_etaria_id", '=', "geral_faixa_etaria.id" ) ->select( 'pronto_atendimento_plantao.id', DB::raw("DATE_FORMAT(pronto_atendimento_plantao.inicio, '%d/%m/%Y %H:%i') as inicio"), DB::raw("DATE_FORMAT(pronto_atendimento_plantao.fim, '%d/%m/%Y %H:%i') as fim"), 'pronto_atendimento_plantao.quantidade_atendimentos', 'pronto_atendimento_plantao.status_id', 'cadastro_unidade.nome_fantasia as unidade_nome_fantasia', 'cadastro_servico.nome as nome_servico', DB::raw('IF(cadastro_infraestrutura.nome IS NULL, ' . 'cadastro_unidade.nome_fantasia, cadastro_infraestrutura.nome) as infraestrutura_nome'), 'cadastro_cidadao.nome as cidadao_nome', DB::raw("IF(geral_faixa_etaria.nome IS NULL, " . "'TODOS', geral_faixa_etaria.nome) as faixa_etaria_nome"), DB::raw("CONCAT(sigtap.ocupacao.codigo, ' - ', sigtap.ocupacao.nome) as ocupacao_codigo_nome") ) ->whereNull('pronto_atendimento_plantao.deleted_at'); if (DataUtil::isStringTrue(request()->query('current_date'))) { $currentTimestamp = Carbon::now(); if (DataUtil::isStringTrue(request()->query('one_hour_before_start'))) { $plantoes->whereRaw("DATE_SUB(pronto_atendimento_plantao.inicio, INTERVAL 60 MINUTE) " . "<= '{$currentTimestamp->format('Y-m-d H:i:s')}'"); } else { $plantoes->where('pronto_atendimento_plantao.inicio', '<=', $currentTimestamp->format('Y-m-d H:i:s')); } $plantoes->where('pronto_atendimento_plantao.fim', '>=', $currentTimestamp->format('Y-m-d H:i:s')); } else { if (DateTimeUtil::isFormattedCorrectly(request()->query('inicio'), 'Y-m-d H:i')) { $plantoes->where('pronto_atendimento_plantao.inicio', '>=', request()->query('inicio')); } if (DateTimeUtil::isFormattedCorrectly(request()->query('fim'), 'Y-m-d H:i')) { $plantoes->where('pronto_atendimento_plantao.fim', '<=', request()->query('fim')); } } if (is_numeric(request()->query('unidade_id'))) { $plantoes->where('cadastro_unidade.id', request()->query('unidade_id')); } if (is_numeric(request()->query('infraestrutura_id'))) { $plantoes->where("cadastro_lotacao.infraestrutura_id", request()->query('infraestrutura_id')); } if (is_numeric(request()->query('usuario_id'))) { $plantoes->where('cadastro_lotacao.usuario_id', request()->query('usuario_id')); } if (is_numeric(request()->query('servico_id'))) { $plantoes->where('pronto_atendimento_plantao.servico_id', request()->query('servico_id')); } if (is_numeric(request()->query('ocupacao_id'))) { $plantoes->where('cadastro_lotacao.ocupacao_id', request()->query('ocupacao_id')); } if (is_numeric(request()->query('status_id'))) { $plantoes->where('pronto_atendimento_plantao.status_id', request()->query('status_id')); } else if (is_array(request()->query('status_id'))) { $plantoes->whereIn('pronto_atendimento_plantao.status_id', request()->query('status_id')); } if (is_string(request()->query('order_by'))) { switch (request()->query('order_by')) { case 'inicio': { $plantoes->orderBy('pronto_atendimento_plantao.inicio'); break; } case 'fim': { $plantoes->orderBy('pronto_atendimento_plantao.fim'); break; } case 'unidade': { $plantoes->orderBy("cadastro_unidade.nome_fantasia"); break; } case 'infraestrutura': { $plantoes->orderByRaw("IF (cadastro_infraestrutura.nome IS NULL, cadastro_unidade.nome_fantasia, cadastro_infraestrutura.nome )"); break; } case 'servico': { $plantoes->orderBy("cadastro_servico.nome"); break; } case 'usuario': { $plantoes->orderBy("cadastro_cidadao.nome"); break; } case 'ocupacao': { $plantoes->orderBy("sigtap.ocupacao.codigo"); break; } case 'status': { $plantoes->orderBy('pronto_atendimento_plantao_status.nome'); break; } } } return response()->json($plantoes->get(), Response::HTTP_OK); } public function list() { $this->auth(__FUNCTION__); return response()->json( [ 'data_atual' => Carbon::now()->format('d/m/Y'), 'form' => [ 'unidades' => $this->getUnidadesComLotacaoCentroCusto(), 'status' => Status::orderBy('nome')->get()->map(fn ($status) => [ 'id' => $status->id, 'nome' => $status->nome, 'cor' => $status->cor, 'cor_hover' => $status->cor_hover, ]), 'servicos' => Servico::orderBy('nome')->get()->map(fn ($servicos) => [ 'id' => $servicos->id, 'nome' => $servicos->nome, ]), 'ordenacao' => [ ['value' => 'ocupacao', 'text' => 'CBO'], ['value' => 'inicio', 'text' => 'DATA DE ENTRADA'], ['value' => 'fim', 'text' => 'DATA DE SAÍDA'], ['value' => 'infraestrutura', 'text' => 'LOCAL DE ATENDIMENTO'], ['value' => 'usuario', 'text' => 'PROFISSIONAL'], ['value' => 'servico', 'text' => 'SERVIÇO'], ['value' => 'status', 'text' => 'STATUS'], ], ] ], Response::HTTP_OK ); } public function index() { $this->auth(__FUNCTION__); $plantoes = $this->get(Plantao::class); if (is_numeric(request()->query('not_id'))) { $plantoes->where('id', '<>', request()->query('not_id')); } if (is_numeric(request()->query('usuario_id'))) { $plantoes->whereHas('lotacao', function ($lotacao) { $lotacao->where('usuario_id', request()->query('usuario_id')); }); } $plantoes = $plantoes->get(); $restParams = $this->getRestParams(); if (!empty($restParams)) { $inicioDescanso = $restParams['inicio']; $fimDescanso = $restParams['fim']; $between = fn ($value, $start, $end) => !is_null($value) && $value >= $start && $value <= $end; $plantoes = $plantoes ->filter(function ($plantao) use ($between, $inicioDescanso, $fimDescanso) { $periodoDescanso = $plantao->periodo_descanso; if (empty($periodoDescanso)) { return false; } return $between($inicioDescanso, $periodoDescanso['inicio'], $periodoDescanso['fim']) || $between($fimDescanso, $periodoDescanso['inicio'], $periodoDescanso['fim']); }) ->values(); } return response()->json($plantoes, Response::HTTP_OK); } private function getRestParams() { if (is_array(request()->query('resting'))) { $restParams = request()->query('resting'); $inicio = null; $fim = null; if (DateTimeUtil::isFormattedCorrectly($restParams['inicio'] ?? '', 'Y-m-d H:i:s')) { $inicio = new Carbon(request()->query('resting')['inicio']); } if (DateTimeUtil::isFormattedCorrectly($restParams['fim'] ?? '', 'Y-m-d H:i:s')) { $fim = new Carbon(request()->query('resting')['fim']); } return compact('inicio', 'fim'); } return []; } public function create() { $this->auth(__FUNCTION__); return response()->json( [ 'min_date' => Carbon::now()->subYear()->format('d/m/Y'), 'max_date' => Carbon::now()->addYear()->format('d/m/Y'), 'form' => $this->getFormData(), 'additionals' => [ 'status_id' => null ] ], Response::HTTP_OK ); } public function store(PlantaoRequest $request) { $this->auth(__FUNCTION__); $this->validateBusinessRules(); if ($this->hasBusinessRulesErrors()) { return response()->json($this->businessRulesErrors, Response::HTTP_UNPROCESSABLE_ENTITY); } $plantoes = null; DB::transaction(function () use (&$plantoes, $request) { $data = [ 'lotacao_id' => $request->lotacao_id, 'servico_id' => $request->servico_id, 'faixa_etaria_id' => $request->faixa_etaria_id, 'escala_tipo_id' => $request->escala['tipo_id'], 'status_id' => $request->status_id, ]; if ($request->escala['tipo_id'] === TipoEscala::FIXA) { $plantoes = $this->createPlantoesWithEscalasFixasTo($data); } else if ($request->escala['tipo_id'] === TipoEscala::DINAMICA) { $plantoes = $this->createPlantoesWithEscalasDinamicasTo($data); } else if ($request->escala['tipo_id'] === TipoEscala::UNICA) { $plantoes = $this->createPlantaoWithEscalaUnicaTo($data); } }); return response()->json($plantoes, Response::HTTP_CREATED); } private function createPlantoesWithEscalasFixasTo($data) { $plantoes = collect(); $inicioOfInterval = new Carbon(request()->escala['inicio']); $fimOfInterval = new Carbon(request()->escala['fim'] . " {$inicioOfInterval->format('H:i:s')}"); $jornadaEmHoras = request()->escala['jornada_em_horas']; $diasSemana = request()->escala['dias_semana']; $currentDate = $inicioOfInterval->copy(); while ($currentDate <= $fimOfInterval) { if (in_array($currentDate->format('w') + 1, $diasSemana)) { $fim = $currentDate->copy()->modify("+{$jornadaEmHoras} hours"); $this->validateTimeEscala($data['lotacao_id'], $currentDate, $fim); $this->verificaConflitoTempoAdicionalPlantao($data['lotacao_id'], $currentDate); $plantao = Plantao::create([ 'lotacao_id' => $data['lotacao_id'], 'servico_id' => $data['servico_id'], 'faixa_etaria_id' => $data['faixa_etaria_id'], 'escala_tipo_id' => $data['escala_tipo_id'], 'inicio' => $currentDate->format('Y-m-d H:i'), 'fim' => $fim->format('Y-m-d H:i'), 'quantidade_atendimentos' => request()->escala['quantidade_atendimentos'], 'status_id' => $data['status_id'] ?? PlantaoStatus::CADASTRADO, ]); $plantoes->push($plantao); } $currentDate->addDay(); } } private function createPlantoesWithEscalasDinamicasTo($data) { $plantoes = collect(); $inicioOfInterval = new Carbon(request()->escala['inicio']); $fimOfInterval = new Carbon(request()->escala['fim'] . " {$inicioOfInterval->format('H:i:s')}"); $jornadaEmHoras = request()->escala['jornada_em_horas']; $restHours = $this->getRestHours(); $inicio = $inicioOfInterval->copy(); while ($inicio <= $fimOfInterval) { $fim = $inicio->copy()->modify("+{$jornadaEmHoras} hours"); $this->validateTimeEscala($data['lotacao_id'], $inicio, $fim); $this->verificaConflitoTempoAdicionalPlantao($data['lotacao_id'], $inicio); $plantao = Plantao::create([ 'lotacao_id' => $data['lotacao_id'], 'servico_id' => $data['servico_id'], 'faixa_etaria_id' => $data['faixa_etaria_id'], 'escala_tipo_id' => $data['escala_tipo_id'], 'inicio' => $inicio->format('Y-m-d H:i'), 'fim' => $fim->format('Y-m-d H:i'), 'quantidade_atendimentos' => request()->escala['quantidade_atendimentos'], 'status_id' => $data['status_id'] ?? PlantaoStatus::CADASTRADO, ]); $plantoes->push($plantao); $inicio = $fim->modify("+{$restHours} hours"); } } private function getRestHours() { switch (request()->escala['jornada_em_horas']) { case 6: { return 18; } case 8: { return 16; } case 12: { return 36; } case 24: { return 48; } } } private function createPlantaoWithEscalaUnicaTo($data) { $inicio = new Carbon(request()->escala['inicio']); $fim = new Carbon(request()->escala['fim']); $this->validateTimeEscala($data['lotacao_id'], $inicio, $fim); $this->verificaConflitoTempoAdicionalPlantao($data['lotacao_id'], $inicio); return Plantao::create([ 'lotacao_id' => $data['lotacao_id'], 'servico_id' => $data['servico_id'], 'faixa_etaria_id' => $data['faixa_etaria_id'], 'escala_tipo_id' => $data['escala_tipo_id'], 'inicio' => $inicio->format('Y-m-d H:i'), 'fim' => $fim->format('Y-m-d H:i'), 'quantidade_atendimentos' => request()->escala['quantidade_atendimentos'], 'status_id' => $data['status_id'] ?? PlantaoStatus::CADASTRADO, ]); } public function show($id) { $this->auth(__FUNCTION__); $plantao = $this->get(Plantao::class, $id); return response()->json($plantao, Response::HTTP_OK); } public function edit($id) { $this->auth(__FUNCTION__); $plantao = Plantao::findOrFail($id); return response()->json( [ 'min_date' => Carbon::now()->subYear()->format('d/m/Y'), 'max_date' => Carbon::now()->addYear()->format('d/m/Y'), 'form' => array_merge($this->getFormData(), [ 'unidade_id' => $plantao->lotacao->unidade_id, 'infraestrutura_id' => $plantao->lotacao->infraestrutura_id, 'servico_id' => $plantao->servico_id, 'usuario_id' => $plantao->lotacao->usuario_id, 'ocupacao_id' => $plantao->lotacao->ocupacao_id, ]), 'model' => [ 'faixa_etaria_id' => $plantao->faixa_etaria_id, 'escala' => [ 'periodo' => [ 'start' => $plantao->inicio->format('d/m/Y'), 'end' => $plantao->fim->format('d/m/Y'), ], 'hora_entrada' => $plantao->inicio->format('H:i:s'), 'hora_saida' => $plantao->fim->format('H:i:s'), 'quantidade_atendimentos' => $plantao->quantidade_atendimentos, ] ], 'additionals' => [ 'status_id' => $plantao->status_id ] ], Response::HTTP_OK ); } private function getFormData() { return [ 'servicos' => Servico::orderBy('nome')->get()->map(fn ($servicos) => [ 'id' => $servicos->id, 'nome' => $servicos->nome, ]), 'unidades' => $this->getUnidadesComLotacaoCentroCusto(), 'faixas_etarias' => FaixaEtaria::orderBy('nome')->get(), 'dias_semana' => [ ['value' => 1, 'text' => 'Domingo', 'disabled' => true], ['value' => 2, 'text' => 'Segunda', 'disabled' => true], ['value' => 3, 'text' => 'Terça', 'disabled' => true], ['value' => 4, 'text' => 'Quarta', 'disabled' => true], ['value' => 5, 'text' => 'Quinta', 'disabled' => true], ['value' => 6, 'text' => 'Sexta', 'disabled' => true], ['value' => 7, 'text' => 'Sábado', 'disabled' => true], ], 'jornadas' => [ ['value' => 6, 'text' => '6 H'], ['value' => 8, 'text' => '8 H'], ['value' => 12, 'text' => '12 H'], ['value' => 24, 'text' => '24 H'], ], 'descansos' => [ ['text' => '16 H', 'value' => 16, 'disabled' => true], ['text' => '18 H', 'value' => 18, 'disabled' => true], ['text' => '36 H', 'value' => 36, 'disabled' => true], ['text' => '48 H', 'value' => 48, 'disabled' => true], ], ]; } private function getUnidadesComLotacaoCentroCusto() { $unidades = DB::table('cadastro_unidade') ->whereExists(function ($query) { $query ->select(DB::raw(1)) ->from('cadastro_infraestrutura') ->whereColumn('cadastro_infraestrutura.unidade_id', 'cadastro_unidade.id') ->whereExists(function ($query) { $query ->select(DB::raw(1)) ->from('cadastro_lotacao') ->whereColumn('cadastro_lotacao.infraestrutura_id', 'cadastro_infraestrutura.id'); }) ->whereExists(function ($query) { $query ->select(DB::raw(1)) ->from('cadastro_centro_custo') ->whereColumn('cadastro_centro_custo.infraestrutura_id', 'cadastro_infraestrutura.id'); }); }) ->select( 'cadastro_unidade.id', 'cadastro_unidade.nome_fantasia' ) ->orderBy('cadastro_unidade.nome_fantasia') ->get(); $unidades->each(function ($unidade) { $unidade->infraestruturas = DB::table('cadastro_infraestrutura') ->where('cadastro_infraestrutura.unidade_id', $unidade->id) ->whereExists(function ($query) { $query ->select(DB::raw(1)) ->from('cadastro_lotacao') ->whereColumn('cadastro_lotacao.infraestrutura_id', 'cadastro_infraestrutura.id'); }) ->whereExists(function ($query) { $query ->select(DB::raw(1)) ->from('cadastro_centro_custo') ->whereColumn('cadastro_centro_custo.infraestrutura_id', 'cadastro_infraestrutura.id'); }) ->select( 'cadastro_infraestrutura.id', DB::raw("COALESCE(cadastro_infraestrutura.nome, '{$unidade->nome_fantasia}') AS nome") ) ->orderByRaw("COALESCE(cadastro_infraestrutura.nome, '{$unidade->nome_fantasia}')") ->get(); $unidade->infraestruturas->each(function ($infraestrutura) { $infraestrutura->usuarios = DB::table('cadastro_usuario') ->join( 'cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_usuario.cidadao_id' ) ->whereExists(function ($query) use ($infraestrutura) { $query ->select(DB::raw(1)) ->from('cadastro_lotacao') ->whereColumn('cadastro_lotacao.usuario_id', 'cadastro_usuario.id') ->where('cadastro_lotacao.infraestrutura_id', $infraestrutura->id) ->whereNull('cadastro_lotacao.deleted_at') ->where('realiza_atendimento', true); }) ->select( 'cadastro_usuario.id', 'cadastro_cidadao.nome' ) ->orderBy('cadastro_cidadao.nome') ->get(); $infraestrutura->usuarios->each(function ($usuario) use ($infraestrutura) { $usuario->ocupacoes = DB::table('sigtap.ocupacao') ->join( 'cadastro_lotacao', 'cadastro_lotacao.ocupacao_id', 'sigtap.ocupacao.id' ) ->where('cadastro_lotacao.usuario_id', $usuario->id) ->where('cadastro_lotacao.infraestrutura_id', $infraestrutura->id) ->whereNull('cadastro_lotacao.deleted_at') ->where('realiza_atendimento', true) ->select( 'sigtap.ocupacao.id', DB::raw("CONCAT(sigtap.ocupacao.codigo, ' - ', sigtap.ocupacao.nome) as codigo_nome"), 'cadastro_lotacao.id AS lotacao_id' ) ->orderBy('sigtap.ocupacao.nome') ->get(); }); }); }); return $unidades; } public function update(PlantaoRequest $request, $id) { $this->auth(__FUNCTION__); $plantao = Plantao::findOrFail($id); $params = $request->all(); if (!empty($params)) { if (isset($params['status_id']) && is_numeric($params['status_id'])) { $plantao->status_id = $params['status_id']; } if (isset($params['escala'])) { $escala = $params['escala']; if (isset($escala['inicio'])) { $this->validateBusinessRulesToUpdateSinglePlantao($plantao); if ($this->hasBusinessRulesErrors()) { return response()->json($this->businessRulesErrors, Response::HTTP_UNPROCESSABLE_ENTITY); } $inicio = new Carbon($escala['inicio']); $fim = new Carbon($escala['fim']); $this->validateTimeEscala($plantao->lotacao_id, $inicio, $fim, $plantao->id); $plantao->inicio = $escala['inicio']; $plantao->fim = $escala['fim']; } if (isset($escala['quantidade_atendimentos']) && is_numeric($escala['quantidade_atendimentos'])) { $plantao->quantidade_atendimentos = $escala['quantidade_atendimentos']; } } $plantao->save(); } return response()->json($plantao->fresh(), Response::HTTP_OK); } public function updateAllStatus() { $this->auth(__FUNCTION__); $plantoes = collect(); collect(request()->all())->each(function ($plantao) use ($plantoes) { $plantao = tap(Plantao::findOrFail($plantao['id']))->update($plantao); $plantoes->push($plantao->fresh()); }); return response()->json($plantoes, Response::HTTP_OK); } public function destroy($id) { $this->auth(__FUNCTION__); Plantao::findOrFail($id)->delete(); return response()->json(null, Response::HTTP_NO_CONTENT); } public function destroyAll() { $this->auth(__FUNCTION__); Plantao::destroy(request()->all()); return response()->json(null, Response::HTTP_NO_CONTENT); } private function validateBusinessRules() { $this->validateInicio(); $this->validateFim(); if ($this->isEscalaTipoFixa()) { $this->validateDiasSemana(); } } private function validateBusinessRulesToUpdateSinglePlantao($plantao) { $this->validateInicio($plantao); $this->validateFim($plantao); } private function validateInicio($plantao = null) { $errors = []; if ($this->isInicioLessThanMinDate()) { $errors[] = 'A data/hora inicial não pode ser uma data/hora anterior a um ano anterior da data atual.'; } $inicio = new Carbon(request()->escala['inicio']); if ($plantao && $plantao->date_time_of_first_atendimento && $inicio > $plantao->date_time_of_first_atendimento) { $errors[] = "Início do plantão deve ser inferior ou igual ao primeiro " . "atendimento {$plantao->date_time_of_first_atendimento->format('d/m/Y H:i')}."; } if (!empty($errors)) { $this->businessRulesErrors['escala.inicio'] = $errors; } } private function isInicioLessThanMinDate() { $minDate = Carbon::now()->subYear(); return new Carbon(request()->escala['inicio']) < $minDate; } private function validateFim($plantao = null) { $errors = []; if ($this->isFimGreaterThanMaxDate()) { $errors[] = 'A data/hora final não pode ser uma data/hora posterior a um ano anterior da data atual.'; } if ($this->isEscalaTipoUnica() && $this->isFimGreaterThan24HoursFromInicio()) { $errors[] = 'A data/hora final não pode ultrapassar 24 horas da data/hora inicial.'; } $fim = new Carbon(request()->escala['fim']); if ($plantao && $plantao->date_time_of_last_atendimento && $fim < $plantao->date_time_of_last_atendimento) { $errors[] = "Fim do plantão deve ser superior ou igual ao último " . "atendimento {$plantao->date_time_of_last_atendimento->format('d/m/Y H:i')}."; } if (!empty($errors)) { $this->businessRulesErrors['escala.fim'] = $errors; } } private function isFimGreaterThanMaxDate() { $maxDate = Carbon::now()->addYear(); return new Carbon(request()->escala['fim']) > $maxDate; } private function isEscalaTipoUnica() { return request()->escala['tipo_id'] === TipoEscala::UNICA; } private function isFimGreaterThan24HoursFromInicio() { $dateAfterInicio = (new Carbon(request()->escala['inicio']))->addDay(); return new Carbon(request()->escala['fim']) > $dateAfterInicio; } private function isEscalaTipoFixa() { return request()->escala['tipo_id'] === TipoEscala::FIXA; } private function validateDiasSemana() { if ($this->isJornada12Hours()) { $this->validateDiasSemanaToJornada12Hours(); } else if ($this->isJornada24Hours()) { $this->validateDiasSemanaToJornada24Hours(); } } private function isJornada12Hours() { return request()->escala['jornada_em_horas'] === 12; } private function validateDiasSemanaToJornada12Hours() { $errors = []; if ($this->hasNotAllowedDiasSemanaInDiasSemana($this->getNotAllowedDiasSemanaToJornada12Hours())) { $errors[] = 'Se a jornada for de 12 horas, então deverá ter um intervalo de 1 dia ' . 'anterior e 1 dia posterior entre os dias da semana.'; } if (!empty($errors)) { $this->businessRulesErrors['escala.dias_semana.*'] = $errors; } } private function getNotAllowedDiasSemanaToJornada12Hours() { $notAllowedDiasSemana = []; foreach (request()->escala['dias_semana'] as $dia) { array_push($notAllowedDiasSemana, WeekCalc::sub($dia, 1), WeekCalc::sum($dia, 1)); } return $notAllowedDiasSemana; } private function isJornada24Hours() { return request()->escala['jornada_em_horas'] === 24; } private function validateDiasSemanaToJornada24Hours() { $errors = []; if ($this->hasNotAllowedDiasSemanaInDiasSemana($this->getNotAllowedDiasSemanaToJornada24Hours())) { $errors[] = 'Se a jornada for de 24 horas, então deverá ter um intervalo de 2 dias ' . 'anteriores e 2 dias posteriores entre os dias da semana.'; } if (!empty($errors)) { $this->businessRulesErrors['escala.dias_semana.*'] = $errors; } } private function hasNotAllowedDiasSemanaInDiasSemana($notAllowedDiasSemana) { foreach (request()->escala['dias_semana'] as $dia) { if (in_array($dia, $notAllowedDiasSemana)) { return true; } } } private function getNotAllowedDiasSemanaToJornada24Hours() { $notAllowedDiasSemana = []; foreach (request()->escala['dias_semana'] as $dia) { array_push( $notAllowedDiasSemana, WeekCalc::sub($dia, 1), WeekCalc::sub($dia, 2), WeekCalc::sum($dia, 1), WeekCalc::sum($dia, 2) ); } return $notAllowedDiasSemana; } private function hasBusinessRulesErrors() { return !empty($this->businessRulesErrors); } private function validateTimeEscala($lotacaoId, $inicio, $fim, $currentPlantaoId = null) { $usuarioId = Lotacao::findOrFail($lotacaoId)->usuario_id; if ($this->isConflictingEscala($usuarioId, $inicio, $fim, $currentPlantaoId)) { throw new ConflictingPlantaoException; } } private function isConflictingEscala($usuarioId, $inicio, $fim, $currentPlantaoId = null) { return Plantao::whereHas('lotacao', function ($lotacao) use ($usuarioId) { $lotacao->where('usuario_id', $usuarioId); })->when($currentPlantaoId, function ($query, $id) { $query->where('id', '<>', $id); })->where(function ($plantao) use ($inicio, $fim) { $plantao ->where(function ($plantao) use ($inicio) { $plantao ->where('inicio', '<=', $inicio) ->where('fim', '>=', $inicio); }) ->orWhere(function ($plantao) use ($fim) { $plantao ->where('inicio', '<=', $fim) ->where('fim', '>=', $fim); }) ->orWhere(function ($plantao) use ($inicio, $fim) { $plantao ->where('inicio', '>=', $inicio) ->where('inicio', '<=', $fim); }) ->orWhere(function ($plantao) use ($inicio, $fim) { $plantao ->where('fim', '>=', $inicio) ->where('fim', '<=', $fim); }); })->exists(); } private function verificaConflitoTempoAdicionalPlantao($lotacaoId, $inicio) { $parametrizacao = Parametrizacao::first(); if (!is_null($parametrizacao) && $parametrizacao->tempo_adicional_plantao > 0) { $plantaoComTempoAdicionalConflitante = Plantao::where('lotacao_id', $lotacaoId) ->whereDate('fim', $inicio->format('Y-m-d')) ->where('fim', '>=', $inicio->subMinutes($parametrizacao->tempo_adicional_plantao ?? 0)->format('Y-m-d H:i')) ->exists(); if ($plantaoComTempoAdicionalConflitante) { throw new PlantaoComTempoAdicionalConflitanteException(); } } } }