Files
compras/app/Http/Requests/ConfirmReceiptRequest.php
2026-11-02 08:08:05 +02:00

59 lines
3.2 KiB
PHP

<?php
namespace App\Http\Requests;
use App\Models\GoodsReceipt;
use App\Models\PurchaseOrder;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class ConfirmReceiptRequest extends FormRequest
{
public function authorize(): bool
{
$order = $this->route('order');
return $order instanceof PurchaseOrder && ($this->user()?->can('create', [GoodsReceipt::class, $order]) ?? false);
}
/** @return array<string, mixed> */
public function rules(): array
{
return [
'idempotency_key' => 'required|uuid', 'delivery_note' => 'required|string|max:100',
'received_on' => 'required|date_format:Y-m-d|before_or_equal:today',
'warehouse_id' => ['nullable', 'integer', Rule::exists('warehouses', 'id')->where('tenant_id', $this->user()?->tenant_id)],
'items' => 'required|array|min:1|max:100', 'items.*.purchase_order_item_id' => 'required|integer|distinct',
'items.*.received_quantity' => ['required', 'string', 'numeric', 'gt:0', 'max:1000000', 'regex:/^\d+(\.\d{1,3})?$/'],
'items.*.accepted_quantity' => ['required', 'string', 'numeric', 'min:0', 'max:1000000', 'regex:/^\d+(\.\d{1,3})?$/'],
'items.*.quality_status' => ['required', Rule::in(['compliant', 'reservations', 'nonconforming'])],
'items.*.notes' => 'nullable|string|max:3000',
'items.*.lots' => 'sometimes|array|max:100',
'items.*.lots.*.code' => 'nullable|string|max:100',
'items.*.lots.*.expires_on' => 'nullable|date_format:Y-m-d',
'items.*.lots.*.no_expiry' => 'sometimes|boolean',
'items.*.lots.*.quantity' => ['nullable', 'string', 'regex:/^\d{1,9}(\.\d{1,3})?$/'],
'items.*.stock_item_id' => ['nullable', 'integer', Rule::exists('stock_items', 'id')->where('tenant_id', $this->user()?->tenant_id)],
'tenant_id' => 'prohibited', 'received_by' => 'prohibited', 'status' => 'prohibited', 'snapshot' => 'prohibited',
];
}
/** @return array<string, string> */
public function messages(): array
{
return [
'delivery_note.required' => 'Indique a guia de remessa do fornecedor.',
'received_on.before_or_equal' => 'A recepção não pode ser registada numa data futura.',
'items.required' => 'Seleccione pelo menos uma linha para conferir.',
'items.min' => 'Seleccione pelo menos uma linha para conferir.',
'items.*.received_quantity.regex' => 'Use quantidades com até três casas decimais.',
'items.*.accepted_quantity.regex' => 'Use quantidades com até três casas decimais.',
'items.*.received_quantity.string' => 'Envie a quantidade recebida como texto decimal para manter a precisão.',
'items.*.accepted_quantity.string' => 'Envie a quantidade aceite como texto decimal para manter a precisão.',
'warehouse_id.exists' => 'Seleccione um armazém da sua empresa.',
'items.*.stock_item_id.exists' => 'Seleccione um artigo de stock da sua empresa.',
'idempotency_key.uuid' => 'A chave de confirmação é inválida. Reabra o formulário.',
];
}
}