feat: 完成進貨單自動拋轉應付帳款流程與AP介面優化
All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m8s
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:
@@ -23,6 +23,13 @@ import {
|
||||
DialogFooter,
|
||||
DialogDescription,
|
||||
} from "@/Components/ui/dialog";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/Components/ui/select";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -138,10 +145,6 @@ export default function Show({ requisition, warehouses }: Props) {
|
||||
};
|
||||
|
||||
const handleApprove = () => {
|
||||
if (!supplyWarehouseId) {
|
||||
toast.error("請選擇供貨倉庫");
|
||||
return;
|
||||
}
|
||||
// 確認每個核准數量
|
||||
for (const item of approvedItems) {
|
||||
const qty = parseFloat(item.approved_qty);
|
||||
@@ -155,7 +158,6 @@ export default function Show({ requisition, warehouses }: Props) {
|
||||
router.post(
|
||||
route("store-requisitions.approve", [requisition.id]),
|
||||
{
|
||||
supply_warehouse_id: supplyWarehouseId,
|
||||
items: approvedItems.map((item) => ({
|
||||
id: item.id,
|
||||
approved_qty: parseFloat(item.approved_qty),
|
||||
@@ -196,6 +198,20 @@ export default function Show({ requisition, warehouses }: Props) {
|
||||
|
||||
const isEditable = ["draft", "rejected"].includes(requisition.status);
|
||||
const isPending = requisition.status === "pending";
|
||||
const canApprove = usePermission().can("store_requisitions.approve");
|
||||
|
||||
const handleUpdateSupplyWarehouse = (warehouseId: string) => {
|
||||
setSubmitting(true);
|
||||
router.patch(
|
||||
route("store-requisitions.update-supply-warehouse", [requisition.id]),
|
||||
{ supply_warehouse_id: warehouseId },
|
||||
{
|
||||
onFinish: () => setSubmitting(false),
|
||||
onSuccess: () => toast.success("供貨倉庫已更新"),
|
||||
preserveScroll: true,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout
|
||||
@@ -294,9 +310,27 @@ export default function Show({ requisition, warehouses }: Props) {
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-sm text-gray-500">供貨倉庫</span>
|
||||
<p className="font-medium text-gray-800 mt-1">
|
||||
{requisition.supply_warehouse_name || "-"}
|
||||
</p>
|
||||
<div className="mt-1">
|
||||
{isPending && canApprove ? (
|
||||
<SearchableSelect
|
||||
value={requisition.supply_warehouse_id?.toString() || ""}
|
||||
onValueChange={handleUpdateSupplyWarehouse}
|
||||
options={warehouses
|
||||
.filter((w) => w.id !== requisition.store_warehouse_id)
|
||||
.map((w) => ({
|
||||
label: w.name,
|
||||
value: w.id.toString(),
|
||||
}))}
|
||||
placeholder="選擇供貨倉庫"
|
||||
className="h-9 w-full max-w-[200px]"
|
||||
disabled={submitting}
|
||||
/>
|
||||
) : (
|
||||
<p className="font-medium text-gray-800">
|
||||
{requisition.supply_warehouse_name || "-"}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-sm text-gray-500">申請人</span>
|
||||
@@ -455,22 +489,14 @@ export default function Show({ requisition, warehouses }: Props) {
|
||||
<DialogDescription>選擇供貨倉庫,並確認各商品的核准數量。</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4 py-2">
|
||||
<div className="space-y-2">
|
||||
<Label>
|
||||
供貨倉庫 <span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<SearchableSelect
|
||||
value={supplyWarehouseId}
|
||||
onValueChange={setSupplyWarehouseId}
|
||||
options={warehouses
|
||||
.filter((w) => w.id !== requisition.store_warehouse_id)
|
||||
.map((w) => ({
|
||||
label: w.name,
|
||||
value: w.id.toString(),
|
||||
}))}
|
||||
placeholder="請選擇供貨倉庫"
|
||||
className="h-9"
|
||||
/>
|
||||
<div className="flex items-center justify-between p-3 bg-blue-50 border border-blue-100 rounded-lg">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-blue-700 font-medium">供貨倉庫:</span>
|
||||
<span className="text-blue-900 font-bold">{requisition.supply_warehouse_name || "尚未選擇"}</span>
|
||||
</div>
|
||||
{!requisition.supply_warehouse_id && (
|
||||
<span className="text-xs text-red-500 font-medium">* 請先在基本資訊中選擇供貨倉庫</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="border rounded-lg overflow-hidden">
|
||||
@@ -534,7 +560,7 @@ export default function Show({ requisition, warehouses }: Props) {
|
||||
<Button
|
||||
className="bg-green-600 hover:bg-green-700 text-white"
|
||||
onClick={handleApprove}
|
||||
disabled={approving || !supplyWarehouseId}
|
||||
disabled={approving || !requisition.supply_warehouse_id}
|
||||
>
|
||||
{approving && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
確認核准
|
||||
|
||||
Reference in New Issue
Block a user