339 lines
15 KiB
PHP
339 lines
15 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',
|
|
'proveedor_id',
|
|
'color_id',
|
|
'size_id',
|
|
'cantidad',
|
|
];
|
|
|
|
public function inventarioPrenda()
|
|
{
|
|
return $this->belongsTo(InventarioPrenda::class);
|
|
}
|
|
|
|
public function bodega()
|
|
{
|
|
return $this->belongsTo(Bodega::class);
|
|
}
|
|
|
|
public function proveedor()
|
|
{
|
|
return $this->belongsTo(Proveedor::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 terminada total (no distribuir más del total entregado)
|
|
if (($sumExistentes + $cantidad) > (int) $parent->cantidad_terminada) {
|
|
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 terminada total (no distribuir más del total entregado)
|
|
if (($othersSum + $newCantidad) > (int) $parent->cantidad_terminada) {
|
|
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 a proveedor_id is present, treat as assignment to a provider/person (no warehouse stock changes)
|
|
if ($dist->proveedor_id && ! $bodegaId) {
|
|
// Just decrement disponibilidad on parent
|
|
$parent = $dist->inventarioPrenda;
|
|
if ($parent) {
|
|
$parent->cantidad_disponible = max(0, $parent->cantidad_disponible - $cantidad);
|
|
$parent->save();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
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);
|
|
|
|
// 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 = 'AUTOP-' . $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::create([
|
|
'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,
|
|
'categoria_id' => \App\Models\Categoria::first()?->id ?? \App\Models\Categoria::create(['nombre' => 'Generica'])->id,
|
|
]);
|
|
|
|
$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();
|
|
}
|
|
}
|
|
|
|
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()]);
|
|
}
|
|
|
|
// Nota: No incrementamos el stock global del producto aquí — el stock global ya se incrementó cuando se creó el InventarioPrenda.
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|