id(); $table->foreignId('tenant_id')->constrained()->restrictOnDelete(); $table->foreignId('created_by')->constrained('users')->restrictOnDelete(); $table->foreignId('responsible_id')->constrained('users')->restrictOnDelete(); $table->foreignId('warehouse_id')->constrained()->restrictOnDelete(); $table->foreignId('destination_warehouse_id')->nullable()->constrained('warehouses')->restrictOnDelete(); $table->foreignId('stock_item_id')->constrained()->restrictOnDelete(); $table->foreignId('count_id')->nullable()->unique()->constrained('stock_operations')->restrictOnDelete(); $table->string('kind'); $table->string('reference', 100); $table->uuid('idempotency_key'); $table->string('payload_hash', 64); $table->string('destination', 200)->nullable(); $table->text('reason'); $table->bigInteger('quantity_milli'); $table->bigInteger('theoretical_milli')->nullable(); $table->unsignedBigInteger('ledger_version')->nullable(); $table->json('snapshot'); $table->timestamp('recorded_at'); $table->unique(['tenant_id', 'reference']); $table->unique(['tenant_id', 'idempotency_key']); }); Schema::table('stock_movements', function (Blueprint $table) { $table->unsignedBigInteger('goods_receipt_item_id')->nullable()->change(); $table->bigInteger('quantity_milli')->change(); $table->foreignId('stock_operation_id')->nullable()->constrained()->restrictOnDelete(); $table->unique(['stock_operation_id', 'warehouse_id']); }); } public function down(): void { // Signed ledger entries must never be coerced back to unsigned quantities. throw new LogicException('Migração de histórico irreversível; preservar movimentos e usar migrações aditivas.'); } };