feat: implement multi-tenant cart system with stock reservation and inventory tracking

This commit is contained in:
2026-07-01 16:21:53 -03:00
parent 230ea57ce0
commit 6a0b08c9d7
8 changed files with 144 additions and 18 deletions

View File

@@ -10,8 +10,12 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Casts\Attribute;
#[Fillable([
'producto_id',
'stock_real',
'stock_reservado',
'stock',
'is_placeholder',
])]
@@ -21,11 +25,87 @@ class ProductVariant extends Model
protected $table = 'productos_variantes';
protected $appends = ['stock_tecnico'];
protected static function booted(): void
{
static::saving(function (ProductVariant $variant) {
$variant->validateStock();
});
}
public function validateStock(): void
{
if ($this->stock_real < 0) {
throw new \InvalidArgumentException('El stock real no puede ser negativo.');
}
if ($this->stock_reservado < 0) {
throw new \InvalidArgumentException('El stock reservado no puede ser negativo.');
}
if ($this->stock_reservado > $this->stock_real) {
throw new \InvalidArgumentException('El stock reservado no puede ser mayor que el stock real.');
}
}
public function incrementRealStock(int $amount): void
{
if ($amount < 0) {
throw new \InvalidArgumentException('El monto a incrementar debe ser positivo.');
}
$this->stock_real += $amount;
$this->save();
}
public function decrementRealStock(int $amount): void
{
if ($amount < 0) {
throw new \InvalidArgumentException('El monto a decrementar debe ser positivo.');
}
$this->stock_real -= $amount;
$this->save();
}
public function incrementReservedStock(int $amount): void
{
if ($amount < 0) {
throw new \InvalidArgumentException('El monto a incrementar debe ser positivo.');
}
$this->stock_reservado += $amount;
$this->save();
}
public function decrementReservedStock(int $amount): void
{
if ($amount < 0) {
throw new \InvalidArgumentException('El monto a decrementar debe ser positivo.');
}
$this->stock_reservado -= $amount;
$this->save();
}
protected function stockTecnico(): Attribute
{
return Attribute::get(fn () => $this->stock_real - $this->stock_reservado);
}
protected function stock(): Attribute
{
return Attribute::make(
get: fn () => $this->stock_real,
set: fn ($value) => [
'stock_real' => $value,
]
);
}
protected function casts(): array
{
return [
'producto_id' => 'integer',
'stock' => 'integer',
'stock_real' => 'integer',
'stock_reservado' => 'integer',
'is_placeholder' => 'boolean',
];
}