fix: permisos de usuario
This commit is contained in:
parent
eaad8a57df
commit
2c8189ca59
@ -90,6 +90,7 @@ public function import(InventoryImportRequest $request)
|
||||
return ApiResponse::OK->response([
|
||||
'message' => 'Importación completada exitosamente.',
|
||||
'imported' => $stats['imported'],
|
||||
'updated' => $stats['updated'],
|
||||
'skipped' => $stats['skipped'],
|
||||
'errors' => $stats['errors'],
|
||||
]);
|
||||
|
||||
@ -44,13 +44,15 @@ public function messages(): array
|
||||
|
||||
/**
|
||||
* Reglas de validación para cada fila del Excel
|
||||
* Nota: SKU y código de barras no tienen 'unique' porque se permite reimportar
|
||||
* para agregar stock/seriales a productos existentes
|
||||
*/
|
||||
public static function rowRules(): array
|
||||
{
|
||||
return [
|
||||
'nombre' => ['required', 'string', 'max:100'],
|
||||
'sku' => ['nullable', 'string', 'max:50', 'unique:inventories,sku'],
|
||||
'codigo_barras' => ['nullable', 'string', 'max:100', 'unique:inventories,barcode'],
|
||||
'sku' => ['nullable', 'string', 'max:50'],
|
||||
'codigo_barras' => ['nullable', 'string', 'max:100'],
|
||||
'categoria' => ['nullable', 'string', 'max:100'],
|
||||
'stock' => ['required', 'integer', 'min:0'],
|
||||
'costo' => ['required', 'numeric', 'min:0'],
|
||||
@ -67,9 +69,7 @@ public static function rowMessages(): array
|
||||
return [
|
||||
'nombre.required' => 'El nombre del producto es requerido.',
|
||||
'nombre.max' => 'El nombre no debe exceder los 100 caracteres.',
|
||||
'sku.unique' => 'El SKU ya existe en el sistema.',
|
||||
'sku.max' => 'El SKU no debe exceder los 50 caracteres.',
|
||||
'codigo_barras.unique' => 'El código de barras ya existe en el sistema.',
|
||||
'stock.required' => 'El stock es requerido.',
|
||||
'stock.integer' => 'El stock debe ser un número entero.',
|
||||
'stock.min' => 'El stock no puede ser negativo.',
|
||||
|
||||
@ -33,6 +33,7 @@ class ProductsImport implements ToModel, WithHeadingRow, WithValidation, WithChu
|
||||
|
||||
private $errors = [];
|
||||
private $imported = 0;
|
||||
private $updated = 0;
|
||||
private $skipped = 0;
|
||||
|
||||
/**
|
||||
@ -64,7 +65,21 @@ public function model(array $row)
|
||||
}
|
||||
|
||||
try {
|
||||
// Validar que el precio de venta sea mayor que el costo
|
||||
// Buscar producto existente por SKU o código de barras
|
||||
$existingInventory = null;
|
||||
if (!empty($row['sku'])) {
|
||||
$existingInventory = Inventory::where('sku', trim($row['sku']))->first();
|
||||
}
|
||||
if (!$existingInventory && !empty($row['codigo_barras'])) {
|
||||
$existingInventory = Inventory::where('barcode', trim($row['codigo_barras']))->first();
|
||||
}
|
||||
|
||||
// Si el producto ya existe, solo agregar stock y seriales
|
||||
if ($existingInventory) {
|
||||
return $this->updateExistingProduct($existingInventory, $row);
|
||||
}
|
||||
|
||||
// Producto nuevo: validar precios
|
||||
$costo = (float) $row['costo'];
|
||||
$precioVenta = (float) $row['precio_venta'];
|
||||
|
||||
@ -90,7 +105,7 @@ public function model(array $row)
|
||||
$inventory->sku = !empty($row['sku']) ? trim($row['sku']) : null;
|
||||
$inventory->barcode = !empty($row['codigo_barras']) ? trim($row['codigo_barras']) : null;
|
||||
$inventory->category_id = $categoryId;
|
||||
$inventory->stock = 0; // Se calculará automáticamente
|
||||
$inventory->stock = 0;
|
||||
$inventory->is_active = true;
|
||||
$inventory->save();
|
||||
|
||||
@ -103,28 +118,7 @@ public function model(array $row)
|
||||
]);
|
||||
|
||||
// Crear números de serie si se proporcionan
|
||||
if (!empty($row['numeros_serie'])) {
|
||||
$serials = explode(',', $row['numeros_serie']);
|
||||
|
||||
foreach ($serials as $serial) {
|
||||
$serial = trim($serial);
|
||||
|
||||
if (!empty($serial)) {
|
||||
InventorySerial::create([
|
||||
'inventory_id' => $inventory->id,
|
||||
'serial_number' => $serial,
|
||||
'status' => 'disponible',
|
||||
]);
|
||||
}
|
||||
}
|
||||
// Sincronizar stock basado en los seriales
|
||||
$inventory->syncStock();
|
||||
} else {
|
||||
// Si no se proporcionan seriales, es un producto no serializado.
|
||||
// Asignar el stock directamente desde la columna 'stock'.
|
||||
$inventory->stock = (int) ($row['stock'] ?? 0);
|
||||
$inventory->save();
|
||||
}
|
||||
$this->addSerials($inventory, $row['numeros_serie'] ?? null, $row['stock'] ?? 0);
|
||||
|
||||
$this->imported++;
|
||||
|
||||
@ -136,6 +130,80 @@ public function model(array $row)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza un producto existente: suma stock y agrega seriales nuevos
|
||||
*/
|
||||
private function updateExistingProduct(Inventory $inventory, array $row)
|
||||
{
|
||||
$serialsAdded = 0;
|
||||
$serialsSkipped = 0;
|
||||
|
||||
// Agregar seriales nuevos (ignorar duplicados)
|
||||
if (!empty($row['numeros_serie'])) {
|
||||
$serials = explode(',', $row['numeros_serie']);
|
||||
|
||||
foreach ($serials as $serial) {
|
||||
$serial = trim($serial);
|
||||
if (empty($serial)) continue;
|
||||
|
||||
// Verificar si el serial ya existe (global, no solo en este producto)
|
||||
$exists = InventorySerial::where('serial_number', $serial)->exists();
|
||||
|
||||
if (!$exists) {
|
||||
InventorySerial::create([
|
||||
'inventory_id' => $inventory->id,
|
||||
'serial_number' => $serial,
|
||||
'status' => 'disponible',
|
||||
]);
|
||||
$serialsAdded++;
|
||||
} else {
|
||||
$serialsSkipped++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sincronizar stock basado en seriales disponibles
|
||||
$inventory->syncStock();
|
||||
} else {
|
||||
// Producto sin seriales: sumar stock
|
||||
$stockToAdd = (int) ($row['stock'] ?? 0);
|
||||
$inventory->increment('stock', $stockToAdd);
|
||||
}
|
||||
|
||||
$this->updated++;
|
||||
|
||||
if ($serialsSkipped > 0) {
|
||||
$this->errors[] = "Producto '{$inventory->name}': {$serialsSkipped} seriales ya existían y fueron ignorados";
|
||||
}
|
||||
|
||||
return null; // No retornar modelo para evitar que Maatwebsite intente guardarlo
|
||||
}
|
||||
|
||||
/**
|
||||
* Agrega seriales a un producto nuevo
|
||||
*/
|
||||
private function addSerials(Inventory $inventory, ?string $serialsString, int $stockFromExcel)
|
||||
{
|
||||
if (!empty($serialsString)) {
|
||||
$serials = explode(',', $serialsString);
|
||||
|
||||
foreach ($serials as $serial) {
|
||||
$serial = trim($serial);
|
||||
if (!empty($serial)) {
|
||||
InventorySerial::create([
|
||||
'inventory_id' => $inventory->id,
|
||||
'serial_number' => $serial,
|
||||
'status' => 'disponible',
|
||||
]);
|
||||
}
|
||||
}
|
||||
$inventory->syncStock();
|
||||
} else {
|
||||
// Producto sin seriales
|
||||
$inventory->stock = $stockFromExcel;
|
||||
$inventory->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reglas de validación para cada fila
|
||||
*/
|
||||
@ -167,6 +235,7 @@ public function getStats(): array
|
||||
{
|
||||
return [
|
||||
'imported' => $this->imported,
|
||||
'updated' => $this->updated,
|
||||
'skipped' => $this->skipped,
|
||||
'errors' => $this->errors,
|
||||
];
|
||||
|
||||
@ -166,6 +166,7 @@ public function run(): void
|
||||
$salesCreate,
|
||||
$salesCancel,
|
||||
$inventoryIndex,
|
||||
$inventoryImport,
|
||||
$inventoryCreate,
|
||||
$inventoryEdit,
|
||||
$inventoryDestroy,
|
||||
@ -190,8 +191,11 @@ public function run(): void
|
||||
$salesIndex, // Ver historial de ventas
|
||||
$salesCreate, // Crear ventas
|
||||
// Inventario (solo lectura)
|
||||
$inventoryIndex, // Listar productos
|
||||
$inventoryIndex,
|
||||
$inventoryImport, // Importar productos
|
||||
$inventoryCreate,
|
||||
$inventoryEdit,
|
||||
$inventoryDestroy,
|
||||
// Clientes
|
||||
$clientIndex, // Buscar clientes
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user