orderBy('created_at', 'desc') ->get(); } public function findById(int $id): ?ServicePackageItem { return ServicePackageItem::find($id); } public function create(array $data): ServicePackageItem { return DB::transaction(function () use ($data) { [$servicePackage, $schedule] = $this->validateItem(data_get($data, 'service_package_id'), data_get($data, 'schedule_id')); if (! $servicePackage->provider_id) { $servicePackage->update(['provider_id' => $schedule->provider_id]); } return ServicePackageItem::create($data); }); } public function update(int $id, array $data): ?ServicePackageItem { return DB::transaction(function () use ($id, $data): ?ServicePackageItem { $model = $this->findById($id); if (! $model) { return null; } $servicePackageId = data_get($data, 'service_package_id', $model->service_package_id); $scheduleId = data_get($data, 'schedule_id', $model->schedule_id); [$servicePackage, $schedule] = $this->validateItem($servicePackageId, $scheduleId); if (! $servicePackage->provider_id) { $servicePackage->update(['provider_id' => $schedule->provider_id]); } $model->update($data); return $model->fresh(); }); } public function delete(int $id): bool { $model = $this->findById($id); if (!$model) { return false; } return DB::transaction(function () use ($model): bool { $this->validateItem($model->service_package_id, $model->schedule_id); return $model->delete(); }); } private function validateItem(int $servicePackageId, int $scheduleId): array { $servicePackage = ServicePackage::query()->lockForUpdate()->findOrFail($servicePackageId); $schedule = Schedule::query()->findOrFail($scheduleId); if ($servicePackage->status !== ServicePackageStatusEnum::OPEN) { throw ValidationException::withMessages([ 'service_package_id' => 'Somente pacotes abertos podem ser alterados.', ]); } if ($schedule->client_id !== $servicePackage->client_id) { throw ValidationException::withMessages([ 'schedule_id' => 'O agendamento precisa pertencer ao mesmo cliente do pacote.', ]); } if (! $schedule->provider_id || ($servicePackage->provider_id && $schedule->provider_id !== $servicePackage->provider_id)) { throw ValidationException::withMessages([ 'schedule_id' => __('messages.service_package_same_provider'), ]); } $belongsToAnotherPackage = ServicePackageItem::query() ->where('schedule_id', $scheduleId) ->where('service_package_id', '!=', $servicePackageId) ->exists(); if ($belongsToAnotherPackage) { throw ValidationException::withMessages([ 'schedule_id' => 'O agendamento já pertence a outro pacote.', ]); } $hasActivePayment = Payment::query() ->where('schedule_id', $scheduleId) ->whereIn('status', [ PaymentStatusEnum::PENDING->value, PaymentStatusEnum::PROCESSING->value, PaymentStatusEnum::AUTHORIZED->value, PaymentStatusEnum::PAID->value, ]) ->exists(); if ($hasActivePayment) { throw ValidationException::withMessages([ 'schedule_id' => 'O agendamento já possui um pagamento e não pode ser adicionado ao pacote.', ]); } return [$servicePackage, $schedule]; } }