New-Thanasoft/thanasoft-back/app/Http/Requests/StoreInvoiceRequest.php
nyavokevin 8f7019e815 feat(invoice): support group-based invoices without a client
Allow invoices to target either a client or a client group by making
`client_id` nullable and validating that exactly one recipient is set.

Load group relations in invoice data so the frontend can display group
details in invoice views and type definitions.

Make quote acceptance reuse an existing invoice instead of creating a
duplicate, and surface backend status update errors in the quote UI.
2026-04-02 16:08:44 +03:00

100 lines
4.4 KiB
PHP

<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreInvoiceRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'client_id' => 'nullable|exists:clients,id',
'group_id' => 'nullable|exists:client_groups,id',
'source_quote_id' => 'nullable|exists:quotes,id',
'status' => 'required|in:brouillon,emise,envoyee,partiellement_payee,payee,echue,annulee,avoir',
'invoice_date' => 'required|date',
'due_date' => 'nullable|date|after_or_equal:invoice_date',
'currency' => 'required|string|size:3',
'total_ht' => 'required|numeric|min:0',
'total_tva' => 'required|numeric|min:0',
'total_ttc' => 'required|numeric|min:0',
'e_invoicing_channel_id' => 'nullable|exists:e_invoicing_channels,id',
'e_invoice_status' => 'nullable|in:cree,transmis,accepte,refuse,en_litige,acquitte,archive',
'lines' => 'required|array|min:1',
'lines.*.product_id' => 'nullable|exists:products,id',
'lines.*.packaging_id' => 'nullable|exists:product_packagings,id',
'lines.*.packages_qty' => 'nullable|numeric|min:0',
'lines.*.units_qty' => 'nullable|numeric|min:0',
'lines.*.description' => 'required|string',
'lines.*.qty_base' => 'nullable|numeric|min:0',
'lines.*.unit_price' => 'required|numeric|min:0',
'lines.*.unit_price_per_package' => 'nullable|numeric|min:0',
'lines.*.tva_rate_id' => 'nullable|exists:tva_rates,id',
'lines.*.discount_pct' => 'required|numeric|min:0|max:100',
'lines.*.total_ht' => 'required|numeric|min:0',
];
}
public function withValidator($validator): void
{
$validator->after(function ($validator) {
$hasClient = filled($this->input('client_id'));
$hasGroup = filled($this->input('group_id'));
if (! $hasClient && ! $hasGroup) {
$message = 'Un client ou un groupe de clients est obligatoire.';
$validator->errors()->add('client_id', $message);
$validator->errors()->add('group_id', $message);
}
if ($hasClient && $hasGroup) {
$message = 'Selectionnez soit un client, soit un groupe de clients.';
$validator->errors()->add('client_id', $message);
$validator->errors()->add('group_id', $message);
}
});
}
public function messages(): array
{
return [
'client_id.exists' => 'Le client sélectionné est invalide.',
'group_id.exists' => 'Le groupe sélectionné est invalide.',
'status.required' => 'Le statut est obligatoire.',
'status.in' => 'Le statut sélectionné est invalide.',
'invoice_date.required' => 'La date de la facture est obligatoire.',
'invoice_date.date' => 'La date de la facture n\'est pas valide.',
'due_date.date' => 'La date d\'échéance n\'est pas valide.',
'due_date.after_or_equal' => 'La date d\'échéance doit être postérieure ou égale à la date de la facture.',
'currency.required' => 'La devise est obligatoire.',
'currency.size' => 'La devise doit comporter 3 caractères.',
'total_ht.required' => 'Le total HT est obligatoire.',
'total_ht.numeric' => 'Le total HT doit être un nombre.',
'total_ht.min' => 'Le total HT ne peut pas être négatif.',
'total_tva.required' => 'Le total TVA est obligatoire.',
'total_tva.numeric' => 'Le total TVA doit être un nombre.',
'total_tva.min' => 'Le total TVA ne peut pas être négatif.',
'total_ttc.required' => 'Le total TTC est obligatoire.',
'total_ttc.numeric' => 'Le total TTC doit être un nombre.',
'total_ttc.min' => 'Le total TTC ne peut pas être négatif.',
'lines.required' => 'Veuillez ajouter au moins une ligne à la facture.',
];
}
}