fix: agregar conteo de seriales en inventarios y ajustar carga de seriales en ventas

This commit is contained in:
Juan Felipe Zapata Moreno 2026-01-19 11:55:38 -06:00
parent c1473cdb95
commit eaad8a57df
5 changed files with 12 additions and 39 deletions

View File

@ -23,7 +23,7 @@ public function __construct(
public function index(Request $request) public function index(Request $request)
{ {
$products = Inventory::with(['category', 'price']) $products = Inventory::with(['category', 'price'])->withCount('serials')
->where('is_active', true); ->where('is_active', true);
@ -46,7 +46,7 @@ public function index(Request $request)
public function show(Inventory $inventario) public function show(Inventory $inventario)
{ {
return ApiResponse::OK->response([ return ApiResponse::OK->response([
'model' => $inventario->load(['category', 'price']) 'model' => $inventario->load(['category', 'price'])->loadCount('serials')
]); ]);
} }

View File

@ -32,7 +32,7 @@ public function index(Inventory $inventario, Request $request)
$query->where('serial_number', 'like', "%{$request->q}%"); $query->where('serial_number', 'like', "%{$request->q}%");
} }
$serials = $query->orderBy('serial_number', 'ASC') $serials = $query->orderBy('serial_number', 'ASC')->with('saleDetail.sale')
->paginate(config('app.pagination')); ->paginate(config('app.pagination'));
return ApiResponse::OK->response([ return ApiResponse::OK->response([
@ -136,36 +136,4 @@ public function destroy(Inventory $inventario, InventorySerial $serial)
'inventory' => $inventario->fresh(), 'inventory' => $inventario->fresh(),
]); ]);
} }
/**
* Importar múltiples seriales
*/
public function bulkStore(Inventory $inventario, Request $request)
{
$request->validate([
'serial_numbers' => ['required', 'array', 'min:1'],
'serial_numbers.*' => ['required', 'string', 'unique:inventory_serials,serial_number'],
]);
$created = [];
foreach ($request->serial_numbers as $serialNumber) {
$serial = InventorySerial::create([
'inventory_id' => $inventario->id,
'serial_number' => $serialNumber,
'status' => 'disponible',
]);
$created[] = $serial;
}
// Sincronizar stock
$inventario->syncStock();
return ApiResponse::CREATED->response([
'serials' => $created,
'count' => count($created),
'inventory' => $inventario->fresh(),
]);
}
} }

View File

@ -17,7 +17,7 @@ public function __construct(
public function index(Request $request) public function index(Request $request)
{ {
$sales = Sale::with(['details.inventory', 'user', 'client']) $sales = Sale::with(['details.inventory', 'details.serials', 'user', 'client'])
->orderBy('created_at', 'desc'); ->orderBy('created_at', 'desc');
if ($request->has('q') && $request->q) { if ($request->has('q') && $request->q) {

View File

@ -28,6 +28,8 @@ class Inventory extends Model
'is_active' => 'boolean', 'is_active' => 'boolean',
]; ];
protected $appends = ['has_serials'];
public function category() public function category()
{ {
return $this->belongsTo(Category::class); return $this->belongsTo(Category::class);
@ -67,4 +69,9 @@ public function syncStock(): void
{ {
$this->update(['stock' => $this->getAvailableStockAttribute()]); $this->update(['stock' => $this->getAvailableStockAttribute()]);
} }
public function getHasSerialsAttribute(): bool
{
return isset($this->attributes['serials_count']) && $this->attributes['serials_count'] > 0;
}
} }

View File

@ -35,9 +35,7 @@
Route::get('inventario/template/download', [InventoryController::class, 'downloadTemplate']); Route::get('inventario/template/download', [InventoryController::class, 'downloadTemplate']);
// Números de serie // Números de serie
Route::resource('inventario.serials', InventorySerialController::class) Route::resource('inventario.serials', InventorySerialController::class);
->except(['create', 'edit']);
Route::post('inventario/{inventario}/serials/bulk', [InventorySerialController::class, 'bulkStore']);
//CATEGORIAS //CATEGORIAS
Route::resource('categorias', CategoryController::class); Route::resource('categorias', CategoryController::class);