Files
voltcerto/app/Http/Requests/ContractRequest.php
Luis Medon e488ae3342 Add feature tests, unit tests, and configuration for Laravel application
- Created ExampleTest and RoutesTest for basic application response and route testing.
- Implemented IsolatedDatabaseTestCase for isolated database testing.
- Added unit tests for various models and services including Contract, CPE, and LeadDetail.
- Developed request validation tests for CreateClientRequest, UpdateClientRequest, and ContractRequest.
- Introduced Vite configuration for asset management in the Laravel application.
2026-10-29 11:30:06 +00:00

197 lines
14 KiB
PHP

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
use Carbon\Carbon;
class ContractRequest extends FormRequest
{
protected function localizedMessage(string $key, string $fallback): string
{
if (function_exists('app') && app()->bound('translator')) {
return __($key, [], app()->getLocale()) ?: $fallback;
}
return $fallback;
}
public function authorize(): bool
{
return true;
}
protected function prepareForValidation(): void
{
foreach (['validity', 'contract_end_date', 'contract_date', 'activation_date', 'chargeback_date', 'payment_date', 'renewal_date'] as $field) {
$value = $this->input($field);
if ($value) {
try {
$date = str_contains((string) $value, '/')
? Carbon::createFromFormat('d/m/Y', $value)
: Carbon::parse($value);
$this->merge([$field => $date->format('Y-m-d')]);
} catch (\Throwable) {
// Mantém o valor original para o validador apresentar a mensagem adequada.
}
}
}
if ($this->filled('chargeback_value')) {
$this->merge(['chargeback' => true]);
}
}
public function rules(): array
{
$rules = [
'client_id' => ['required', 'exists:clients,id'],
'contract_value' => ['nullable', 'numeric', 'min:0'],
'commission_value' => ['nullable', 'numeric',],
'profit_value' => ['nullable', 'numeric'],
'seller_id' => ['nullable', 'exists:users,id'],
'supply_type' => ['required', 'in:cpe,cui'],
'supply_address' => ['nullable', 'string', 'max:255'],
'annual_consumption' => ['nullable', 'numeric', 'min:0'],
'code' => ['required', 'string', 'max:255'],
'contract_type_id' => ['required', 'exists:contract_types,id'],
'validity' => ['nullable', 'date'],
'contract_end_date' => ['nullable', 'date'],
'contract_date' => ['nullable', 'date'],
'activation_date' => ['nullable', 'date'],
'status_id' => ['required', 'exists:contract_status,id'],
'commission_rate' => ['nullable', 'numeric', 'between:0,100'],
'notes' => ['nullable', 'string'],
'power_tier_id' => ['nullable', 'exists:power_tiers,id'],
'payment_method_id' => ['required', 'exists:payment_methods,id'],
'delivery_method' => ['required', 'in:correio,email'],
'delivery_email' => ['nullable', 'email', 'max:255'],
'previous_supplier_id' => ['nullable', 'exists:suppliers,id'],
'new_supplier_id' => ['nullable', 'exists:suppliers,id'],
'typology_id' => ['nullable', 'exists:typologies,id'],
'cui_tier_id' => ['nullable', 'exists:cui_tiers,id'],
'go_ki' => ['required', 'numeric'],
'paid' => ['nullable', 'boolean'],
'chargeback' => ['nullable', 'boolean'],
'chargeback_value' => ['required_if:chargeback,1', 'nullable', 'numeric', 'max:-0.01'],
'chargeback_date' => ['required_if:chargeback,1', 'nullable', 'date'],
// Parcelas
'installments.*.due_date' => ['nullable', 'date'],
'installments.*.amount' => ['nullable', 'numeric', 'min:0'],
'installments.*.paid' => ['nullable', 'boolean'],
];
if (! $this->user()?->can('view_contract_summary')) {
foreach (['contract_value', 'commission_value', 'profit_value', 'paid', 'chargeback', 'chargeback_value', 'chargeback_date', 'installments.*.due_date', 'installments.*.amount', 'installments.*.paid'] as $field) {
unset($rules[$field]);
}
}
return $rules;
}
public function withValidator(Validator $validator)
{
$validator->after(function ($validator) {
if (! $this->user()?->can('view_contract_summary')) {
return;
}
$installments = $this->input('installments', []);
$validity = $this->input('validity');
$previousDate = null;
foreach ($installments as $index => $installment) {
if (!empty($installment['due_date'])) {
$dueDate = Carbon::parse($installment['due_date']);
// Data da parcela não pode ser superior à validade do contrato
// if (!empty($validity)) {
// $validityDate = Carbon::createFromFormat('d/m/Y', $validity);
// if ($dueDate->gt($validityDate)) {
// $validator->errors()->add(
// "installments.$index.due_date",
// "A data da parcela $index não pode ser superior à data de renovação do contrato."
// );
// }
// }
// Data da parcela deve ser superior à anterior
if ($previousDate && $dueDate->lte($previousDate)) {
$validator->errors()->add(
"installments.$index.due_date",
"A data da parcela $index deve ser superior à parcela anterior."
);
}
$previousDate = $dueDate;
}
}
});
}
public function messages(): array
{
return [
'cui_tier_id.exists' => $this->localizedMessage('validation.custom.cui_tier_id.exists', 'O escalão CUI selecionado não é válido.'),
'client_id.required' => $this->localizedMessage('validation.custom.client_id.required', 'O cliente é obrigatório.'),
'client_id.exists' => $this->localizedMessage('validation.custom.client_id.exists', 'O cliente selecionado não é válido.'),
'contract_value.numeric' => $this->localizedMessage('validation.custom.contract_value.numeric', 'O valor do contrato deve ser um número.'),
'contract_value.min' => $this->localizedMessage('validation.custom.contract_value.min', 'O valor do contrato não pode ser negativo.'),
'go_ki.required' => $this->localizedMessage('validation.custom.go_ki.required', 'O campo GO/KI é obrigatório.'),
'go_ki.numeric' => $this->localizedMessage('validation.custom.go_ki.numeric', 'O campo GO/KI deve ser numérico.'),
'commission_value.numeric' => $this->localizedMessage('validation.custom.commission_value.numeric', 'O valor da comissão deve ser um número.'),
'profit_value.numeric' => $this->localizedMessage('validation.custom.profit_value.numeric', 'O lucro deve ser um número.'),
'seller_id.exists' => $this->localizedMessage('validation.custom.seller_id.exists', 'O vendedor selecionado não é válido.'),
'supply_type.required' => $this->localizedMessage('validation.custom.supply_type.required', 'O tipo de fornecimento é obrigatório.'),
'supply_type.in' => $this->localizedMessage('validation.custom.supply_type.in', 'O tipo de fornecimento deve ser CPE ou cui.'),
'supply_address.string' => $this->localizedMessage('validation.custom.supply_address.string', 'O endereço de fornecimento deve ser texto.'),
'supply_address.max' => $this->localizedMessage('validation.custom.supply_address.max', 'O endereço de fornecimento não pode exceder 255 caracteres.'),
'annual_consumption.numeric' => $this->localizedMessage('validation.custom.annual_consumption.numeric', 'O consumo anual deve ser numérico.'),
'annual_consumption.min' => $this->localizedMessage('validation.custom.annual_consumption.min', 'O consumo anual não pode ser negativo.'),
'contract_type_id.required' => $this->localizedMessage('validation.custom.contract_type_id.required', 'O tipo de contrato é obrigatório.'),
'contract_type_id.exists' => $this->localizedMessage('validation.custom.contract_type_id.exists', 'O tipo de contrato selecionado não é válido.'),
'validity.date' => $this->localizedMessage('validation.custom.validity.date', 'A validade deve ser uma data válida.'),
'validity.date_format' => $this->localizedMessage('validation.custom.validity.date_format', 'A validade deve estar no formato DD/MM/AAAA.'),
'contract_end_date.date' => $this->localizedMessage('validation.custom.contract_end_date.date', 'A data de fim do contrato deve ser válida.'),
'contract_end_date.date_format' => $this->localizedMessage('validation.custom.contract_end_date.date_format', 'A data de fim de contrato deve estar no formato DD/MM/AAAA.'),
'contract_date.date' => $this->localizedMessage('validation.custom.contract_date.date', 'A data do contrato deve ser válida.'),
'contract_date.date_format' => $this->localizedMessage('validation.custom.contract_date.date_format', 'A data do contrato deve estar no formato DD/MM/AAAA.'),
'activation_date.date' => $this->localizedMessage('validation.custom.activation_date.date', 'A data de ativação deve ser válida.'),
'activation_date.date_format' => $this->localizedMessage('validation.custom.activation_date.date_format', 'A data de ativação deve estar no formato DD/MM/AAAA.'),
'status_id.required' => $this->localizedMessage('validation.custom.status_id.required', 'O estado do contrato é obrigatório.'),
'status_id.exists' => $this->localizedMessage('validation.custom.status_id.exists', 'O estado do contrato selecionado não é válido.'),
'commission_rate.numeric' => $this->localizedMessage('validation.custom.commission_rate.numeric', 'A percentagem da comissão deve ser um número.'),
'commission_rate.between' => $this->localizedMessage('validation.custom.commission_rate.between', 'A percentagem da comissão deve estar entre 0 e 100.'),
'notes.string' => $this->localizedMessage('validation.custom.notes.string', 'As notas devem ser texto.'),
'power_tier_id.exists' => $this->localizedMessage('validation.custom.power_tier_id.exists', 'O escalão de potência selecionado não é válido.'),
'payment_method_id.required' => $this->localizedMessage('validation.custom.payment_method_id.required', 'O método de pagamento é obrigatório.'),
'payment_method_id.exists' => $this->localizedMessage('validation.custom.payment_method_id.exists', 'O método de pagamento selecionado não é válido.'),
'delivery_method.required' => $this->localizedMessage('validation.custom.delivery_method.required', 'O método de envio é obrigatório.'),
'delivery_method.in' => $this->localizedMessage('validation.custom.delivery_method.in', 'O método de envio deve ser "correio" ou "email".'),
'delivery_email.email' => $this->localizedMessage('validation.custom.delivery_email.email', 'O e-mail de envio deve ser válido.'),
'delivery_email.max' => $this->localizedMessage('validation.custom.delivery_email.max', 'O e-mail de envio não pode exceder 255 caracteres.'),
'previous_supplier_id.exists' => $this->localizedMessage('validation.custom.previous_supplier_id.exists', 'O fornecedor anterior selecionado não é válido.'),
'new_supplier_id.exists' => $this->localizedMessage('validation.custom.new_supplier_id.exists', 'O novo fornecedor selecionado não é válido.'),
'paid.required' => $this->localizedMessage('validation.custom.paid.required', 'O campo "Pago" é obrigatório.'),
'paid.boolean' => $this->localizedMessage('validation.custom.paid.boolean', 'O campo "Pago" deve ser verdadeiro ou falso.'),
'chargeback.boolean' => $this->localizedMessage('validation.custom.chargeback.boolean', 'O campo "Chargeback" deve ser verdadeiro ou falso.'),
'chargeback_value.required_if' => $this->localizedMessage('validation.custom.chargeback_value.required_if', 'O valor do chargeback é obrigatório.'),
'chargeback_value.numeric' => $this->localizedMessage('validation.custom.chargeback_value.numeric', 'O valor do chargeback deve ser numérico.'),
'chargeback_value.max' => $this->localizedMessage('validation.custom.chargeback_value.max', 'O valor do chargeback deve ser negativo.'),
'chargeback_date.required_if' => $this->localizedMessage('validation.custom.chargeback_date.required_if', 'A data de chargeback é obrigatória.'),
'chargeback_date.date' => $this->localizedMessage('validation.custom.chargeback_date.date', 'A data de chargeback deve ser uma data válida.'),
'chargeback_date.date_format' => $this->localizedMessage('validation.custom.chargeback_date.date_format', 'A data de chargeback deve estar no formato DD/MM/AAAA.'),
'installments.*.due_date.required_with' => $this->localizedMessage('validation.custom.installments_due_date.required_with', 'A data da parcela é obrigatória quando o valor está preenchido.'),
'installments.*.due_date.date' => $this->localizedMessage('validation.custom.installments_due_date.date', 'A data da parcela deve ser uma data válida.'),
'installments.*.due_date.date_format' => $this->localizedMessage('validation.custom.installments_due_date.date_format', 'A data da parcela deve estar no formato DD/MM/AAAA.'),
'installments.*.amount.required_with' => $this->localizedMessage('validation.custom.installments_amount.required_with', 'O valor da parcela é obrigatório quando a data está preenchida.'),
'installments.*.amount.numeric' => $this->localizedMessage('validation.custom.installments_amount.numeric', 'O valor da parcela deve ser numérico.'),
'installments.*.amount.min' => $this->localizedMessage('validation.custom.installments_amount.min', 'O valor da parcela não pode ser negativo.'),
];
}
}