Files
pos_heidiver/app/Models/InventarioPrendaDistribucion.php
T
2026-01-19 21:16:51 -05:00

289 lines
13 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class InventarioPrendaDistribucion extends Model
{
use HasFactory;
protected $table = 'inventario_prenda_distribuciones';
protected $fillable = [
'inventario_prenda_id',
'bodega_id',
'color_id',
'size_id',
'cantidad',
];
public function inventarioPrenda()
{
return $this->belongsTo(InventarioPrenda::class);
}
public function bodega()
{
return $this->belongsTo(Bodega::class);
}
public function color()
{
return $this->belongsTo(Color::class);
}
public function size()
{
return $this->belongsTo(Size::class);
}
protected static function booted()
{
// Validaciones: impedir que la suma de distribuciones supere la cantidad terminada
static::creating(function ($dist) {
$parentId = $dist->inventario_prenda_id ?? null;
if (! $parentId) return;
$parent = \App\Models\InventarioPrenda::find($parentId);
if (! $parent) return;
$cantidad = intval($dist->cantidad ?? 0);
$sumExistentes = (int) self::where('inventario_prenda_id', $parentId)->sum('cantidad');
// Validar contra la cantidad disponible actual
if (($sumExistentes + $cantidad) > (int) $parent->cantidad_disponible) {
throw \Illuminate\Validation\ValidationException::withMessages([
'cantidad' => 'No se puede añadir más prendas que las disponibles.',
]);
}
});
static::updating(function ($dist) {
$parentId = $dist->inventario_prenda_id ?? null;
if (! $parentId) return;
$parent = \App\Models\InventarioPrenda::find($parentId);
if (! $parent) return;
$newCantidad = intval($dist->cantidad ?? 0);
$othersSum = (int) self::where('inventario_prenda_id', $parentId)
->where('id', '<>', $dist->id)
->sum('cantidad');
// Validar contra la cantidad disponible actual (considerando otras distribuciones)
if (($othersSum + $newCantidad) > (int) $parent->cantidad_disponible) {
throw \Illuminate\Validation\ValidationException::withMessages([
'cantidad' => 'No se puede añadir más prendas que las disponibles.',
]);
}
});
// Al crear una distribución, incrementar stock
static::created(function ($dist) {
$cantidad = $dist->cantidad ?? 0;
if ($cantidad <= 0) return;
$bodegaId = $dist->bodega_id;
if ($dist->color_id && $dist->size_id) {
// Variante
// Determinar producto: preferir inventario.prenda.producto_id -> op.producto_id
$productoId = $dist->inventarioPrenda->producto_id ?? ($dist->inventarioPrenda->ordenProduccion->producto_id ?? null);
// Si no existe producto, intentar crear/inferrir desde la Orden de Producción
if (! $productoId && $dist->inventarioPrenda && $dist->inventarioPrenda->ordenProduccion) {
$op = $dist->inventarioPrenda->ordenProduccion;
$nombre = $op->prenda_modelo ?? $op->referencia ?? ('Producto OP #' . $op->id);
$codigo = 'AUTOD-' . $op->id . '-' . time();
$codigo = substr($codigo, 0, 50);
while (\App\Models\Producto::where('codigo_barras', $codigo)->exists()) {
$codigo .= '-' . rand(0, 9);
$codigo = substr($codigo, 0, 50);
}
$producto = \App\Models\Producto::firstOrCreate(
['nombre' => $nombre],
[
'descripcion' => 'Creado automáticamente desde distribución (OP #' . $op->id . ')',
'stock' => 0,
'estado' => true,
'precio_compra' => 0,
'precio_venta' => 0,
'unidad_medida' => 'unidad',
'codigo_barras' => $codigo,
]
);
$productoId = $producto->id;
// Guardar producto en el inventario padre para futuras referencias
$parent = $dist->inventarioPrenda;
if ($parent && ! $parent->producto_id) {
$parent->producto_id = $productoId;
$parent->save();
}
}
$variant = \App\Models\ProductVariant::firstOrCreate([
'producto_id' => $productoId,
'color_id' => $dist->color_id,
'size_id' => $dist->size_id,
], ['stock' => 0, 'sku' => 'AUTO-'.uniqid(), 'barcode' => '']);
$existing = \DB::table('variante_bodega')
->where('variante_id', $variant->id)
->where('bodega_id', $bodegaId)
->first();
if ($existing) {
\DB::table('variante_bodega')
->where('variante_id', $variant->id)
->where('bodega_id', $bodegaId)
->update(['stock' => ($existing->stock ?? 0) + $cantidad, 'updated_at' => now()]);
} else {
\DB::table('variante_bodega')->insert(['variante_id' => $variant->id, 'bodega_id' => $bodegaId, 'stock' => $cantidad, 'created_at' => now(), 'updated_at' => now()]);
}
$variant->increment('stock', $cantidad);
// Reducir disponibilidad en inventario_prenda
$parent = $dist->inventarioPrenda;
if ($parent) {
$parent->cantidad_disponible = max(0, $parent->cantidad_disponible - $cantidad);
$parent->save();
}
} else {
// Producto
$productoId = $dist->inventarioPrenda->producto_id ?? ($dist->inventarioPrenda->ordenProduccion->producto_id ?? null);
if ($productoId) {
$existing = \DB::table('producto_bodega')->where('producto_id', $productoId)->where('bodega_id', $bodegaId)->first();
if ($existing) {
\DB::table('producto_bodega')->where('producto_id', $productoId)->where('bodega_id', $bodegaId)->update(['stock' => ($existing->stock ?? 0) + $cantidad, 'updated_at' => now()]);
} else {
\DB::table('producto_bodega')->insert(['producto_id' => $productoId, 'bodega_id' => $bodegaId, 'stock' => $cantidad, 'created_at' => now(), 'updated_at' => now()]);
}
$prod = \App\Models\Producto::find($productoId);
if ($prod && ! $prod->variants()->exists()) {
$prod->increment('stock', $cantidad);
}
// Reducir disponibilidad en inventario_prenda
$parent = $dist->inventarioPrenda;
if ($parent) {
$parent->cantidad_disponible = max(0, $parent->cantidad_disponible - $cantidad);
$parent->save();
}
}
}
});
// Al actualizar, ajustar la diferencia
static::updated(function ($dist) {
$original = $dist->getOriginal();
$oldCantidad = intval($original['cantidad'] ?? 0);
$newCantidad = intval($dist->cantidad ?? 0);
$delta = $newCantidad - $oldCantidad;
if ($delta == 0) return;
$bodegaId = $dist->bodega_id;
if ($dist->color_id && $dist->size_id) {
$variant = \App\Models\ProductVariant::firstOrCreate([
'producto_id' => $dist->inventarioPrenda->producto_id ?? ($dist->inventarioPrenda->ordenProduccion->producto_id ?? null),
'color_id' => $dist->color_id,
'size_id' => $dist->size_id,
], ['stock' => 0, 'sku' => 'AUTO-'.uniqid(), 'barcode' => '']);
$existing = \DB::table('variante_bodega')->where('variante_id', $variant->id)->where('bodega_id', $bodegaId)->first();
if ($existing) {
\DB::table('variante_bodega')->where('variante_id', $variant->id)->where('bodega_id', $bodegaId)->update(['stock' => ($existing->stock ?? 0) + $delta, 'updated_at' => now()]);
} else {
\DB::table('variante_bodega')->insert(['variante_id' => $variant->id, 'bodega_id' => $bodegaId, 'stock' => max(0, $delta), 'created_at' => now(), 'updated_at' => now()]);
}
$variant->increment('stock', $delta);
$parent = $dist->inventarioPrenda;
if ($parent) {
$parent->cantidad_disponible = max(0, min($parent->cantidad_terminada, $parent->cantidad_disponible - $delta));
$parent->save();
}
} else {
$productoId = $dist->inventarioPrenda->producto_id ?? ($dist->inventarioPrenda->ordenProduccion->producto_id ?? null);
if ($productoId) {
$existing = \DB::table('producto_bodega')->where('producto_id', $productoId)->where('bodega_id', $bodegaId)->first();
if ($existing) {
\DB::table('producto_bodega')->where('producto_id', $productoId)->where('bodega_id', $bodegaId)->update(['stock' => ($existing->stock ?? 0) + $delta, 'updated_at' => now()]);
} else {
\DB::table('producto_bodega')->insert(['producto_id' => $productoId, 'bodega_id' => $bodegaId, 'stock' => max(0, $delta), 'created_at' => now(), 'updated_at' => now()]);
}
$prod = \App\Models\Producto::find($productoId);
if ($prod && ! $prod->variants()->exists()) {
$prod->increment('stock', $delta);
}
$parent = $dist->inventarioPrenda;
if ($parent) {
$parent->cantidad_disponible = max(0, min($parent->cantidad_terminada, $parent->cantidad_disponible - $delta));
$parent->save();
}
}
}
});
// Al eliminar, restar la cantidad
static::deleted(function ($dist) {
$cantidad = $dist->cantidad ?? 0;
if ($cantidad <= 0) return;
$bodegaId = $dist->bodega_id;
if ($dist->color_id && $dist->size_id) {
$variant = \App\Models\ProductVariant::where('color_id', $dist->color_id)->where('size_id', $dist->size_id)->first();
if ($variant) {
$existing = \DB::table('variante_bodega')->where('variante_id', $variant->id)->where('bodega_id', $bodegaId)->first();
if ($existing) {
$newStock = max(0, ($existing->stock ?? 0) - $cantidad);
\DB::table('variante_bodega')->where('variante_id', $variant->id)->where('bodega_id', $bodegaId)->update(['stock' => $newStock, 'updated_at' => now()]);
}
$variant->decrement('stock', $cantidad);
// Restaurar disponibilidad en inventario_prenda
$parent = $dist->inventarioPrenda;
if ($parent) {
$parent->cantidad_disponible = min($parent->cantidad_terminada, $parent->cantidad_disponible + $cantidad);
$parent->save();
}
}
} else {
$productoId = $dist->inventarioPrenda->producto_id ?? ($dist->inventarioPrenda->ordenProduccion->producto_id ?? null);
if ($productoId) {
$existing = \DB::table('producto_bodega')->where('producto_id', $productoId)->where('bodega_id', $bodegaId)->first();
if ($existing) {
$newStock = max(0, ($existing->stock ?? 0) - $cantidad);
\DB::table('producto_bodega')->where('producto_id', $productoId)->where('bodega_id', $bodegaId)->update(['stock' => $newStock, 'updated_at' => now()]);
}
$prod = \App\Models\Producto::find($productoId);
if ($prod && ! $prod->variants()->exists()) {
$prod->decrement('stock', $cantidad);
}
// Restaurar disponibilidad en inventario_prenda
$parent = $dist->inventarioPrenda;
if ($parent) {
$parent->cantidad_disponible = min($parent->cantidad_terminada, $parent->cantidad_disponible + $cantidad);
$parent->save();
}
}
}
});
}
}