isMethod('POST') ? 'required' : 'sometimes'; return [ 'student_id' => "$required|exists:students,id", 'protocol' => 'sometimes|nullable|string|max:255', 'signature_date' => 'sometimes|nullable|date_format:Y-m-d', 'end_date' => 'sometimes|nullable|date_format:Y-m-d', 'class_package_unit_id' => "$required|exists:class_package_units,id", 'class_quantity' => 'sometimes|nullable|integer|min:1', 'weekday' => 'sometimes|nullable|integer|min:0|max:6', 'start_time' => 'sometimes|nullable|date_format:H:i', 'end_time' => 'sometimes|nullable|date_format:H:i', 'second_weekday' => 'sometimes|nullable|integer|min:0|max:6', 'second_start_time' => 'sometimes|nullable|date_format:H:i', 'second_end_time' => 'sometimes|nullable|date_format:H:i', 'due_day' => 'sometimes|nullable|integer|min:1|max:31', 'tax_register' => 'sometimes|nullable|numeric|min:0', 'installments' => 'sometimes|nullable|integer|min:1|max:12', 'enrollment_due_date' => 'sometimes|nullable|date_format:Y-m-d', 'package_value' => 'sometimes|nullable|numeric|min:0', 'package_installments' => 'sometimes|nullable|integer|min:1|max:13', 'package_due_date' => 'sometimes|nullable|date_format:Y-m-d', 'early_payment_discount' => 'sometimes|nullable|numeric|min:0|max:100', 'interest_rate' => 'sometimes|nullable|numeric|min:0', 'payment_method' => 'sometimes|nullable|string|in:pix,credit_card,debit_card', 'fine_cancelled' => 'sometimes|nullable|numeric|min:0|max:100', ]; } public function after(): array { return [ function (Validator $validator): void { // o cadastro e a renovacao possuem limites de periodo diferentes if ($this->isMethod('POST')) { $this->validateCreationPeriod($validator); return; } $this->validateRenewalPeriod($validator); }, ]; } private function validateCreationPeriod(Validator $validator): void { // na criacao o contrato pode durar no maximo um ano desde a assinatura if ( ! $this->filled(['signature_date', 'end_date']) || $validator->errors()->hasAny(['signature_date', 'end_date']) ) { return; } $signatureDate = CarbonImmutable::createFromFormat('!Y-m-d', $this->string('signature_date')->toString()); $endDate = CarbonImmutable::createFromFormat('!Y-m-d', $this->string('end_date')->toString()); if ($endDate->greaterThan($signatureDate->addYearNoOverflow())) { $validator->errors()->add( 'end_date', __('validation.student_contract_max_duration'), ); } } private function validateRenewalPeriod(Validator $validator): void { // a renovacao sempre considera os dados da versao atual do contrato $contract = $this->contractBeingUpdated(); if (!$contract) { return; } // a data inicial fica imutavel depois que o contrato e criado if ( $this->exists('signature_date') && !$validator->errors()->has('signature_date') && $this->input('signature_date') !== $contract->signature_date?->format('Y-m-d') ) { $validator->errors()->add( 'signature_date', __('validation.student_contract_signature_date_immutable'), ); } // sem uma nova data final valida nao existe periodo para conferir if (!$this->exists('end_date') || $validator->errors()->has('end_date')) { return; } $currentEndDate = $contract->end_date?->toImmutable(); $newEndDate = $this->filled('end_date') ? CarbonImmutable::createFromFormat('!Y-m-d', $this->string('end_date')->toString()) : null; // a data final nunca pode diminuir nem ser removida if ($currentEndDate && (!$newEndDate || $newEndDate->lessThan($currentEndDate))) { $validator->errors()->add( 'end_date', __('validation.student_contract_end_date_cannot_decrease'), ); return; } // reenviar a mesma data nao caracteriza uma renovacao if ( (!$currentEndDate && !$newEndDate) || ($currentEndDate && $newEndDate && $newEndDate->equalTo($currentEndDate)) ) { return; } // a renovacao pode avancar no maximo um ano a partir da data atual $maximumEndDate = CarbonImmutable::today()->addYearNoOverflow(); if ($newEndDate?->greaterThan($maximumEndDate)) { $validator->errors()->add( 'end_date', __('validation.student_contract_renewal_max_end_date', [ 'date' => $maximumEndDate->format('d/m/Y'), ]), ); } } protected function contractBeingUpdated(): ?StudentContract { // o id da rota identifica a versao usada como base para a edicao $contractId = $this->route('id'); return is_numeric($contractId) ? StudentContract::find((int) $contractId) : null; } }