Files
star-erp/app/Modules/Finance/Services/AccountPayableService.php
sky121113 455f945296
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m8s
feat: 完成進貨單自動拋轉應付帳款流程與AP介面優化
1. 新增 AccountPayable (應付帳款) 模組,包含 Migration、Model、Service 與 Controller
2. 修改 GoodsReceipt (進貨單) 流程,在確認進貨時自動產生對應的應付帳款單 (AP-YYYYMMDD-XX)
3. 實作應付帳款詳細頁面 (Show.tsx),包含發票登記與標記付款功能
4. 修正應付帳款 Show 頁面的排版,將發票資訊套用標準的綠色背景區塊,並調整按鈕位置
5. 更新相關的 Service Provider 與 Routes
2026-02-24 16:46:55 +08:00

86 lines
2.9 KiB
PHP

<?php
namespace App\Modules\Finance\Services;
use App\Modules\Finance\Models\AccountPayable;
use Illuminate\Support\Facades\DB;
use App\Modules\Inventory\Contracts\GoodsReceiptServiceInterface;
class AccountPayableService
{
protected GoodsReceiptServiceInterface $goodsReceiptService;
public function __construct(GoodsReceiptServiceInterface $goodsReceiptService)
{
$this->goodsReceiptService = $goodsReceiptService;
}
/**
* 根據進貨單建立應付帳款
*
* @param int $goodsReceiptId
* @param int $userId 執行操作的使用者 ID
* @return AccountPayable
* @throws \Exception
*/
public function createFromGoodsReceipt(int $goodsReceiptId, int $userId): AccountPayable
{
// 透過 Contract 取得 Inventory 模組的資料,避免直接依賴 Model
$receiptData = $this->goodsReceiptService->getGoodsReceiptData($goodsReceiptId);
if (!$receiptData) {
throw new \Exception("找不到對應的進貨單資料 (ID: {$goodsReceiptId})");
}
// 檢查是否已經建立過(密等性)
$existingAp = AccountPayable::where('source_document_type', 'goods_receipt')
->where('source_document_id', $goodsReceiptId)
->first();
if ($existingAp) {
return $existingAp;
}
return DB::transaction(function () use ($receiptData, $userId) {
$ap = AccountPayable::create([
'vendor_id' => $receiptData['vendor_id'],
'source_document_type' => 'goods_receipt',
'source_document_id' => $receiptData['id'],
'document_number' => $this->generateApNumber(),
'total_amount' => collect($receiptData['items'] ?? [])->sum('total_amount'),
'tax_amount' => 0, // 假設後續會實作稅額計算,目前預設為 0
'status' => AccountPayable::STATUS_PENDING,
// 設定應付日期,預設為進貨後 30 天 (可依據供應商設定調整)
'due_date' => now()->addDays(30)->toDateString(),
'created_by' => $userId,
'remarks' => "由進貨單 {$receiptData['code']} 自動生成",
]);
return $ap;
});
}
/**
* 產生應付帳款單號
*/
protected function generateApNumber(): string
{
$prefix = 'AP-' . date('Ymd') . '-';
$lastPrefix = "{$prefix}%";
$latest = AccountPayable::where('document_number', 'like', $lastPrefix)
->orderBy('document_number', 'desc')
->first();
if (!$latest) {
return $prefix . '01';
}
$parts = explode('-', $latest->document_number);
$lastNumber = intval(end($parts));
$newNumber = str_pad((string)($lastNumber + 1), 2, '0', STR_PAD_LEFT);
return $prefix . $newNumber;
}
}