pdv.backend/app/Http/Requests/App/InventoryExitRequest.php

119 lines
5.2 KiB
PHP

<?php
namespace App\Http\Requests\App;
use App\Models\Inventory;
use Illuminate\Foundation\Http\FormRequest;
class InventoryExitRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
// Si tiene "products" array, es salida múltiple
if ($this->has('products')) {
return [
'warehouse_id' => 'required|exists:warehouses,id',
'notes' => 'nullable|string|max:1000',
// Validación del array de productos
'products' => 'required|array|min:1',
'products.*.inventory_id' => 'required|exists:inventories,id',
'products.*.quantity' => 'required|numeric|min:0.001',
'products.*.serial_numbers' => 'nullable|array',
'products.*.serial_numbers.*' => 'required|string|exists:inventory_serials,serial_number',
'products.*.unit_of_measure_id' => 'nullable|exists:units_of_measurement,id',
];
}
// Salida única (formato original)
return [
'inventory_id' => 'required|exists:inventories,id',
'warehouse_id' => 'required|exists:warehouses,id',
'quantity' => 'required|numeric|min:0.001',
'notes' => 'nullable|string|max:1000',
'serial_numbers' => 'nullable|array',
'serial_numbers.*' => 'required|string|exists:inventory_serials,serial_number',
'unit_of_measure_id' => 'nullable|exists:units_of_measurement,id',
];
}
public function messages(): array
{
return [
// Mensajes para salida única
'inventory_id.required' => 'El producto es requerido',
'inventory_id.exists' => 'El producto no existe',
'serial_numbers.array' => 'Los números de serie deben ser un arreglo',
'serial_numbers.*.required' => 'El número de serie no puede estar vacío',
'serial_numbers.*.string' => 'El número de serie debe ser texto',
'serial_numbers.*.exists' => 'El número de serie no existe en el sistema',
// Mensajes para salida múltiple
'products.required' => 'Debe incluir al menos un producto',
'products.*.inventory_id.required' => 'El producto es requerido',
'products.*.inventory_id.exists' => 'El producto no existe',
'products.*.quantity.required' => 'La cantidad es requerida',
'products.*.quantity.min' => 'La cantidad debe ser al menos 1',
'products.*.serial_numbers.array' => 'Los números de serie deben ser un arreglo',
'products.*.serial_numbers.*.required' => 'El número de serie no puede estar vacío',
'products.*.serial_numbers.*.string' => 'El número de serie debe ser texto',
'products.*.serial_numbers.*.exists' => 'El número de serie no existe en el sistema',
// Mensajes comunes
'warehouse_id.required' => 'El almacén es requerido',
'warehouse_id.exists' => 'El almacén no existe',
'quantity.required' => 'La cantidad es requerida',
'quantity.min' => 'La cantidad debe ser al menos 1',
];
}
/**
* Validación adicional: cantidades decimales solo con unidades que permiten decimales
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
$products = $this->has('products') ? $this->products : [[
'inventory_id' => $this->inventory_id,
'quantity' => $this->quantity,
'serial_numbers' => $this->serial_numbers ?? null,
]];
foreach ($products as $index => $product) {
$inventory = Inventory::with('unitOfMeasure')->find($product['inventory_id']);
if (! $inventory || ! $inventory->unitOfMeasure) {
continue;
}
$quantity = $product['quantity'];
$isDecimal = floor($quantity) != $quantity;
// Si la cantidad es decimal pero la unidad no permite decimales
if ($isDecimal && ! $inventory->unitOfMeasure->allows_decimals) {
$field = $this->has('products') ? "products.{$index}.quantity" : 'quantity';
$validator->errors()->add(
$field,
"El producto '{$inventory->name}' usa la unidad '{$inventory->unitOfMeasure->name}' que no permite cantidades decimales. Use cantidades enteras."
);
}
$serialNumbers = $product['serial_numbers'] ?? null;
if (! empty($serialNumbers) && $inventory->unitOfMeasure->allows_decimals) {
$field = $this->has('products') ? "products.{$index}.serial_numbers" : 'serial_numbers';
$validator->errors()->add(
$field,
"No se pueden registrar números de serie para el producto '{$inventory->name}' porque usa la unidad '{$inventory->unitOfMeasure->name}' que permite cantidades decimales. Los seriales solo son válidos para unidades discretas como 'Pieza'."
);
}
}
});
}
}