route('order'); return $order instanceof PurchaseOrder && ($this->user()?->can('create', [GoodsReceipt::class, $order]) ?? false); } /** @return array */ 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 */ 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.', ]; } }