route('id'); $rules = [ 'document' => [ 'sometimes', 'string', 'regex:/^[0-9]{11}$|^[0-9]{14}$/', function ($attribute, $value, $fail) use ($providerId) { if (!$this->isValidCpfCnpj($value)) { $fail(__('validation.custom.document.invalid')); } }, Rule::unique('providers', 'document') ->ignore($providerId) ->whereNull('deleted_at'), ], 'rg' => 'sometimes|nullable|string|max:20', 'user_id' => [ 'sometimes', 'exists:users,id', Rule::unique('providers', 'user_id') ->ignore($providerId) ->whereNull('deleted_at'), function ($attribute, $value, $fail) { // Verifica se o user já está vinculado a um client if (\DB::table('clients')->where('user_id', $value)->whereNull('deleted_at')->exists()) { $fail(__('validation.custom.user_id.already_linked_to_client')); } }, ], 'average_rating' => 'sometimes|nullable|numeric|min:0|max:5', 'total_services' => 'sometimes|integer|min:0', 'birth_date' => 'sometimes|nullable|date|before:today', 'selfie_verified' => 'sometimes|boolean', 'document_verified' => 'sometimes|boolean', 'is_approved' => 'sometimes|boolean', 'daily_price_8h' => 'sometimes|nullable|numeric|min:100|max:500', 'daily_price_6h' => 'sometimes|nullable|numeric|min:100|max:500', 'daily_price_4h' => 'sometimes|nullable|numeric|min:100|max:500', 'daily_price_2h' => 'sometimes|nullable|numeric|min:100|max:500', 'profile_media_id' => 'sometimes|nullable|exists:media,id', ]; if ($this->isMethod('post')) { $rules['document'] = [ 'required', 'string', 'regex:/^[0-9]{11}$|^[0-9]{14}$/', function ($attribute, $value, $fail) { if (!$this->isValidCpfCnpj($value)) { $fail(__('validation.custom.document.invalid')); } }, Rule::unique('providers', 'document')->whereNull('deleted_at'), ]; $rules['user_id'] = [ 'required', 'exists:users,id', Rule::unique('providers', 'user_id')->whereNull('deleted_at'), function ($attribute, $value, $fail) { // Verifica se o user já está vinculado a um client if (\DB::table('clients')->where('user_id', $value)->whereNull('deleted_at')->exists()) { $fail(__('validation.custom.user_id.already_linked_to_client')); } }, ]; } return $rules; } /** * Valida CPF ou CNPJ */ private function isValidCpfCnpj(string $value): bool { $value = preg_replace('/[^0-9]/', '', $value); if (strlen($value) === 11) { return $this->isValidCpf($value); } elseif (strlen($value) === 14) { return $this->isValidCnpj($value); } return false; } /** * Valida CPF */ private function isValidCpf(string $cpf): bool { // Elimina CPFs inválidos conhecidos if (preg_match('/(\d)\1{10}/', $cpf)) { return false; } // Valida primeiro dígito verificador for ($t = 9; $t < 11; $t++) { for ($d = 0, $c = 0; $c < $t; $c++) { $d += $cpf[$c] * (($t + 1) - $c); } $d = ((10 * $d) % 11) % 10; if ($cpf[$c] != $d) { return false; } } return true; } /** * Valida CNPJ */ private function isValidCnpj(string $cnpj): bool { // Elimina CNPJs inválidos conhecidos if (preg_match('/(\d)\1{13}/', $cnpj)) { return false; } // Valida primeiro dígito verificador $length = strlen($cnpj) - 2; $numbers = substr($cnpj, 0, $length); $digits = substr($cnpj, $length); $sum = 0; $pos = $length - 7; for ($i = $length; $i >= 1; $i--) { $sum += $numbers[$length - $i] * $pos--; if ($pos < 2) { $pos = 9; } } $result = $sum % 11 < 2 ? 0 : 11 - $sum % 11; if ($result != $digits[0]) { return false; } // Valida segundo dígito verificador $length = $length + 1; $numbers = substr($cnpj, 0, $length); $sum = 0; $pos = $length - 7; for ($i = $length; $i >= 1; $i--) { $sum += $numbers[$length - $i] * $pos--; if ($pos < 2) { $pos = 9; } } $result = $sum % 11 < 2 ? 0 : 11 - $sum % 11; if ($result != $digits[1]) { return false; } return true; } }