id(); $table->string('code', 50)->unique()->comment('倉庫編號'); $table->string('name', 50)->comment('倉庫名稱'); $table->string('address')->nullable()->comment('地址'); $table->text('description')->nullable()->comment('描述'); $table->timestamps(); }); // 商品庫存詳情 Schema::create('inventories', function (Blueprint $table) { $table->id(); $table->foreignId('warehouse_id')->constrained()->onDelete('cascade'); $table->foreignId('product_id')->constrained()->onDelete('restrict'); $table->decimal('quantity', 10, 2)->default(0)->comment('當前庫存數量'); $table->decimal('safety_stock', 10, 2)->default(0)->nullable()->comment('安全存量'); $table->string('location', 50)->nullable()->comment('儲位/貨架號'); $table->timestamps(); $table->unique(['warehouse_id', 'product_id'], 'warehouse_product_unique'); }); // 庫存異動紀錄 Schema::create('inventory_transactions', function (Blueprint $table) { $table->id(); $table->foreignId('inventory_id')->constrained()->onDelete('cascade'); $table->string('type', 20)->comment('異動類型: purchase_in, sales_out, adjustment, transfer_in, transfer_out'); $table->decimal('quantity', 10, 2)->comment('異動數量 (+/-)'); $table->decimal('balance_before', 10, 2)->comment('異動前餘額'); $table->decimal('balance_after', 10, 2)->comment('異動後餘額'); $table->string('reason')->nullable()->comment('異動原因/備註'); $table->nullableMorphs('reference'); // reference_type, reference_id $table->foreignId('user_id')->nullable()->constrained()->onDelete('set null')->comment('操作人員'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('inventory_transactions'); Schema::dropIfExists('inventories'); Schema::dropIfExists('warehouses'); } };