fix: actualizar respuestas de API para ventas con datos de facturación y ajustar seriales en inventarios

This commit is contained in:
Juan Felipe Zapata Moreno 2026-01-16 21:37:40 -06:00
parent 810aff1b0e
commit c1473cdb95
5 changed files with 40 additions and 45 deletions

View File

@ -32,7 +32,7 @@ public function show(string $invoiceNumber)
// Si ya tiene datos de facturación
if ($sale->client_id) {
return ApiResponse::INTERNAL_ERROR->response([
return ApiResponse::NO_CONTENT->response([
'message' => 'Esta venta ya tiene datos de facturación registrados',
'client' => $sale->client,
'sale' => $this->formatSaleData($sale)
@ -60,7 +60,7 @@ public function store(Request $request, string $invoiceNumber)
}
if ($sale->client_id) {
return ApiResponse::BAD_REQUEST->response([
return ApiResponse::NO_CONTENT->response([
'message' => 'Esta venta ya tiene datos de facturación registrados'
]);
}

View File

@ -130,7 +130,8 @@ public function downloadTemplate()
'stock',
'costo',
'precio_venta',
'impuesto'
'impuesto',
'numeros_serie'
];
$exampleData = [
@ -149,10 +150,11 @@ public function downloadTemplate()
'sku' => 'COCA-600',
'codigo_barras' => '750227686666',
'categoria' => 'Bebidas',
'stock' => 100,
'stock' => 5,
'costo' => 12.50,
'precio_venta' => 18.00,
'impuesto' => 8
'impuesto' => 8,
'numeros_serie' => '' // Dejar vacío si el producto no maneja seriales individuales
],
[
'nombre' => 'Laptop HP Pavilion 15',
@ -162,7 +164,8 @@ public function downloadTemplate()
'stock' => 5,
'costo' => 8500.00,
'precio_venta' => 12000.00,
'impuesto' => 16
'impuesto' => 16,
'numeros_serie' => 'HP-LAP-15-01,HP-LAP-15-02,HP-LAP-15-03,HP-LAP-15-04,HP-LAP-15-05'
],
];

View File

@ -20,9 +20,9 @@ class InventorySerialController extends Controller
/**
* Listar seriales de un producto
*/
public function index(Inventory $inventory, Request $request)
public function index(Inventory $inventario, Request $request)
{
$query = $inventory->serials();
$query = $inventario->serials();
if ($request->has('status')) {
$query->where('status', $request->status);
@ -32,22 +32,22 @@ public function index(Inventory $inventory, Request $request)
$query->where('serial_number', 'like', "%{$request->q}%");
}
$serials = $query->orderBy('created_at', 'desc')
$serials = $query->orderBy('serial_number', 'ASC')
->paginate(config('app.pagination'));
return ApiResponse::OK->response([
'serials' => $serials,
'inventory' => $inventory->load('category'),
'inventory' => $inventario->load('category'),
]);
}
/**
* Mostrar un serial específico
*/
public function show(Inventory $inventory, InventorySerial $serial)
public function show(Inventory $inventario, InventorySerial $serial)
{
// Verificar que el serial pertenece al inventario
if ($serial->inventory_id !== $inventory->id) {
if ($serial->inventory_id !== $inventario->id) {
return ApiResponse::NOT_FOUND->response([
'message' => 'Serial no encontrado para este inventario'
]);
@ -55,14 +55,14 @@ public function show(Inventory $inventory, InventorySerial $serial)
return ApiResponse::OK->response([
'serial' => $serial->load('saleDetail'),
'inventory' => $inventory->load('category'),
'inventory' => $inventario->load('category'),
]);
}
/**
* Crear un nuevo serial
*/
public function store(Inventory $inventory, Request $request)
public function store(Inventory $inventario, Request $request)
{
$request->validate([
'serial_number' => ['required', 'string', 'unique:inventory_serials,serial_number'],
@ -70,28 +70,28 @@ public function store(Inventory $inventory, Request $request)
]);
$serial = InventorySerial::create([
'inventory_id' => $inventory->id,
'inventory_id' => $inventario->id,
'serial_number' => $request->serial_number,
'status' => 'disponible',
'notes' => $request->notes,
]);
// Sincronizar stock
$inventory->syncStock();
$inventario->syncStock();
return ApiResponse::CREATED->response([
'serial' => $serial,
'inventory' => $inventory->fresh(),
'inventory' => $inventario->fresh(),
]);
}
/**
* Actualizar un serial
*/
public function update(Inventory $inventory, InventorySerial $serial, Request $request)
public function update(Inventory $inventario , InventorySerial $serial, Request $request)
{
// Verificar que el serial pertenece al inventario
if ($serial->inventory_id !== $inventory->id) {
if ($serial->inventory_id !== $inventario->id) {
return ApiResponse::NOT_FOUND->response([
'message' => 'Serial no encontrado para este inventario'
]);
@ -99,28 +99,28 @@ public function update(Inventory $inventory, InventorySerial $serial, Request $r
$request->validate([
'serial_number' => ['sometimes', 'string', 'unique:inventory_serials,serial_number,' . $serial->id],
'status' => ['sometimes', 'in:disponible,vendido,dañado,reservado'],
'status' => ['sometimes', 'in:disponible,vendido'],
'notes' => ['nullable', 'string'],
]);
$serial->update($request->only(['serial_number', 'status', 'notes']));
// Sincronizar stock del inventario
$inventory->syncStock();
$inventario->syncStock();
return ApiResponse::OK->response([
'serial' => $serial->fresh(),
'inventory' => $inventory->fresh(),
'inventory' => $inventario->fresh(),
]);
}
/**
* Eliminar un serial
*/
public function destroy(Inventory $inventory, InventorySerial $serial)
public function destroy(Inventory $inventario, InventorySerial $serial)
{
// Verificar que el serial pertenece al inventario
if ($serial->inventory_id !== $inventory->id) {
if ($serial->inventory_id !== $inventario->id) {
return ApiResponse::NOT_FOUND->response([
'message' => 'Serial no encontrado para este inventario'
]);
@ -129,18 +129,18 @@ public function destroy(Inventory $inventory, InventorySerial $serial)
$serial->delete();
// Sincronizar stock
$inventory->syncStock();
$inventario->syncStock();
return ApiResponse::OK->response([
'message' => 'Serial eliminado exitosamente',
'inventory' => $inventory->fresh(),
'inventory' => $inventario->fresh(),
]);
}
/**
* Importar múltiples seriales
*/
public function bulkStore(Inventory $inventory, Request $request)
public function bulkStore(Inventory $inventario, Request $request)
{
$request->validate([
'serial_numbers' => ['required', 'array', 'min:1'],
@ -151,7 +151,7 @@ public function bulkStore(Inventory $inventory, Request $request)
foreach ($request->serial_numbers as $serialNumber) {
$serial = InventorySerial::create([
'inventory_id' => $inventory->id,
'inventory_id' => $inventario->id,
'serial_number' => $serialNumber,
'status' => 'disponible',
]);
@ -160,12 +160,12 @@ public function bulkStore(Inventory $inventory, Request $request)
}
// Sincronizar stock
$inventory->syncStock();
$inventario->syncStock();
return ApiResponse::CREATED->response([
'serials' => $created,
'count' => count($created),
'inventory' => $inventory->fresh(),
'inventory' => $inventario->fresh(),
]);
}
}

View File

@ -49,7 +49,7 @@ public function map($row): array
'costo' => $row['costo'] ?? null,
'precio_venta' => $row['precio_venta'] ?? null,
'impuesto' => $row['impuesto'] ?? null,
'numeros_serie' => $row['numeros_serie'] ?? null, // Nueva columna: separados por comas
'numeros_serie' => $row['numeros_serie'] ?? null,
];
}
@ -117,22 +117,15 @@ public function model(array $row)
]);
}
}
// Sincronizar stock basado en los seriales
$inventory->syncStock();
} else {
// Si no se proporcionan seriales, generar automáticamente
$stockQuantity = (int) $row['stock'];
for ($i = 1; $i <= $stockQuantity; $i++) {
InventorySerial::create([
'inventory_id' => $inventory->id,
'serial_number' => $inventory->sku . '-' . str_pad($i, 4, '0', STR_PAD_LEFT),
'status' => 'disponible',
]);
}
// 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();
}
// Sincronizar stock
$inventory->syncStock();
$this->imported++;
return $inventory;

View File

@ -19,7 +19,6 @@ public function up(): void
$table->integer('quantity');
$table->decimal('unit_price', 10, 2);
$table->decimal('subtotal', 10, 2);
$table->json('serial_numbers')->nullable();
$table->timestamps();
});
}