first commit

This commit is contained in:
2025-12-30 15:03:19 +08:00
commit c735c36009
902 changed files with 83591 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
<?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('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};

View File

@@ -0,0 +1,35 @@
<?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('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration');
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};

View File

@@ -0,0 +1,57 @@
<?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('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};

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.
*/
public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('description')->nullable();
$table->boolean('is_active')->default(true);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('categories');
}
};

View File

@@ -0,0 +1,40 @@
<?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('products', function (Blueprint $table) {
$table->id();
$table->string('code')->unique()->comment('商品編號');
$table->string('name')->comment('商品名稱');
$table->foreignId('category_id')->constrained('categories')->onDelete('restrict')->comment('商品分類');
$table->string('brand')->nullable()->comment('品牌');
$table->text('specification')->nullable()->comment('規格描述');
// Unit conversion
$table->string('base_unit')->comment('基本庫存單位 (e.g. g, ml)');
$table->string('large_unit')->nullable()->comment('大單位 (e.g. 桶, 箱)');
$table->decimal('conversion_rate', 10, 4)->default(1)->comment('換算率 (1 大單位 = ? 基本單位)');
$table->string('purchase_unit')->nullable()->comment('採購單位');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('products');
}
};

View File

@@ -0,0 +1,38 @@
<?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('vendors', function (Blueprint $table) {
$table->id();
$table->string('code')->unique()->comment('廠商編號');
$table->string('name')->comment('廠商名稱');
$table->string('short_name')->nullable()->comment('廠商簡稱');
$table->string('tax_id')->nullable()->comment('統一編號');
$table->string('owner')->nullable()->comment('負責人');
$table->string('contact_name')->nullable()->comment('聯絡人');
$table->string('tel')->nullable()->comment('市話');
$table->string('phone')->nullable()->comment('連絡電話');
$table->string('email')->nullable()->comment('電子郵件');
$table->text('address')->nullable()->comment('地址');
$table->text('remark')->nullable()->comment('備註');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('vendors');
}
};

View File

@@ -0,0 +1,68 @@
<?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('vendors', function (Blueprint $table) {
$table->string('code', 50)->change();
$table->string('name', 100)->change();
$table->string('short_name', 50)->nullable()->change();
$table->string('tax_id', 20)->nullable()->change();
$table->string('owner', 50)->nullable()->change();
$table->string('contact_name', 50)->nullable()->change();
$table->string('tel', 20)->nullable()->change();
$table->string('phone', 20)->nullable()->change();
});
Schema::table('products', function (Blueprint $table) {
$table->string('code', 50)->change();
$table->string('name', 100)->change();
$table->string('brand', 50)->nullable()->change();
$table->string('base_unit', 20)->change();
$table->string('large_unit', 20)->nullable()->change();
$table->string('purchase_unit', 20)->nullable()->change();
});
Schema::table('categories', function (Blueprint $table) {
$table->string('name', 50)->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('vendors', function (Blueprint $table) {
$table->string('code', 255)->change();
$table->string('name', 255)->change();
$table->string('short_name', 255)->nullable()->change();
$table->string('tax_id', 255)->nullable()->change();
$table->string('owner', 255)->nullable()->change();
$table->string('contact_name', 255)->nullable()->change();
$table->string('tel', 255)->nullable()->change();
$table->string('phone', 255)->nullable()->change();
});
Schema::table('products', function (Blueprint $table) {
$table->string('code', 255)->change();
$table->string('name', 255)->change();
$table->string('brand', 255)->nullable()->change();
$table->string('base_unit', 255)->change();
$table->string('large_unit', 255)->nullable()->change();
$table->string('purchase_unit', 255)->nullable()->change();
});
Schema::table('categories', function (Blueprint $table) {
$table->string('name', 255)->change();
});
}
};

View File

@@ -0,0 +1,61 @@
<?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('warehouses', function (Blueprint $table) {
$table->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');
}
};

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', 20)->comment('異動類型: 採購進貨, 銷售出庫, 盤點調整, 撥補入庫, 撥補出庫, 手動入庫')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inventory_transactions', function (Blueprint $table) {
$table->string('type', 20)->comment('異動類型: purchase_in, sales_out, adjustment, transfer_in, transfer_out')->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('inventory_transactions', function (Blueprint $table) {
$table->dateTime('actual_time')->nullable()->after('reason')->comment('實際異動發生時間');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inventory_transactions', function (Blueprint $table) {
$table->dropColumn('actual_time');
});
}
};

View File

@@ -0,0 +1,33 @@
<?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('product_vendor', function (Blueprint $table) {
$table->id();
$table->foreignId('vendor_id')->constrained()->cascadeOnDelete();
$table->foreignId('product_id')->constrained()->cascadeOnDelete();
$table->decimal('last_price', 10, 2)->nullable()->comment('最近一次進價');
$table->timestamps();
// 確保同一個廠商對同一個商品只有一筆記錄
$table->unique(['vendor_id', 'product_id']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('product_vendor');
}
};

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.
*/
public function up(): void
{
Schema::table('inventories', function (Blueprint $table) {
// Change default value of safety_stock to NULL
$table->decimal('safety_stock', 10, 2)->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('inventories', function (Blueprint $table) {
// Revert default value to 0
$table->decimal('safety_stock', 10, 2)->nullable()->default(0)->change();
});
}
};

View File

@@ -0,0 +1,37 @@
<?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('purchase_orders', function (Blueprint $table) {
$table->id();
$table->string('code')->unique()->comment('採購單號');
$table->foreignId('vendor_id')->constrained()->onDelete('restrict');
$table->foreignId('warehouse_id')->nullable()->constrained()->onDelete('set null');
$table->foreignId('user_id')->constrained()->onDelete('restrict');
$table->string('status')->default('draft')->comment('草稿, 待審核, 處理中, 運送中, 待確認, 已完成');
$table->date('expected_delivery_date')->nullable();
$table->decimal('total_amount', 12, 2)->default(0);
$table->decimal('tax_amount', 12, 2)->default(0);
$table->decimal('grand_total', 12, 2)->default(0);
$table->text('remark')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('purchase_orders');
}
};

View File

@@ -0,0 +1,33 @@
<?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('purchase_order_items', function (Blueprint $table) {
$table->id();
$table->foreignId('purchase_order_id')->constrained()->onDelete('cascade');
$table->foreignId('product_id')->constrained()->onDelete('restrict');
$table->decimal('quantity', 10, 2);
$table->decimal('unit_price', 10, 2);
$table->decimal('subtotal', 12, 2);
$table->decimal('received_quantity', 10, 2)->default(0);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('purchase_order_items');
}
};