copy()->startOfWeek(Carbon::SUNDAY); $weekEnd = $date->copy()->endOfWeek(Carbon::SATURDAY); $weeklySchedulesCount = Schedule::where('client_id', $clientId) ->where('provider_id', $providerId) ->whereNotIn('status', self::EXCLUDED_STATUSES) ->whereBetween('date', [$weekStart->format('Y-m-d'), $weekEnd->format('Y-m-d')]) ->when($excludeScheduleId, function ($query) use ($excludeScheduleId) { $query->where('id', '!=', $excludeScheduleId); }) ->count(); if ($weeklySchedulesCount >= 2) { throw new \Exception(__('validation.custom.schedule.weekly_limit_exceeded')); } return true; } /** * Valida se o prestador tem horário de trabalho cadastrado para o dia da semana e período * @param int $provider_id * @param int $day_of_week (0 - domingo, 6 - sábado) * @param string $period ('morning' ou 'afternoon') * @return bool * @throws \Exception */ public static function validateWorkingDay($provider_id, $day_of_week, $period) { $workingDay = ProviderWorkingDay::where('provider_id', $provider_id) ->where('day', $day_of_week) ->where('period', $period) ->first(); if(!$workingDay) { throw new \Exception(__('validation.custom.schedule.provider_not_working')); } return true; } /** * Valida se o prestador tem bloqueio cadastrado para o dia e horário * @param int $provider_id * @param string $date_ymd (Y-m-d) * @param string $start_time (H:i:s) * @param string $end_time (H:i:s) * @return bool * @throws \Exception */ public static function validateBlockedDay($provider_id, $date_ymd, $start_time, $end_time) { $blockedDay = ProviderBlockedDay::where('provider_id', $provider_id) ->where('date', $date_ymd) ->where(function ($query) use ($start_time, $end_time) { $query->where('period', 'full') ->orWhere(function ($q) use ($start_time, $end_time) { $q->where('period', 'partial') ->where(function ($q2) use ($start_time, $end_time) { $q2->whereBetween('init_hour', [$start_time, $end_time]) ->orWhereBetween('end_hour', [$start_time, $end_time]) ->orWhere(function ($q3) use ($start_time, $end_time) { $q3->where('init_hour', '<=', $start_time) ->where('end_hour', '>=', $end_time); }); }); }); }) ->first(); if ($blockedDay) { throw new \Exception(__('validation.custom.schedule.provider_blocked')); } return true; } public static function validatePricePeriod($provider_id, $min_price, $max_price, $period_type) { if ($min_price < 0 || $max_price < 0) { throw new \Exception(__('validation.custom.schedule.invalid_price')); } if ($min_price > $max_price) { throw new \Exception(__('validation.custom.schedule.invalid_price_range')); } $provider = Provider::find($provider_id); $provider_price_period = 0; switch ($period_type): case '2': //2 horas $provider_price_period = $provider->daily_price_2h; break; case '4': //4 horas $provider_price_period = $provider->daily_price_4h; break; case '6': //6 horas $provider_price_period = $provider->daily_price_6h; break; case '8': //8 horas $provider_price_period = $provider->daily_price_8h; break; default: throw new \Exception(__('validation.custom.schedule.invalid_period_type')); endswitch; if ($provider_price_period < $min_price || $provider_price_period > $max_price) { throw new \Exception(__('validation.custom.schedule.price_not_in_range')); } return true; } /** * Valida se o prestador tem outro agendamento no mesmo dia e horário * @param int $provider_id * @param string $date_ymd (Y-m-d) * @param string $start_time (H:i:s) * @param string $end_time (H:i:s) * @param int|null $exclude_schedule_id (id do agendamento a ser excluído da validação, usado para edição de agendamento) * @return bool * @throws \Exception */ public static function validateConflictingSchedule($provider_id, $date_ymd, $start_time, $end_time, $exclude_schedule_id = null) { $conflictingSchedule = Schedule::where('provider_id', $provider_id) ->where('date', $date_ymd) ->whereIn('status', ['pending', 'accepted', 'paid', 'started']) ->where(function ($query) use ($start_time, $end_time) { $query->whereBetween('start_time', [$start_time, $end_time]) ->orWhereBetween('end_time', [$start_time, $end_time]) ->orWhere(function ($q) use ($start_time, $end_time) { $q->where('start_time', '<=', $start_time) ->where('end_time', '>=', $end_time); }); }) ->when($exclude_schedule_id, function ($query) use ($exclude_schedule_id) { $query->where('id', '!=', $exclude_schedule_id); }) ->first(); if ($conflictingSchedule) { throw new \Exception(__('validation.custom.schedule.provider_conflicting_schedule')); } return true; } /** * Valida se o prestador tem outro agendamento com o mesmo cliente no mesmo dia e horário * @param int $provider_id * @param string $date_ymd (Y-m-d) * @param string $start_time (H:i:s) * @param string $end_time (H:i:s) * @param int|null $exclude_schedule_id (id do agendamento a ser excluído da validação, usado para edição de agendamento) * @return bool * @throws \Exception */ public static function validateConflictingSameProposal($provider_id, $schedule_id) { $conflictingSameProposal = ScheduleProposal::where('schedule_proposals.provider_id', $provider_id) ->where('schedule_proposals.schedule_id', $schedule_id) ->leftJoin('schedules', 'schedule_proposals.schedule_id', '=', 'schedules.id') ->whereNotIn('schedules.status', self::EXCLUDED_STATUSES) ->first(); if ($conflictingSameProposal) { throw new \Exception(__('validation.custom.schedule.provider_conflicting_same_proposal')); } return true; } /** * Valida se o prestador tem outro agendamento com o mesmo cliente no mesmo dia e horário, ignorando o horário * @param int $provider_id * @param string $date_ymd (Y-m-d) * @param string $start_time (H:i:s) * @param string $end_time (H:i:s) * @param int|null $exclude_schedule_id (id do agendamento a ser excluído da validação, usado para edição de agendamento) * @return bool * @throws \Exception */ public static function validateConflictingProposalSameDate($provider_id, $date_ymd, $start_time, $end_time, $exclude_schedule_id = null) { $conflictingProposalSameDate = ScheduleProposal::where('schedule_proposals.provider_id', $provider_id) ->leftJoin('schedules', 'schedule_proposals.schedule_id', '=', 'schedules.id') ->where('schedules.date', $date_ymd) ->where(function ($query) use ($start_time, $end_time) { $query->whereBetween('schedules.start_time', [$start_time, $end_time]) ->orWhereBetween('schedules.end_time', [$start_time, $end_time]) ->orWhere(function ($q) use ($start_time, $end_time) { $q->where('schedules.start_time', '<=', $start_time) ->where('schedules.end_time', '>=', $end_time); }); }) ->whereNotIn('status', self::EXCLUDED_STATUSES) ->when($exclude_schedule_id, function ($query) use ($exclude_schedule_id) { $query->where('schedules.id', '!=', $exclude_schedule_id); }) ->first(); if ($conflictingProposalSameDate) { throw new \Exception(__('validation.custom.schedule.provider_conflicting_proposal_same_date')); } return true; } }