refactor: 重構模組通訊與調整儀表板功能
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 57s
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:
@@ -7,23 +7,41 @@ use App\Modules\Finance\Models\AccountPayable;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Inertia;
|
||||
|
||||
use App\Modules\Procurement\Contracts\ProcurementServiceInterface;
|
||||
use App\Modules\Inventory\Contracts\InventoryServiceInterface;
|
||||
|
||||
class AccountPayableController extends Controller
|
||||
{
|
||||
protected $procurementService;
|
||||
protected $inventoryService;
|
||||
|
||||
public function __construct(
|
||||
ProcurementServiceInterface $procurementService,
|
||||
InventoryServiceInterface $inventoryService
|
||||
) {
|
||||
$this->procurementService = $procurementService;
|
||||
$this->inventoryService = $inventoryService;
|
||||
}
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = AccountPayable::with(['vendor', 'creator']);
|
||||
$query = AccountPayable::with(['creator']);
|
||||
|
||||
// 關鍵字搜尋 (單號、供應商名稱)
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('document_number', 'like', "%{$search}%")
|
||||
->orWhereHas('vendor', function ($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%");
|
||||
});
|
||||
|
||||
// 透過 ProcurementService 查詢符合關鍵字的 Vendor IDs
|
||||
$matchedVendors = $this->procurementService->searchVendors($search);
|
||||
$vendorIds = $matchedVendors->pluck('id')->toArray();
|
||||
|
||||
$query->where(function ($q) use ($search, $vendorIds) {
|
||||
$q->where('document_number', 'like', "%{$search}%");
|
||||
if (!empty($vendorIds)) {
|
||||
$q->orWhereIn('vendor_id', $vendorIds);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -48,7 +66,16 @@ class AccountPayableController extends Controller
|
||||
$perPage = $request->input('per_page', 10);
|
||||
$payables = $query->latest()->paginate($perPage)->withQueryString();
|
||||
|
||||
$vendors = \App\Modules\Procurement\Models\Vendor::select('id', 'name')->get();
|
||||
// Manual Hydration for Vendors
|
||||
$allVendorIds = collect($payables->items())->pluck('vendor_id')->unique()->filter()->toArray();
|
||||
$vendorsMap = $this->procurementService->getVendorsByIds($allVendorIds)->keyBy('id');
|
||||
|
||||
$payables->getCollection()->transform(function ($item) use ($vendorsMap) {
|
||||
$item->vendor = $vendorsMap->get($item->vendor_id);
|
||||
return $item;
|
||||
});
|
||||
|
||||
$vendors = $this->procurementService->getAllVendors();
|
||||
|
||||
return Inertia::render('AccountPayable/Index', [
|
||||
'payables' => $payables,
|
||||
@@ -62,14 +89,19 @@ class AccountPayableController extends Controller
|
||||
*/
|
||||
public function show(AccountPayable $accountPayable)
|
||||
{
|
||||
$accountPayable->load(['vendor', 'creator']);
|
||||
$accountPayable->load(['creator']);
|
||||
|
||||
if ($accountPayable->vendor_id) {
|
||||
$accountPayable->vendor = $this->procurementService->getVendorsByIds([$accountPayable->vendor_id])->first();
|
||||
}
|
||||
|
||||
// 嘗試加載來源單據資訊 (目前支援 goods_receipt)
|
||||
$sourceDocumentCode = null;
|
||||
if ($accountPayable->source_document_type === 'goods_receipt') {
|
||||
$receipt = \App\Modules\Inventory\Models\GoodsReceipt::find($accountPayable->source_document_id);
|
||||
if ($receipt) {
|
||||
$sourceDocumentCode = $receipt->code;
|
||||
$receiptData = app(\App\Modules\Inventory\Contracts\GoodsReceiptServiceInterface::class)
|
||||
->getGoodsReceiptData($accountPayable->source_document_id);
|
||||
if ($receiptData) {
|
||||
$sourceDocumentCode = $receiptData['code'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user