108 lines
2.6 KiB
PHP
108 lines
2.6 KiB
PHP
<?php namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class Bundle extends Model
|
|
{
|
|
use SoftDeletes;
|
|
|
|
protected $fillable = [
|
|
'name',
|
|
'sku',
|
|
'barcode',
|
|
];
|
|
|
|
protected $appends = ['available_stock', 'total_cost'];
|
|
|
|
/**
|
|
* Componentes del kit (items individuales)
|
|
*/
|
|
public function items()
|
|
{
|
|
return $this->hasMany(BundleItem::class);
|
|
}
|
|
|
|
/**
|
|
* Productos que componen el kit (relación many-to-many)
|
|
*/
|
|
public function inventories()
|
|
{
|
|
return $this->belongsToMany(Inventory::class, 'bundle_items')
|
|
->withPivot('quantity')
|
|
->withTimestamps();
|
|
}
|
|
|
|
/**
|
|
* Precio del kit
|
|
*/
|
|
public function price()
|
|
{
|
|
return $this->hasOne(BundlePrice::class);
|
|
}
|
|
|
|
/**
|
|
* Stock disponible del kit en el almacén principal (único para venta)
|
|
* = mínimo(stock_almacén_principal_componente / cantidad_requerida)
|
|
*/
|
|
public function getAvailableStockAttribute(): int
|
|
{
|
|
$mainWarehouseId = Warehouse::where('is_main', true)->value('id');
|
|
|
|
if (! $mainWarehouseId) {
|
|
return 0;
|
|
}
|
|
|
|
return $this->stockInWarehouse($mainWarehouseId);
|
|
}
|
|
|
|
/**
|
|
* Stock disponible en un almacén específico
|
|
*/
|
|
public function stockInWarehouse(int $warehouseId): int
|
|
{
|
|
if ($this->items->isEmpty()) {
|
|
return 0;
|
|
}
|
|
|
|
$minStock = PHP_INT_MAX;
|
|
|
|
foreach ($this->items as $item) {
|
|
$inventory = $item->inventory;
|
|
$warehouseStock = $inventory->stockInWarehouse($warehouseId);
|
|
|
|
$possibleKits = $warehouseStock > 0 ? floor($warehouseStock / $item->quantity) : 0;
|
|
$minStock = min($minStock, $possibleKits);
|
|
}
|
|
|
|
return $minStock === PHP_INT_MAX ? 0 : (int) $minStock;
|
|
}
|
|
|
|
/**
|
|
* Costo total del kit (suma de costos de componentes)
|
|
*/
|
|
public function getTotalCostAttribute(): float
|
|
{
|
|
$total = 0;
|
|
|
|
foreach ($this->items as $item) {
|
|
$componentCost = $item->inventory->price->cost ?? 0;
|
|
$total += $componentCost * $item->quantity;
|
|
}
|
|
|
|
return round($total, 2);
|
|
}
|
|
|
|
/**
|
|
* Validar si el kit tiene stock disponible
|
|
*/
|
|
public function hasStock(int $quantity = 1, ?int $warehouseId = null): bool
|
|
{
|
|
if ($warehouseId) {
|
|
return $this->stockInWarehouse($warehouseId) >= $quantity;
|
|
}
|
|
|
|
return $this->available_stock >= $quantity;
|
|
}
|
|
}
|