pdv.backend/app/Services/WarehouseService.php
2026-02-05 17:01:19 -06:00

116 lines
3.6 KiB
PHP

<?php namespace App\Services;
use App\Models\Warehouse;
use Illuminate\Support\Facades\DB;
/**
* Servicio para gestión de almacenes
*/
class WarehouseService
{
/**
* Obtener almacén principal
*/
public function getMainWarehouse(): ?Warehouse
{
return Warehouse::main()->first();
}
/**
* Crear nuevo almacén
*/
public function createWarehouse(array $data): Warehouse
{
return DB::transaction(function () use ($data) {
// Si se marca como principal, desactivar otros principales
if ($data['is_main'] ?? false) {
Warehouse::where('is_main', true)->update(['is_main' => false]);
}
// Si no hay almacenes principales, este debe serlo
if (!Warehouse::main()->exists()) {
$data['is_main'] = true;
}
return Warehouse::create($data);
});
}
/**
* Actualizar almacén
*/
public function updateWarehouse(Warehouse $warehouse, array $data): Warehouse
{
return DB::transaction(function () use ($warehouse, $data) {
// Si se marca como principal, desactivar otros principales
if (isset($data['is_main']) && $data['is_main']) {
Warehouse::where('id', '!=', $warehouse->id)
->where('is_main', true)
->update(['is_main' => false]);
}
// No permitir desactivar el último almacén principal
if (isset($data['is_main']) && !$data['is_main'] && $warehouse->is_main) {
if (Warehouse::main()->count() === 1) {
throw new \Exception('No se puede desactivar el único almacén principal. Asigna otro almacén como principal primero.');
}
}
$warehouse->update($data);
return $warehouse->fresh();
});
}
/**
* Activar/Desactivar almacén
*/
public function toggleActive(Warehouse $warehouse): Warehouse
{
// No permitir desactivar el almacén principal
if ($warehouse->is_main && $warehouse->is_active) {
throw new \Exception('No se puede desactivar el almacén principal.');
}
$warehouse->update(['is_active' => !$warehouse->is_active]);
return $warehouse->fresh();
}
/**
* Obtener stock de un almacén
*/
public function getWarehouseStock(Warehouse $warehouse)
{
return $warehouse->inventories()
->with(['category', 'price'])
->select('inventories.*')
->get()
->map(function ($inventory) use ($warehouse) {
$pivot = $inventory->warehouses()
->where('warehouse_id', $warehouse->id)
->first();
return [
'inventory_id' => $inventory->id,
'name' => $inventory->name,
'sku' => $inventory->sku,
'category' => $inventory->category?->name,
'stock' => $pivot?->pivot->stock ?? 0,
'min_stock' => $pivot?->pivot->min_stock,
'max_stock' => $pivot?->pivot->max_stock,
'cost' => $inventory->price?->cost,
'retail_price' => $inventory->price?->retail_price,
];
});
}
/**
* Validar que existe almacén principal
*/
public function ensureMainWarehouse(): void
{
if (!Warehouse::main()->exists()) {
throw new \Exception('No existe un almacén principal configurado.');
}
}
}