223 lines
15 KiB
PHP
223 lines
15 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Requests;
|
|
|
|
use App\Models\Contract;
|
|
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->filled('code') && $this->filled('supply_type')) {
|
|
$contractId = $this->route('id');
|
|
$existingContract = Contract::query()
|
|
->with('client:id,name')
|
|
->where('code', $this->input('code'))
|
|
->where('supply_type', $this->input('supply_type'))
|
|
->when($contractId, fn ($query) => $query->where('id', '!=', $contractId))
|
|
->first();
|
|
|
|
if ($existingContract && ! $this->boolean('confirm_duplicate')) {
|
|
$supplyType = strtoupper($this->input('supply_type'));
|
|
$clientName = $existingContract->client?->name;
|
|
$message = "Já existe um contrato {$supplyType} com este código";
|
|
|
|
if ($clientName) {
|
|
$message .= " associado ao cliente {$clientName}";
|
|
}
|
|
|
|
$validator->errors()->add(
|
|
'duplicate_code',
|
|
$message . '. Confirme apenas se se trata de uma mudança de titularidade.'
|
|
);
|
|
}
|
|
}
|
|
|
|
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.'),
|
|
];
|
|
}
|
|
}
|