refactor: 重構模組通訊與調整儀表板功能
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 57s

- 依循跨模組通訊規範,將 Sales 與 Production 模組中對 Inventory 的直接模型關聯改為透過 InventoryServiceInterface 取得
- 於 InventoryService 實作獲取最高庫存價值、即將過期商品等方法,供儀表板使用
- 確保所有跨模組調用皆採用手動水和(Manual Hydration)方式組合資料
- 移除本地已歸檔的 .agent 規範檔案
This commit is contained in:
2026-02-25 11:48:52 +08:00
parent ad91b08dbc
commit deef3baacc
22 changed files with 826 additions and 1396 deletions

View File

@@ -40,6 +40,14 @@ interface InventoryServiceInterface
*/
public function getProductsByIds(array $ids);
/**
* Get multiple warehouses by their codes.
*
* @param array $codes
* @return \Illuminate\Support\Collection
*/
public function getWarehousesByCodes(array $codes);
/**
* Search products by name.
*
@@ -139,4 +147,14 @@ interface InventoryServiceInterface
* @return object
*/
public function findOrCreateWarehouseByName(string $warehouseName);
/**
* Get top inventory value for dashboard.
*/
public function getTopInventoryValue(int $limit = 5): \Illuminate\Support\Collection;
/**
* Get items expiring soon for dashboard.
*/
public function getExpiringSoon(int $limit = 5): \Illuminate\Support\Collection;
}

View File

@@ -7,11 +7,10 @@ use App\Modules\Inventory\Services\GoodsReceiptService;
use App\Modules\Inventory\Services\InventoryService;
use App\Modules\Procurement\Contracts\ProcurementServiceInterface;
use Illuminate\Http\Request;
use App\Modules\Procurement\Models\Vendor;
use App\Modules\Inventory\Services\DuplicateCheckService;
use Inertia\Inertia;
use App\Modules\Inventory\Models\GoodsReceipt;
use Illuminate\Support\Facades\DB;
use App\Modules\Inventory\Services\DuplicateCheckService;
class GoodsReceiptController extends Controller
{

View File

@@ -16,6 +16,26 @@ class InventoryService implements InventoryServiceInterface
return Warehouse::all();
}
public function getTopInventoryValue(int $limit = 5): \Illuminate\Support\Collection
{
return Inventory::select('product_id', \Illuminate\Support\Facades\DB::raw('SUM(quantity * unit_cost) as total_value'))
->where('quantity', '>', 0)
->groupBy('product_id')
->orderByDesc('total_value')
->limit($limit)
->get();
}
public function getExpiringSoon(int $limit = 5): \Illuminate\Support\Collection
{
return Inventory::where('quantity', '>', 0)
->whereNotNull('expiry_date')
->where('expiry_date', '>=', now()) // 只顯示未過期但即將過期的
->orderBy('expiry_date', 'asc')
->limit($limit)
->get();
}
public function getAllProducts()
{
return Product::with(['baseUnit', 'largeUnit'])->get();
@@ -41,6 +61,11 @@ class InventoryService implements InventoryServiceInterface
return Product::whereIn('id', $ids)->with(['baseUnit', 'largeUnit'])->get();
}
public function getWarehousesByCodes(array $codes)
{
return Warehouse::whereIn('code', $codes)->get();
}
public function getProductsByName(string $name)
{
return Product::where('name', 'like', "%{$name}%")->with(['baseUnit', 'largeUnit'])->get();