diff --git a/database/migrations/2026_09_25_000000_generate_available_inventory_stock.php b/database/migrations/2026_09_25_000000_generate_available_inventory_stock.php index fe0694f0..533a02bf 100644 --- a/database/migrations/2026_09_25_000000_generate_available_inventory_stock.php +++ b/database/migrations/2026_09_25_000000_generate_available_inventory_stock.php @@ -52,8 +52,38 @@ return new class extends Migration private function assertNonNegative(string $expression, string $reason): void { - if (DB::table('inventories')->whereRaw("({$expression}) < 0")->exists()) { - throw new RuntimeException("Hay inventarios inconsistentes: {$reason}."); + $invalidInventories = DB::table('inventories') + ->select([ + 'id', + 'real_stock', + 'sold_units', + 'refunded_units', + 'reserved_stock', + 'entry_reserved_stock', + ]) + ->selectRaw("({$expression}) as calculated_stock") + ->whereRaw("({$expression}) < 0") + ->orderBy('id') + ->limit(20) + ->get(); + + if ($invalidInventories->isNotEmpty()) { + $details = $invalidInventories + ->map(static fn (object $inventory): string => sprintf( + 'id=%d [real=%d, vendidas=%d, reintegradas=%d, reservadas=%d, reservas_entradas=%d, resultado=%d]', + $inventory->id, + $inventory->real_stock, + $inventory->sold_units, + $inventory->refunded_units, + $inventory->reserved_stock, + $inventory->entry_reserved_stock, + $inventory->calculated_stock, + )) + ->implode('; '); + + throw new RuntimeException( + "Hay inventarios inconsistentes: {$reason}. Inventarios detectados (máximo 20): {$details}." + ); } } }; diff --git a/tests/Feature/Migrations/InventoryStockMovementMigrationTest.php b/tests/Feature/Migrations/InventoryStockMovementMigrationTest.php index c70c29ee..8946f515 100644 --- a/tests/Feature/Migrations/InventoryStockMovementMigrationTest.php +++ b/tests/Feature/Migrations/InventoryStockMovementMigrationTest.php @@ -113,12 +113,16 @@ class InventoryStockMovementMigrationTest extends TestCase public function test_migration_rejects_an_inventory_with_negative_available_stock(): void { DB::table('inventories')->insert([ + 'id' => 23, 'real_stock' => 1, 'reserved_stock' => 2, ]); $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('stock disponible actual es negativo'); + $this->expectExceptionMessage( + 'stock disponible actual es negativo. Inventarios detectados (máximo 20): ' + .'id=23 [real=1, vendidas=0, reintegradas=0, reservadas=2, reservas_entradas=0, resultado=-1]' + ); $this->stockMigration()->up(); }