- Implementa CRUD de unidades y soporte para decimales en inventario. - Integra servicios de WhatsApp para envío de documentos y auth. - Ajusta validación de series y permisos (RoleSeeder).
128 lines
5.9 KiB
PHP
128 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Requests\App;
|
|
|
|
use App\Models\Inventory;
|
|
use Illuminate\Foundation\Http\FormRequest;
|
|
|
|
class InventoryEntryRequest extends FormRequest
|
|
{
|
|
public function authorize(): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function rules(): array
|
|
{
|
|
if ($this->has('products')) {
|
|
return [
|
|
'warehouse_id' => 'required|exists:warehouses,id',
|
|
'invoice_reference' => 'required|string|max:255',
|
|
'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.*.unit_cost' => 'required|numeric|min:0',
|
|
'products.*.serial_numbers' => 'nullable|array',
|
|
'products.*.serial_numbers.*' => 'required|string|distinct|unique:inventory_serials,serial_number',
|
|
];
|
|
}
|
|
|
|
return [
|
|
'inventory_id' => 'required|exists:inventories,id',
|
|
'warehouse_id' => 'required|exists:warehouses,id',
|
|
'quantity' => 'required|numeric|min:0.001',
|
|
'unit_cost' => 'required|numeric|min:0',
|
|
'invoice_reference' => 'required|string|max:255',
|
|
'notes' => 'nullable|string|max:1000',
|
|
'serial_numbers' => 'nullable|array',
|
|
'serial_numbers.*' => 'required|string|distinct|unique:inventory_serials,serial_number',
|
|
];
|
|
}
|
|
|
|
public function messages(): array
|
|
{
|
|
return [
|
|
// Mensajes para entrada ú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.*.distinct' => 'Los números de serie no pueden repetirse',
|
|
'serial_numbers.*.unique' => 'El número de serie ya existe en el sistema',
|
|
|
|
// Mensajes para entrada 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.*.unit_cost.required' => 'El costo unitario es requerido',
|
|
'products.*.unit_cost.numeric' => 'El costo unitario debe ser un número',
|
|
'products.*.unit_cost.min' => 'El costo unitario no puede ser negativo',
|
|
'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.*.distinct' => 'Los números de serie no pueden repetirse',
|
|
'products.*.serial_numbers.*.unique' => 'El número de serie ya 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',
|
|
'unit_cost.required' => 'El costo unitario es requerido',
|
|
'invoice_reference.required' => 'La referencia de la factura es requerida',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Validaciones adicionales de negocio
|
|
*/
|
|
public function withValidator($validator)
|
|
{
|
|
$validator->after(function ($validator) {
|
|
// Extraer productos del request (entrada simple o múltiple)
|
|
$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;
|
|
}
|
|
|
|
// VALIDACIÓN 1: Cantidades decimales solo con unidades que permiten decimales
|
|
$quantity = $product['quantity'];
|
|
$isDecimal = floor($quantity) != $quantity;
|
|
|
|
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."
|
|
);
|
|
}
|
|
|
|
// VALIDACIÓN 2: No permitir seriales con unidades decimales
|
|
$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'."
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|