feat: 修正庫存與撥補單邏輯並整合文件
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Successful in 53s
Koori-ERP-Deploy-System / deploy-production (push) Has been skipped

1. 修復倉庫統計數據加總與樣式。
2. 修正可用庫存計算邏輯(排除不可銷售倉庫)。
3. 撥補單商品列表加入批號與效期顯示。
4. 修正撥補單儲存邏輯以支援精確批號轉移。
5. 整合 FEATURES.md 至 README.md。
This commit is contained in:
2026-01-26 14:59:24 +08:00
parent b0848a6bb8
commit 106de4e945
81 changed files with 4118 additions and 1023 deletions

View File

@@ -4,7 +4,7 @@ namespace App\Modules\Inventory\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Modules\Procurement\Models\PurchaseOrder; // Cross-module dependency
class Inventory extends Model
{
@@ -35,8 +35,8 @@ class Inventory extends Model
];
/**
* Transient property to store the reason for the activity log (e.g., "Replenishment #123").
* This is not stored in the database column but used for logging context.
* 用於活動記錄的暫時屬性(例如 "補貨 #123")。
* 此屬性不存儲在資料庫欄位中,但用於記錄上下文。
* @var string|null
*/
public $activityLogReason;
@@ -55,12 +55,12 @@ class Inventory extends Model
$attributes = $properties['attributes'] ?? [];
$snapshot = $properties['snapshot'] ?? [];
// Always snapshot names for context, even if IDs didn't change
// $this refers to the Inventory model instance
// 始終對名稱進行快照以便於上下文顯示,即使 ID 未更改
// $this 指的是 Inventory 模型實例
$snapshot['warehouse_name'] = $this->warehouse ? $this->warehouse->name : ($snapshot['warehouse_name'] ?? null);
$snapshot['product_name'] = $this->product ? $this->product->name : ($snapshot['product_name'] ?? null);
// Capture the reason if set
// 如果已設定原因,則進行捕捉
if ($this->activityLogReason) {
$attributes['_reason'] = $this->activityLogReason;
}
@@ -105,13 +105,7 @@ class Inventory extends Model
});
}
/**
* 來源採購單
*/
public function sourcePurchaseOrder(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(PurchaseOrder::class, 'source_purchase_order_id');
}
/**
* 產生批號

View File

@@ -4,7 +4,7 @@ namespace App\Modules\Inventory\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Modules\Core\Models\User; // Cross-module Core dependency
use App\Modules\Core\Models\User; // 跨模組核心依賴
class InventoryTransaction extends Model
{

View File

@@ -9,7 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
use App\Modules\Procurement\Models\Vendor; // Cross-module dependency (Procurement)
class Product extends Model
{
@@ -32,7 +32,7 @@ class Product extends Model
];
/**
* Get the category that owns the product.
* 取得該商品所屬的分類。
*/
public function category(): BelongsTo
{
@@ -54,10 +54,7 @@ class Product extends Model
return $this->belongsTo(Unit::class, 'purchase_unit_id');
}
public function vendors(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(Vendor::class)->withPivot('last_price')->withTimestamps();
}
public function inventories(): \Illuminate\Database\Eloquent\Relations\HasMany
{
@@ -83,13 +80,13 @@ class Product extends Model
$attributes = $properties['attributes'] ?? [];
$snapshot = $properties['snapshot'] ?? [];
// Handle Category Name Snapshot
// 處理分類名稱快照
if (isset($attributes['category_id'])) {
$category = Category::find($attributes['category_id']);
$snapshot['category_name'] = $category ? $category->name : null;
}
// Handle Unit Name Snapshots
// 處理單位名稱快照
$unitFields = ['base_unit_id', 'large_unit_id', 'purchase_unit_id'];
foreach ($unitFields as $field) {
if (isset($attributes[$field])) {
@@ -99,7 +96,7 @@ class Product extends Model
}
}
// Always snapshot self name for context (so logs always show "Cola")
// 始終對自身名稱進行快照以便於上下文顯示(這樣日誌總是顯示 "可樂"
$snapshot['name'] = $this->name;
$properties['attributes'] = $attributes;

View File

@@ -4,7 +4,7 @@ namespace App\Modules\Inventory\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Modules\Procurement\Models\PurchaseOrder; // Cross-module dependency (Procurement)
class Warehouse extends Model
{
@@ -17,6 +17,11 @@ class Warehouse extends Model
'name',
'address',
'description',
'is_sellable',
];
protected $casts = [
'is_sellable' => 'boolean',
];
public function getActivitylogOptions(): \Spatie\Activitylog\LogOptions
@@ -43,10 +48,7 @@ class Warehouse extends Model
return $this->hasMany(Inventory::class);
}
public function purchaseOrders(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(PurchaseOrder::class);
}
public function products(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{