|
@@ -25,6 +25,7 @@ use App\Notifications\Push\Cliente\Agendamento\AgendamentoProximoPrestadorPush;
|
|
|
use App\Notifications\Push\Prestador\Agendamento\AgendamentoProximoClientePush;
|
|
use App\Notifications\Push\Prestador\Agendamento\AgendamentoProximoClientePush;
|
|
|
use App\Notifications\Push\Cliente\Agendamento\PrestadorCancelouPush;
|
|
use App\Notifications\Push\Cliente\Agendamento\PrestadorCancelouPush;
|
|
|
use App\Notifications\Push\Prestador\Agendamento\ClienteCancelouPush;
|
|
use App\Notifications\Push\Prestador\Agendamento\ClienteCancelouPush;
|
|
|
|
|
+use App\Notifications\Push\Prestador\Agendamento\PrestadorFaltouPush;
|
|
|
use App\Notifications\Push\Prestador\Agendamento\NewPushRequest;
|
|
use App\Notifications\Push\Prestador\Agendamento\NewPushRequest;
|
|
|
use App\Enums\BlockedPeriodEnum;
|
|
use App\Enums\BlockedPeriodEnum;
|
|
|
use App\Models\ProviderBlockedDay;
|
|
use App\Models\ProviderBlockedDay;
|
|
@@ -269,10 +270,23 @@ class ScheduleService
|
|
|
break;
|
|
break;
|
|
|
//tem que chamar o status cancel por causa da regra de push
|
|
//tem que chamar o status cancel por causa da regra de push
|
|
|
case 'cancelled':
|
|
case 'cancelled':
|
|
|
|
|
+
|
|
|
$notificationService = app(NotificationService::class);
|
|
$notificationService = app(NotificationService::class);
|
|
|
|
|
|
|
|
|
|
+ if ($schedule->cancelled_due_to_provider_absence) {
|
|
|
|
|
+
|
|
|
|
|
+ // Cancelamento por falta do prestador.
|
|
|
|
|
+ // Aqui enviamos a notificação específica para o prestador.
|
|
|
|
|
+
|
|
|
|
|
+ $this->sendProviderAbsencePush($schedule);
|
|
|
|
|
+
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
switch (Auth::user()?->type) {
|
|
switch (Auth::user()?->type) {
|
|
|
|
|
+
|
|
|
case UserTypeEnum::CLIENT:
|
|
case UserTypeEnum::CLIENT:
|
|
|
|
|
+
|
|
|
$user = $schedule->provider?->user;
|
|
$user = $schedule->provider?->user;
|
|
|
|
|
|
|
|
if (!$user) {
|
|
if (!$user) {
|
|
@@ -287,14 +301,18 @@ class ScheduleService
|
|
|
'type' => NotificationTypeEnum::SCHEDULE_PROVIDER_CLIENT_CANCELLED->value,
|
|
'type' => NotificationTypeEnum::SCHEDULE_PROVIDER_CLIENT_CANCELLED->value,
|
|
|
'user_id' => $user->id,
|
|
'user_id' => $user->id,
|
|
|
]);
|
|
]);
|
|
|
|
|
+
|
|
|
$this->sendClientCancelledPush($schedule);
|
|
$this->sendClientCancelledPush($schedule);
|
|
|
|
|
|
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
case UserTypeEnum::PROVIDER:
|
|
case UserTypeEnum::PROVIDER:
|
|
|
|
|
+
|
|
|
$notificationService->create([
|
|
$notificationService->create([
|
|
|
'title' => __('notifications.schedule_cancelled_title'),
|
|
'title' => __('notifications.schedule_cancelled_title'),
|
|
|
- 'description' => __('notifications.provider_cancelled_schedule_description', ['provider' => $schedule->provider->user->name]),
|
|
|
|
|
|
|
+ 'description' => __('notifications.provider_cancelled_schedule_description', [
|
|
|
|
|
+ 'provider' => $schedule->provider->user->name
|
|
|
|
|
+ ]),
|
|
|
'origin' => 'schedule',
|
|
'origin' => 'schedule',
|
|
|
'origin_id' => $schedule->id,
|
|
'origin_id' => $schedule->id,
|
|
|
'type' => NotificationTypeEnum::SCHEDULE_CLIENT_PROVIDER_CANCELLED->value,
|
|
'type' => NotificationTypeEnum::SCHEDULE_CLIENT_PROVIDER_CANCELLED->value,
|
|
@@ -648,9 +666,11 @@ class ScheduleService
|
|
|
|
|
|
|
|
//reporta por falta
|
|
//reporta por falta
|
|
|
|
|
|
|
|
- public function reportProviderAbsence(int $scheduleId): Schedule
|
|
|
|
|
- {
|
|
|
|
|
- return DB::transaction(function () use ($scheduleId) {
|
|
|
|
|
|
|
+ public function reportProviderAbsence(
|
|
|
|
|
+ int $scheduleId,
|
|
|
|
|
+ string $cancelText
|
|
|
|
|
+ ): Schedule {
|
|
|
|
|
+ return DB::transaction(function () use ($scheduleId, $cancelText) {
|
|
|
$schedule = Schedule::findOrFail($scheduleId);
|
|
$schedule = Schedule::findOrFail($scheduleId);
|
|
|
|
|
|
|
|
// O agendamento precisa ter um prestador vinculado
|
|
// O agendamento precisa ter um prestador vinculado
|
|
@@ -661,7 +681,6 @@ class ScheduleService
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// O cliente precisa ser o dono do agendamento
|
|
// O cliente precisa ser o dono do agendamento
|
|
|
-
|
|
|
|
|
if (Auth::user()->type !== UserTypeEnum::CLIENT) {
|
|
if (Auth::user()->type !== UserTypeEnum::CLIENT) {
|
|
|
throw new \Exception(
|
|
throw new \Exception(
|
|
|
__('messages.provider_absence_only_client')
|
|
__('messages.provider_absence_only_client')
|
|
@@ -682,7 +701,13 @@ class ScheduleService
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// O agendamento não pode estar encerrado/cancelado/rejeitado
|
|
// O agendamento não pode estar encerrado/cancelado/rejeitado
|
|
|
- if (in_array($schedule->status, ['cancelled', 'rejected', 'finished'], true)) {
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ in_array(
|
|
|
|
|
+ $schedule->status,
|
|
|
|
|
+ ['cancelled', 'rejected', 'finished'],
|
|
|
|
|
+ true
|
|
|
|
|
+ )
|
|
|
|
|
+ ) {
|
|
|
throw new \Exception(
|
|
throw new \Exception(
|
|
|
__('messages.provider_absence_invalid_status')
|
|
__('messages.provider_absence_invalid_status')
|
|
|
);
|
|
);
|
|
@@ -691,20 +716,24 @@ class ScheduleService
|
|
|
// Valida se o cliente pode informar a falta neste momento
|
|
// Valida se o cliente pode informar a falta neste momento
|
|
|
ScheduleBusinessRules::validateProviderAbsenceWindow($schedule);
|
|
ScheduleBusinessRules::validateProviderAbsenceWindow($schedule);
|
|
|
|
|
|
|
|
- // Motivo utilizado para o cancelamento por falta
|
|
|
|
|
- $cancelText = 'Prestador não compareceu ao serviço.';
|
|
|
|
|
-
|
|
|
|
|
- // Registra que o cancelamento ocorreu por falta do prestador
|
|
|
|
|
|
|
+ // Registra o motivo informado pelo cliente
|
|
|
$schedule->update([
|
|
$schedule->update([
|
|
|
'cancel_text' => $cancelText,
|
|
'cancel_text' => $cancelText,
|
|
|
'cancelled_by' => Auth::user()->type,
|
|
'cancelled_by' => Auth::user()->type,
|
|
|
'cancelled_due_to_provider_absence' => true,
|
|
'cancelled_due_to_provider_absence' => true,
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
- $this->updateStatus($schedule->id, 'cancelled', false, true);
|
|
|
|
|
|
|
+ // Cancela o agendamento
|
|
|
|
|
+ $this->updateStatus(
|
|
|
|
|
+ $schedule->id,
|
|
|
|
|
+ 'cancelled',
|
|
|
|
|
+ false,
|
|
|
|
|
+ true
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Aplica a penalidade de bloqueio de 3 dias úteis do prestador.
|
|
// Aplica a penalidade de bloqueio de 3 dias úteis do prestador.
|
|
|
$this->blockProviderPenaltyDays($schedule);
|
|
$this->blockProviderPenaltyDays($schedule);
|
|
|
|
|
+
|
|
|
// TODO: Implementar estorno integral do pagamento.
|
|
// TODO: Implementar estorno integral do pagamento.
|
|
|
// Esta etapa será implementada posteriormente por outro responsável.
|
|
// Esta etapa será implementada posteriormente por outro responsável.
|
|
|
|
|
|
|
@@ -717,15 +746,15 @@ class ScheduleService
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//penalidade por falta bloqueio de 3 dias validos
|
|
//penalidade por falta bloqueio de 3 dias validos
|
|
|
|
|
+ // penalidade por falta - bloqueio de 3 dias válidos
|
|
|
private function blockProviderPenaltyDays(Schedule $schedule): void
|
|
private function blockProviderPenaltyDays(Schedule $schedule): void
|
|
|
{
|
|
{
|
|
|
$providerId = $schedule->provider_id;
|
|
$providerId = $schedule->provider_id;
|
|
|
-
|
|
|
|
|
$date = Carbon::parse($schedule->date)->startOfDay();
|
|
$date = Carbon::parse($schedule->date)->startOfDay();
|
|
|
-
|
|
|
|
|
$blockedDaysCount = 0;
|
|
$blockedDaysCount = 0;
|
|
|
|
|
|
|
|
while ($blockedDaysCount < 3) {
|
|
while ($blockedDaysCount < 3) {
|
|
|
|
|
+
|
|
|
$date->addDay();
|
|
$date->addDay();
|
|
|
|
|
|
|
|
$dayOfWeek = $date->dayOfWeek;
|
|
$dayOfWeek = $date->dayOfWeek;
|
|
@@ -769,8 +798,13 @@ class ScheduleService
|
|
|
'date' => $date->format('Y-m-d'),
|
|
'date' => $date->format('Y-m-d'),
|
|
|
'period' => BlockedPeriodEnum::ALL->value,
|
|
'period' => BlockedPeriodEnum::ALL->value,
|
|
|
'reason' => 'Bloqueio de 3 dias por falta do prestador.',
|
|
'reason' => 'Bloqueio de 3 dias por falta do prestador.',
|
|
|
|
|
+ 'type' => 'auto_cancel',
|
|
|
'init_hour' => '07:00',
|
|
'init_hour' => '07:00',
|
|
|
'end_hour' => '20:00',
|
|
'end_hour' => '20:00',
|
|
|
|
|
+
|
|
|
|
|
+ // Identifica que este bloqueio é uma penalidade
|
|
|
|
|
+ // e não pode ser alterado/desbloqueado manualmente.
|
|
|
|
|
+ 'blocked_due_to_provider_absence' => true,
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
$blockedDaysCount++;
|
|
$blockedDaysCount++;
|
|
@@ -986,6 +1020,34 @@ class ScheduleService
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // cancelou por falta
|
|
|
|
|
+
|
|
|
|
|
+ private function sendProviderAbsencePush(Schedule $schedule): void
|
|
|
|
|
+ {
|
|
|
|
|
+ $user = $schedule->provider?->user;
|
|
|
|
|
+
|
|
|
|
|
+ if (! $user) {
|
|
|
|
|
+ Log::warning('Push de falta ignorada: prestador sem usuário', [
|
|
|
|
|
+ 'schedule_id' => $schedule->id,
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ app(PushNotificationService::class)->sendToUser(
|
|
|
|
|
+ $user,
|
|
|
|
|
+ new PrestadorFaltouPush()
|
|
|
|
|
+ );
|
|
|
|
|
+ } catch (\Throwable $exception) {
|
|
|
|
|
+ Log::error('Falha ao enviar push de falta do prestador', [
|
|
|
|
|
+ 'schedule_id' => $schedule->id,
|
|
|
|
|
+ 'user_id' => $user->id,
|
|
|
|
|
+ 'error' => $exception->getMessage(),
|
|
|
|
|
+ ]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function sendScheduleStartingSoonPushes(Schedule $schedule): void
|
|
public function sendScheduleStartingSoonPushes(Schedule $schedule): void
|
|
|
{
|
|
{
|
|
|
$pushNotificationService = app(PushNotificationService::class);
|
|
$pushNotificationService = app(PushNotificationService::class);
|