| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <?php
- namespace App\Services;
- use App\Enums\AppointmentStatusEnum;
- use App\Enums\NotificationRecipientEnum;
- use App\Models\Appointment;
- use Carbon\Carbon;
- use Illuminate\Database\Eloquent\Collection;
- use Illuminate\Pagination\LengthAwarePaginator;
- use Illuminate\Support\Str;
- class AppointmentService
- {
- public function __construct(protected NotificationService $notificationService) {}
- public function getAll(): Collection
- {
- return Appointment::with(['user', 'partnerAgreement', 'partnerAgreementService'])
- ->orderBy('date', 'desc')
- ->get();
- }
- public function getAllByUser(int $userId): Collection
- {
- return Appointment::with(['partnerAgreement', 'partnerAgreementService'])
- ->where('user_id', $userId)
- ->orderBy('date', 'desc')
- ->get();
- }
- public function getAllByPartnerUser(int $userId): Collection
- {
- return Appointment::with(['user', 'partnerAgreement', 'partnerAgreementService'])
- ->whereHas('partnerAgreement', fn($q) => $q->where('user_id', $userId))
- ->orderBy('date', 'desc')
- ->get();
- }
- public function findById(int $id): ?Appointment
- {
- return Appointment::with(['user', 'partnerAgreement', 'partnerAgreementService'])->find($id);
- }
- public function create(array $data): Appointment
- {
- $data['order_number'] = $this->generateOrderNumber();
- $data['requested_at'] = now();
- return Appointment::create($data);
- }
- public function notifyCreation(Appointment $model): void
- {
- $dateStr = $model->date ? Carbon::parse($model->date)->format('d/m/Y') : null;
- $message = $dateStr
- ? "Um agendamento #{$model->order_number} foi criado para você" . ($model->time ? " para {$dateStr} às {$model->time}" : " em {$dateStr}") . "."
- : "Um agendamento #{$model->order_number} foi criado para você.";
- $this->notificationService->createAutoForUser([
- 'title' => 'Novo agendamento',
- 'message' => $message,
- 'recipient' => NotificationRecipientEnum::ASSOCIADO,
- 'source' => 'appointment',
- 'source_id' => $model->id,
- ], $model->user_id);
- }
- public function update(int $id, array $data): ?Appointment
- {
- $model = Appointment::find($id);
- if (!$model) {
- return null;
- }
- $model->update($data);
- return $model->fresh(['user', 'partnerAgreement', 'partnerAgreementService']);
- }
- public function delete(int $id): bool
- {
- $model = Appointment::find($id);
- if (!$model) {
- return false;
- }
- return $model->delete();
- }
- public function getAdminCounters(): array
- {
- return [
- 'pendentes' => Appointment::where('status', AppointmentStatusEnum::PENDENTE)->count(),
- 'aprovados' => Appointment::where('status', AppointmentStatusEnum::CONFIRMADO)->count(),
- 'recusados' => Appointment::where('status', AppointmentStatusEnum::RECUSADO)->count(),
- ];
- }
- public function getAllPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
- {
- $query = Appointment::with(['user', 'partnerAgreement', 'partnerAgreementService'])
- ->orderBy('requested_at', 'desc');
- if (!empty($filters['status'])) {
- $query->where('status', $filters['status']);
- }
- if (!empty($filters['search'])) {
- $term = '%' . mb_strtolower($filters['search']) . '%';
- $query->where(function ($q) use ($term) {
- $q->whereHas('user', function ($uq) use ($term) {
- $uq->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]);
- })->orWhereHas('partnerAgreement', function ($pq) use ($term) {
- $pq->whereRaw('UNACCENT(LOWER(COALESCE(trade_name, company_name))) LIKE UNACCENT(?)', [$term]);
- })->orWhereHas('partnerAgreementService', function ($sq) use ($term) {
- $sq->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]);
- })->orWhereRaw('UNACCENT(LOWER(order_number)) LIKE UNACCENT(?)', [$term]);
- });
- }
- return $query->paginate($perPage);
- }
- public function approve(int $id, string $date, string $time): ?Appointment
- {
- $model = Appointment::find($id);
- if (!$model) return null;
- $model->update([
- 'status' => AppointmentStatusEnum::CONFIRMADO,
- 'date' => $date,
- 'time' => $time,
- ]);
- $this->notificationService->createAutoForUser([
- 'title' => 'Agendamento confirmado',
- 'message' => "Seu agendamento #{$model->order_number} foi confirmado para " . Carbon::parse($date)->format('d/m/Y') . " às {$time}.",
- 'recipient' => NotificationRecipientEnum::ASSOCIADO,
- 'source' => 'appointment',
- 'source_id' => $model->id,
- ], $model->user_id);
- return $model->fresh(['user', 'partnerAgreement', 'partnerAgreementService']);
- }
- public function reject(int $id): ?Appointment
- {
- $model = Appointment::find($id);
- if (!$model) return null;
- $model->update(['status' => AppointmentStatusEnum::RECUSADO]);
- $this->notificationService->createAutoForUser([
- 'title' => 'Agendamento recusado',
- 'message' => "Seu agendamento #{$model->order_number} foi recusado.",
- 'recipient' => NotificationRecipientEnum::ASSOCIADO,
- 'source' => 'appointment',
- 'source_id' => $model->id,
- ], $model->user_id);
- return $model->fresh(['user', 'partnerAgreement', 'partnerAgreementService']);
- }
- public function approveByPartner(int $id, int $userId, string $date, string $time): ?Appointment
- {
- $model = Appointment::whereHas('partnerAgreement', fn($q) => $q->where('user_id', $userId))->find($id);
- if (!$model) return null;
- $model->update([
- 'status' => AppointmentStatusEnum::CONFIRMADO,
- 'date' => $date,
- 'time' => $time,
- ]);
- $this->notificationService->createAutoForUser([
- 'title' => 'Agendamento confirmado',
- 'message' => "Seu agendamento #{$model->order_number} foi confirmado para " . Carbon::parse($date)->format('d/m/Y') . " às {$time}.",
- 'recipient' => NotificationRecipientEnum::ASSOCIADO,
- 'source' => 'appointment',
- 'source_id' => $model->id,
- ], $model->user_id);
- return $model->fresh(['user', 'partnerAgreement', 'partnerAgreementService']);
- }
- public function rejectByPartner(int $id, int $userId): ?Appointment
- {
- $model = Appointment::whereHas('partnerAgreement', fn($q) => $q->where('user_id', $userId))->find($id);
- if (!$model) return null;
- $model->update(['status' => AppointmentStatusEnum::RECUSADO]);
- $this->notificationService->createAutoForUser([
- 'title' => 'Agendamento recusado',
- 'message' => "Seu agendamento #{$model->order_number} foi recusado.",
- 'recipient' => NotificationRecipientEnum::ASSOCIADO,
- 'source' => 'appointment',
- 'source_id' => $model->id,
- ], $model->user_id);
- return $model->fresh(['user', 'partnerAgreement', 'partnerAgreementService']);
- }
- private function generateOrderNumber(): string
- {
- do {
- $number = 'AGD-' . strtoupper(Str::random(8));
- } while (Appointment::where('order_number', $number)->exists());
- return $number;
- }
- }
|