From fae5d288f756af86435f66e9e0a2b8c054829b50 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Wed, 3 Jun 2026 13:18:16 +0700 Subject: [PATCH] Return explicit errors for unsupported POS workflows --- .../src/app/api/bff/[...path]/route.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/microservices/apps/tpos-mvp-next/src/app/api/bff/[...path]/route.ts b/microservices/apps/tpos-mvp-next/src/app/api/bff/[...path]/route.ts index 9eef3b02..40923b21 100644 --- a/microservices/apps/tpos-mvp-next/src/app/api/bff/[...path]/route.ts +++ b/microservices/apps/tpos-mvp-next/src/app/api/bff/[...path]/route.ts @@ -30,6 +30,7 @@ import { inventoryAdjust, listInventoryItems, listInventoryWithTransactions, + recordWastage, stockIn, stocktake as stocktakeInventory, stockOut, @@ -337,6 +338,40 @@ function unsupportedPaymentAdapter(method: unknown) { return !["cash", "customer_order", "kitchen_order", "room_fnb"].includes(normalized); } +function statusForServiceError(error: unknown) { + const message = error instanceof Error ? error.message : "BFF request failed"; + if (/not configured|requires persisted|requires a configured/i.test(message)) return 501; + if (/insufficient inventory|insufficient stock/i.test(message)) return 409; + if (/not found/i.test(message)) return 404; + return 400; +} + +function unsupportedWorkflow(path: string[]) { + const key = path.join("/"); + const unsupported = new Map([ + ["inventory/stock-transfer", "Stock transfer requires multi-location inventory ledger support before it can be executed."], + ["orders/split-bill", "Split bill requires persisted split payment ledger support before it can be executed."], + ["orders/cash-drawer", "Cash drawer requires persisted cash session ledger support before it can be executed."], + ["orders/tip", "Tip requires persisted gratuity ledger support before it can be executed."], + ["orders/refund", "Refund requires persisted refund ledger support before it can be executed."], + ["orders/void", "Void requires persisted refund/void ledger support before it can be executed."], + ["pos/stock-transfer", "Stock transfer requires multi-location inventory ledger support before it can be executed."], + ["pos/split-bill", "Split bill requires persisted split payment ledger support before it can be executed."], + ["pos/cash-drawer", "Cash drawer requires persisted cash session ledger support before it can be executed."], + ["pos/tip", "Tip requires persisted gratuity ledger support before it can be executed."], + ["pos/refund", "Refund requires persisted refund ledger support before it can be executed."], + ["pos/void", "Void requires persisted refund/void ledger support before it can be executed."] + ]); + if (unsupported.has(key)) return unsupported.get(key); + if (path[0] === "orders" && path[2] === "refund") return "Refund requires persisted refund ledger support before it can be executed."; + if (path[0] === "orders" && path[2] === "void") return "Void requires persisted refund/void ledger support before it can be executed."; + if (path[0] === "orders" && path[2] === "split-bill") return "Split bill requires persisted split payment ledger support before it can be executed."; + if (path[0] === "orders" && path[2] === "tip") return "Tip requires persisted gratuity ledger support before it can be executed."; + if (path[0] === "orders" && path[2] === "edit") return "Order edit requires persisted order revision support before it can be executed."; + if (path[0] === "orders" && path[2] === "receipt") return "Receipt rendering is read-only in MVP and must use GET order detail."; + return null; +} + function requiredShopId(value: unknown) { const shopId = stringValue(value); return shopId ? { shopId } : { error: fail("shopId is required", { status: 400 }) };