diff --git a/app/build.gradle b/app/build.gradle index 6f8ad82..f78d58e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ plugins { // 避免不同尺寸機台間版本號產生衝突。 // ========================================================================= def verMinor = 1 -def verPatch = 94 +def verPatch = 96 diff --git a/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java b/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java index af93964..536b8d2 100644 --- a/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java +++ b/app/src/main/java/com/unibuy/smartdevice/tools/TransactionFinalizeBuilder.java @@ -47,6 +47,14 @@ public class TransactionFinalizeBuilder { /** 累積的出貨結果清單 */ private final List dispenseRecords = new ArrayList<>(); + /** + * 商品明細快照。在「buyList 仍完整」時擷取(例如進入出貨流程當下); + * 之後 build() 會優先採用此快照,不再即時讀 live buyList。 + * 用以修正掃碼支付(玉山)等較慢流程:結案前 buyList 可能被取消/倒數路徑清空, + * 導致 order.items 變成空陣列(出現「無商品紀錄」),但出貨其實成功。 + */ + private List itemsSnapshot = null; + private String codeId = "0"; /** 交易生命週期狀態(pending/completed/failed/abandoned);預設 completed 維持成功路徑原行為。 */ @@ -151,6 +159,42 @@ public class TransactionFinalizeBuilder { } + /** + * 擷取目前 buyList 的商品明細快照。 + * 應在「buyList 仍完整」時呼叫(例如 DispatchDialog 進入出貨流程當下); + * 之後 {@link #build()} 會優先採用此快照,不再即時讀 live buyList, + * 避免結案前 buyList 被取消/倒數等其他執行緒清空,導致 order.items 變成空陣列。 + * buyList 為空時不覆寫既有快照(避免把有效快照洗成空)。 + */ + public void captureItems() { + List buyList = MyApp.getInstance().getBuyList(); + if (buyList == null || buyList.isEmpty()) { + return; + } + this.itemsSnapshot = buildItemRecords(buyList); + Log.i(TAG, "captureItems: snapshot " + this.itemsSnapshot.size() + + " item(s), flow_id=" + flowId); + } + + /** 由 buyList 組出 items 明細(captureItems 與 build() fallback 共用)。 */ + private List buildItemRecords(List buyList) { + List items = new ArrayList<>(); + if (buyList != null) { + for (BuyStructure buy : buyList) { + int productId = 0; + try { + productId = Integer.parseInt(buy.getProduct().getProductID()); + } catch (NumberFormatException e) { + Log.w(TAG, "Cannot parse productID to int: " + buy.getProduct().getProductID()); + } + int price = buy.getProduct().getRealPrice(); + int quantity = buy.getCount() > 0 ? buy.getCount() : 1; + items.add(new TransactionFinalizePayload.ItemRecord(productId, price, quantity)); + } + } + return items; + } + /** * 加入一筆出貨結果記錄(每個貨道出貨後呼叫一次)。 * @@ -309,20 +353,13 @@ public class TransactionFinalizeBuilder { order.setMachine_time(orderMachineTime); // --- 組裝購買商品清單 (items) --- - List items = new ArrayList<>(); - List buyList = MyApp.getInstance().getBuyList(); - if (buyList != null) { - for (BuyStructure buy : buyList) { - int productId = 0; - try { - productId = Integer.parseInt(buy.getProduct().getProductID()); - } catch (NumberFormatException e) { - Log.w(TAG, "Cannot parse productID to int: " + buy.getProduct().getProductID()); - } - int price = buy.getProduct().getRealPrice(); - int quantity = buy.getCount() > 0 ? buy.getCount() : 1; - items.add(new TransactionFinalizePayload.ItemRecord(productId, price, quantity)); - } + // 優先採用 captureItems() 在出貨流程開始時擷取的快照;無快照時才即時讀 live buyList。 + // 快照可避免結案前 buyList 被其他執行緒清空(掃碼支付等慢流程的競態),造成「無商品紀錄」。 + List items; + if (itemsSnapshot != null && !itemsSnapshot.isEmpty()) { + items = new ArrayList<>(itemsSnapshot); + } else { + items = buildItemRecords(MyApp.getInstance().getBuyList()); } order.setItems(items); diff --git a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java index 6ddb946..f621596 100644 --- a/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java +++ b/app/src/main/java/com/unibuy/smartdevice/ui/dialog/DispatchDialog.java @@ -258,6 +258,10 @@ public class DispatchDialog extends DialogAbstract { httpAPI = new HttpAPI(getHandlerMain()); // 初始化 Finalize Builder(在支付完成、進入出貨流程時建立) finalizeBuilder = new TransactionFinalizeBuilder(); + // 進入出貨流程當下 buyList 必為完整(下方即用它組 dispatchList),先擷取商品明細快照。 + // 之後結案 build() 會優先採用此快照,避免掃碼支付(玉山)等慢流程在結案前 buyList + // 被取消/倒數路徑清空,導致 order.items 變空(無商品紀錄)但出貨其實成功。 + finalizeBuilder.captureItems(); if (com.unibuy.smartdevice.AppEntry.isCmuh()) { MyApp.getInstance().getReportFlowInfoData().setFlowType(42); }