生產工單BOM以及批號完善
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 57s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped

This commit is contained in:
2026-01-22 15:39:35 +08:00
parent 1ae21febb5
commit 1d134c9ad8
31 changed files with 2684 additions and 694 deletions

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('inventories', function (Blueprint $table) {
// 先新增新的唯一約束 (倉庫 + 商品 + 批號)
// 這樣可以確保 warehouse_id 始終有索引可用,避免外鍵約束錯誤
$table->unique(['warehouse_id', 'product_id', 'batch_number'], 'warehouse_product_batch_unique');
// 然後移除舊的唯一約束 (倉庫 + 商品)
$table->dropUnique('warehouse_product_unique');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inventories', function (Blueprint $table) {
// 恢復時也要注意順序,先加回舊的(如果資料允許),再刪除新的
// 但如果資料已經有多批號,加回舊的會失敗。這裡只盡力而為。
$table->unique(['warehouse_id', 'product_id'], 'warehouse_product_unique');
$table->dropUnique('warehouse_product_batch_unique');
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('inventory_transactions', function (Blueprint $table) {
$table->string('type', 50)->comment('異動類型: 採購進貨, 銷售出庫, 盤點調整, 撥補入庫, 撥補出庫, 手動入庫, 手動調整庫存')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inventory_transactions', function (Blueprint $table) {
$table->string('type', 20)->comment('異動類型: 採購進貨, 銷售出庫, 盤點調整, 撥補入庫, 撥補出庫, 手動入庫')->change();
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('inventories', function (Blueprint $table) {
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inventories', function (Blueprint $table) {
$table->dropSoftDeletes();
});
}
};

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('warehouse_product_safety_stocks', function (Blueprint $table) {
$table->id();
$table->foreignId('warehouse_id')->constrained()->cascadeOnDelete();
$table->foreignId('product_id')->constrained()->cascadeOnDelete();
$table->decimal('safety_stock', 10, 2)->default(0);
$table->timestamps();
$table->unique(['warehouse_id', 'product_id'], 'wh_product_safety_stock_unique');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('warehouse_product_safety_stocks');
}
};

View File

@@ -0,0 +1,55 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
* inventories.safety_stock 資料遷移至 warehouse_product_safety_stocks 表格
*/
public function up(): void
{
// 1. 遷移現有資料:從 inventories 提取唯一的 warehouse_id + product_id 組合及其 safety_stock
DB::statement("
INSERT INTO warehouse_product_safety_stocks (warehouse_id, product_id, safety_stock, created_at, updated_at)
SELECT
warehouse_id,
product_id,
MAX(safety_stock) as safety_stock,
NOW(),
NOW()
FROM inventories
WHERE safety_stock IS NOT NULL AND safety_stock > 0
GROUP BY warehouse_id, product_id
ON DUPLICATE KEY UPDATE safety_stock = VALUES(safety_stock), updated_at = NOW()
");
// 2. 移除 inventories 表的 safety_stock 欄位
Schema::table('inventories', function (Blueprint $table) {
$table->dropColumn('safety_stock');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// 1. 在 inventories 表重新加入 safety_stock 欄位
Schema::table('inventories', function (Blueprint $table) {
$table->decimal('safety_stock', 10, 2)->nullable()->after('quantity');
});
// 2. 將資料還原回 inventories (更新同商品所有批號)
DB::statement("
UPDATE inventories i
INNER JOIN warehouse_product_safety_stocks ss
ON i.warehouse_id = ss.warehouse_id AND i.product_id = ss.product_id
SET i.safety_stock = ss.safety_stock
");
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* warehouse_id 改為 nullable支援草稿模式。
*/
public function up(): void
{
Schema::table('production_orders', function (Blueprint $table) {
$table->foreignId('warehouse_id')->nullable()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('production_orders', function (Blueprint $table) {
$table->foreignId('warehouse_id')->nullable(false)->change();
});
}
};