This commit is contained in:
lizandrogd
2026-01-20 01:01:32 -05:00
parent 58ed9609e1
commit 3709078404
3 changed files with 87 additions and 7 deletions
+1 -4
View File
@@ -166,10 +166,7 @@ class InventarioPrendaDistribucion extends Model
\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);
}
// 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;
+56 -3
View File
@@ -79,9 +79,8 @@ class OrdenProduccion extends Model
$orden->referencia = '';
}
// Reserva de tela al crear cuando la OP ya nace en 'en_corte'
$estadoInicial = $orden->estado ?? 'en_corte';
if ($estadoInicial === 'en_corte' && $orden->tela_id && ($orden->metros_requeridos ?? 0) > 0) {
// Reserva de tela al crear cuando la OP usa una tela: restar metros_disponibles inmediatamente
if ($orden->tela_id && ($orden->metros_requeridos ?? 0) > 0) {
$tela = \App\Models\Tela::find($orden->tela_id);
if (! $tela) {
throw \Illuminate\Validation\ValidationException::withMessages([
@@ -119,6 +118,60 @@ class OrdenProduccion extends Model
}
}
// Ajustes automáticos de reserva cuando cambia la tela o los metros requeridos
$originalTelaId = $orden->getOriginal('tela_id');
$originalMetros = $orden->getOriginal('metros_requeridos') ?? 0;
$newTelaId = $orden->tela_id;
$newMetros = $orden->metros_requeridos ?? 0;
// Si cambió la tela en la OP, devolver los metros reservados en la tela anterior (si aplica)
if ($originalTelaId && $originalTelaId != $newTelaId && $originalMetros > 0) {
$oldTela = \App\Models\Tela::find($originalTelaId);
if ($oldTela) {
$oldTela->metros_disponibles = $oldTela->metros_disponibles + $originalMetros;
$oldTela->save();
}
}
// Reservar metros en la nueva tela si se cambió
if ($newTelaId && $originalTelaId != $newTelaId && $newMetros > 0) {
$newTela = \App\Models\Tela::find($newTelaId);
if (! $newTela) {
throw \Illuminate\Validation\ValidationException::withMessages([
'tela_id' => 'No se encontró la tela asociada.',
]);
}
if ($newTela->metros_disponibles < $newMetros) {
throw \Illuminate\Validation\ValidationException::withMessages([
'metros_requeridos' => 'No hay suficientes metros disponibles para reservar (' . $newTela->metros_disponibles . ').',
]);
}
$newTela->metros_disponibles = $newTela->metros_disponibles - $newMetros;
$newTela->save();
$orden->tela_reservada = true;
}
// Si la misma tela y cambiaron los metros, ajustar la diferencia
if ($originalTelaId == $newTelaId && $originalMetros != $newMetros && $newTelaId) {
$delta = $newMetros - $originalMetros;
$tela = \App\Models\Tela::find($newTelaId);
if ($tela) {
if ($delta > 0) {
if ($tela->metros_disponibles < $delta) {
throw \Illuminate\Validation\ValidationException::withMessages([
'metros_requeridos' => 'No hay suficientes metros disponibles para aumentar la reserva.',
]);
}
$tela->metros_disponibles = $tela->metros_disponibles - $delta;
} elseif ($delta < 0) {
$tela->metros_disponibles = $tela->metros_disponibles + abs($delta);
}
$tela->save();
}
}
$originalEstado = $orden->getOriginal('estado');
$nuevoEstado = $orden->estado;
@@ -85,6 +85,36 @@ class InventarioDistribucionTest extends TestCase
$this->assertEquals(2, $pivot->stock);
}
public function test_distribution_does_not_double_increment_product_stock()
{
$categoria = \App\Models\Categoria::create(['nombre' => 'Ropa']);
$producto = Producto::create(['nombre' => 'Doblez', 'descripcion' => '', 'stock' => 0, 'estado' => true, 'precio_compra' => 0, 'precio_venta' => 0, 'unidad_medida' => 'unidad', 'codigo_barras' => '', 'categoria_id' => $categoria->id, 'imagen' => '']);
$op = OrdenProduccion::create(['numero_orden' => 'OP-0200', 'prenda_modelo' => 'Doblez', 'referencia' => 'D-01', 'cantidad_total' => 10, 'metros_requeridos' => 0, 'fecha_inicio' => now(), 'fecha_entrega_estimada' => now()->addDays(7)]);
// Crear inventario: esto incrementa el stock global del producto en +5
$inv = InventarioPrenda::create(['orden_produccion_id' => $op->id, 'cantidad_terminada' => 5, 'cantidad_disponible' => 5, 'fecha_ingreso' => now(), 'estado' => 'en_bodega', 'producto_id' => $producto->id]);
$producto->refresh();
$this->assertEquals(5, $producto->stock, 'Stock should be increased by inventario creation');
// Crear distribución: no debe aumentar nuevamente el stock global del producto
InventarioPrendaDistribucion::create([
'inventario_prenda_id' => $inv->id,
'bodega_id' => 1,
'color_id' => null,
'size_id' => null,
'cantidad' => 2,
]);
$producto->refresh();
$this->assertEquals(5, $producto->stock, 'Stock should NOT be increased by distribution creator (no double count)');
$pivot = \DB::table('producto_bodega')->where('producto_id', $producto->id)->where('bodega_id', 1)->first();
$this->assertNotNull($pivot);
$this->assertEquals(2, $pivot->stock);
}
public function test_creating_inventario_with_excessive_distributions_throws_validation_exception()
{
$categoria = \App\Models\Categoria::create(['nombre' => 'Ropa']);