feat: 完成進貨單自動拋轉應付帳款流程與AP介面優化
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m8s

1. 新增 AccountPayable (應付帳款) 模組,包含 Migration、Model、Service 與 Controller
2. 修改 GoodsReceipt (進貨單) 流程,在確認進貨時自動產生對應的應付帳款單 (AP-YYYYMMDD-XX)
3. 實作應付帳款詳細頁面 (Show.tsx),包含發票登記與標記付款功能
4. 修正應付帳款 Show 頁面的排版,將發票資訊套用標準的綠色背景區塊,並調整按鈕位置
5. 更新相關的 Service Provider 與 Routes
This commit is contained in:
2026-02-24 16:46:55 +08:00
parent aaa93a921e
commit 455f945296
33 changed files with 1708 additions and 186 deletions

View File

@@ -26,29 +26,34 @@ export default function ViewPurchaseOrderPage({ order }: Props) {
<Head title={`採購單詳情 - ${order.poNumber}`} />
<div className="container mx-auto p-6 max-w-7xl">
{/* Header */}
{/* 返回按鈕 */}
<div className="mb-6">
<Link href="/purchase-orders">
<Button
variant="outline"
className="gap-2 button-outlined-primary mb-6"
className="gap-2 button-outlined-primary"
>
<ArrowLeft className="h-4 w-4" />
</Button>
</Link>
</div>
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
<ShoppingCart className="h-6 w-6 text-primary-main" />
</h1>
<p className="text-gray-500 mt-1">{order.poNumber}</p>
</div>
<div className="flex items-center gap-3">
{/* 頁面標題與操作 */}
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-2xl font-bold text-grey-0 flex items-center gap-2">
<ShoppingCart className="h-6 w-6 text-primary-main" />
</h1>
<div className="flex items-center gap-2 mt-1">
<PurchaseOrderStatusBadge status={order.status} />
<span className="text-gray-500 text-sm">{order.poNumber}</span>
</div>
</div>
<div className="flex items-center gap-3">
<PurchaseOrderActions order={order} />
</div>
</div>
{/* 狀態流程條 */}
<div className="mb-8">
@@ -169,10 +174,6 @@ export default function ViewPurchaseOrderPage({ order }: Props) {
</div>
</div>
{/* 操作按鈕 (底部) */}
<div className="flex justify-end pt-4">
<PurchaseOrderActions order={order} />
</div>
</div>
</div>
</div>
@@ -225,16 +226,15 @@ function PurchaseOrderActions({ order }: { order: PurchaseOrder }) {
const canSubmit = canEdit || canView;
return (
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
{['draft', 'pending', 'approved'].includes(order.status) && canCancel && (
<Button
onClick={() => handleUpdateStatus('cancelled', '作廢')}
disabled={processing}
variant="outline"
size="xl"
className="button-outlined-error shadow-red-200/20 border-red-600 text-red-600 hover:bg-red-50"
className="button-outlined-error border-red-600 text-red-600 hover:bg-red-50"
>
<XCircle className="h-5 w-5" />
<XCircle className="h-4 w-4 mr-1" />
</Button>
)}
@@ -243,23 +243,19 @@ function PurchaseOrderActions({ order }: { order: PurchaseOrder }) {
onClick={() => handleUpdateStatus('draft', '退回')}
disabled={processing}
variant="outline"
size="xl"
className="button-outlined-warning shadow-amber-200/20"
className="button-outlined-warning"
>
<RotateCcw className="h-5 w-5" /> 退
<RotateCcw className="h-4 w-4 mr-1" /> 退
</Button>
)}
<div className="flex-1" />
{order.status === 'draft' && canSubmit && (
<Button
onClick={() => handleUpdateStatus('pending', '送出審核')}
disabled={processing}
size="xl"
className="button-filled-primary shadow-primary/20"
>
<Send className="h-5 w-5" />
<Send className="h-4 w-4 mr-1" />
</Button>
)}
@@ -267,10 +263,9 @@ function PurchaseOrderActions({ order }: { order: PurchaseOrder }) {
<Button
onClick={() => handleUpdateStatus('approved', '核准')}
disabled={processing}
size="xl"
className="button-filled-primary shadow-primary/20"
>
<CheckCircle className="h-5 w-5" />
<CheckCircle className="h-4 w-4 mr-1" />
</Button>
)}
</div>