with(['user', 'profileMedia']) ->orderBy('created_at', 'desc') ->get(); return $providers; } public function findById(int $id): ?Provider { return Provider::with(['user', 'profileMedia'])->find($id); } public function create(array $data): Provider { return DB::transaction(function () use ($data) { $provider = Provider::create($data); if (! empty($data['recipient_code'])) { $this->pagarmeRecipientService->createRecipientForProvider($provider, $data); } return $provider->fresh(['user', 'profileMedia']); }); } public function update(int $id, array $data): ?Provider { $model = $this->findById($id); if (! $model) { return null; } if (isset($data['avatar']) && $data['avatar'] instanceof UploadedFile) { $media = $this->mediaService->replaceFile( newFile: $data['avatar'], folder: "provider/avatar/{$model->id}", source: 'provider', sourceId: $model->id, old: $model->profileMedia, ); $data['profile_media_id'] = $media->id; unset($data['avatar']); } $model->update($data); return $model->fresh(['user', 'profileMedia']); } public function updateBankAccount(int $id, array $bankAccountData): ?Provider { $provider = $this->findById($id); if (! $provider) { return null; } $this->pagarmeRecipientService->updateDefaultBankAccount($provider, $bankAccountData); return $provider->fresh(['user', 'profileMedia']); } public function delete(int $id): bool { $model = $this->findById($id); if (! $model) { return false; } return $model->delete(); } public function getPending(int $page = 1, int $perPage = 10): LengthAwarePaginator { return Provider::query() ->where('approval_status', ApprovalStatusEnum::PENDING->value) ->with(['user', 'profileMedia']) ->orderBy('created_at', 'asc') ->paginate($perPage, ['*'], 'page', $page); } public function approve(int $id): Provider { return DB::transaction(function () use ($id) { $provider = Provider::findOrFail($id); $provider->update(['approval_status' => ApprovalStatusEnum::ACCEPTED->value]); return $provider->fresh(['user', 'profileMedia']); }); } public function reject(int $id): Provider { return DB::transaction(function () use ($id) { $provider = Provider::findOrFail($id); $provider->update(['approval_status' => ApprovalStatusEnum::REJECTED->value]); return $provider->fresh(['user', 'profileMedia']); }); } public function register(array $data): ?array { try { DB::beginTransaction(); $email = $data['email'] ?? null; $phone = $data['phone'] ?? null; $code = $data['code'] ?? null; $user = User::query() ->where('type', UserTypeEnum::PROVIDER->value) ->where('code', $code) ->where(function ($query) use ($email, $phone) { if (! empty($email)) { $query->orWhere('email', $email); } if (! empty($phone)) { $query->orWhere('phone', $phone); } }) ->latest('id') ->first(); if (! $user) { throw new \Exception(__('messages.user_not_found_or_code_not_validated')); } $user->name = $data['name']; if (empty($user->email) && ! empty($email)) { $user->email = $email; } if (empty($user->phone) && ! empty($phone)) { $user->phone = $phone; } $user->save(); $provider = new Provider; $provider->user_id = $user->id; $provider->rg = $data['rg'] ?? null; $provider->document = $this->sanitizeDigits($data['document'] ?? null); $provider->birth_date = $data['birth_date'] ?? null; $provider->daily_price_8h = $data['daily_price_8h'] ?? null; $provider->daily_price_6h = $data['daily_price_6h'] ?? null; $provider->daily_price_4h = $data['daily_price_4h'] ?? null; $provider->daily_price_2h = $data['daily_price_2h'] ?? null; $provider->approval_status = ApprovalStatusEnum::PENDING->value; $provider->save(); $provider->refresh(); $selfie = $this->mediaService->createFromFile( file: $data['selfie'], folder: "provider/avatar/{$provider->id}", source: 'provider', sourceId: $provider->id, ); $provider->profile_media_id = $selfie->id; $front = $this->mediaService->createFromFile( file: $data['document_front'], folder: "provider/documentos/{$provider->id}", source: 'provider_document', sourceId: $provider->id, filename: 'frente.'.$data['document_front']->getClientOriginalExtension(), ); $provider->document_front_media_id = $front->id; $back = $this->mediaService->createFromFile( file: $data['document_back'], folder: "provider/documentos/{$provider->id}", source: 'provider_document', sourceId: $provider->id, filename: 'verso.'.$data['document_back']->getClientOriginalExtension(), ); $provider->document_back_media_id = $back->id; $provider->save(); if (! empty($data['recipient_code'])) { $this->pagarmeRecipientService->createRecipientForProvider($provider, $data); } $this->createProviderAddress($provider->id, $data); $this->createProviderServicesTypes($provider->id, $data); $this->createProviderWorkingDays($provider->id, $data); if (empty($user->email) || empty($user->code)) { throw new \Exception(__('messages.user_not_found_or_code_not_validated')); } $result = $this->authService->loginWithEmail( email: $user->email, code: $user->code, ); DB::commit(); return $result; } catch (\Exception $e) { DB::rollBack(); Log::error('Error registering provider: '.$e->getMessage(), [ 'data' => $data, ]); throw $e; } } private function createProviderAddress(int $providerId, array $data): void { $state = null; $city = null; if (! empty($data['state'])) { $state = State::query() ->whereRaw('LOWER(code) = ?', [mb_strtolower($data['state'])]) ->first(); } if (! empty($data['city'])) { $cityQuery = City::query() ->whereRaw('LOWER(name) = ?', [mb_strtolower($data['city'])]); if ($state) { $cityQuery->where('state_id', $state->id); } $city = $cityQuery->first(); } $address = new Address; $address->source = 'provider'; $address->source_id = $providerId; $address->zip_code = $this->sanitizeDigits($data['zip_code'] ?? null); $address->address = $data['address'] ?? null; $address->has_complement = (bool) ($data['has_complement'] ?? false); $address->complement = $data['complement'] ?? null; $address->nickname = $data['nickname'] ?? null; $address->instructions = $data['instructions'] ?? null; $address->address_type = $data['address_type'] ?? 'home'; $address->state_id = $state?->id; $address->city_id = $city?->id; $address->save(); } private function createProviderServicesTypes(int $providerId, array $data): void { $serviceTypeIds = $data['services_types_ids'] ?? $data['service_types_ids'] ?? []; $uniqueIds = array_values(array_unique(array_map('intval', $serviceTypeIds))); foreach ($uniqueIds as $serviceTypeId) { ProviderServicesType::create([ 'provider_id' => $providerId, 'service_type_id' => $serviceTypeId, ]); } } private function createProviderWorkingDays(int $providerId, array $data): void { $workingDays = $data['working_days'] ?? []; $seen = []; foreach ($workingDays as $workingDay) { $day = (int) ($workingDay['day'] ?? -1); $period = $workingDay['period'] ?? null; if ($day < 0 || $day > 6 || ! in_array($period, ['morning', 'afternoon'], true)) { continue; } $uniqueKey = $day.'-'.$period; if (isset($seen[$uniqueKey])) { continue; } $seen[$uniqueKey] = true; ProviderWorkingDay::create([ 'provider_id' => $providerId, 'day' => $day, 'period' => $period, ]); } } private function sanitizeDigits(?string $value): ?string { if ($value === null) { return null; } $digits = preg_replace('/\D+/', '', $value); return $digits === '' ? null : $digits; } }