[FIX] 實作半途出貨失敗的 MQTT Finalize 結案回報機制

1. 遞增 app/build.gradle 修補版本號為 1.31。
2. 於 TransactionFinalizePayload 新增 delivery_status 出貨狀態欄位(0=失敗, 1=成功, 2=部分失敗)。
3. 於 TransactionFinalizeBuilder 實作自動計算出貨狀態與建構回報的邏輯。
4. 於 DispatchDialog 實作 finalizeFailedDispatch 機制,當多筆商品出貨至半途失敗時,自動將剩餘未出貨的商品標記為失敗並上報 MQTT Finalize 結案。
This commit is contained in:
sky121113 2026-05-29 12:17:42 +08:00
parent 47acd44e61
commit b2b6776665
4 changed files with 99 additions and 1 deletions

View File

@ -9,7 +9,7 @@ plugins {
//
// =========================================================================
def verMinor = 1
def verPatch = 30
def verPatch = 31
android {

View File

@ -119,6 +119,11 @@ public class TransactionFinalizePayload {
*/
private int payment_status;
/**
* 訂單出貨狀態0 = 全部失敗, 1 = 全部成功, 2 = 部分失敗
*/
private int delivery_status;
/** 支付 Request 原始內容 (JSON String) */
private String payment_request;
@ -210,6 +215,14 @@ public class TransactionFinalizePayload {
this.payment_status = payment_status;
}
public int getDelivery_status() {
return delivery_status;
}
public void setDelivery_status(int delivery_status) {
this.delivery_status = delivery_status;
}
public String getPayment_request() {
return payment_request;
}

View File

@ -29,6 +29,9 @@ public class TransactionFinalizeBuilder {
private static final String TAG = "TransactionFinalizeBuilder";
private static final SimpleDateFormat SDF =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
private static final int ORDER_STATUS_FAILED = 0;
private static final int ORDER_STATUS_SUCCESS = 1;
private static final int ORDER_STATUS_PARTIAL_FAILED = 2;
/** 訂單建立時間(支付完成時的時間點) */
private final String orderMachineTime;
@ -116,6 +119,7 @@ public class TransactionFinalizeBuilder {
// --- 組裝 order ---
TransactionFinalizePayload.OrderPayload order = buildOrderPayload(flowInfo);
order.setDelivery_status(calculateOrderStatus());
payload.setOrder(order);
// --- 出貨記錄 ---
@ -128,6 +132,27 @@ public class TransactionFinalizeBuilder {
return payload;
}
private int calculateOrderStatus() {
boolean hasSuccess = false;
boolean hasFailed = false;
for (TransactionFinalizePayload.DispenseRecord record : dispenseRecords) {
if (record.getDispense_status() == 1) {
hasSuccess = true;
} else {
hasFailed = true;
}
}
if (hasSuccess && hasFailed) {
return ORDER_STATUS_PARTIAL_FAILED;
}
if (hasSuccess) {
return ORDER_STATUS_SUCCESS;
}
return ORDER_STATUS_FAILED;
}
/**
* MyApp 的全域狀態組裝 OrderPayload
*/

View File

@ -196,6 +196,7 @@ public class DispatchDialog extends DialogAbstract {
for (String logItem : deliveryLogs) {
getLogs().info(logItem);
}
finalizeFailedDispatch(message);
new Handler().postDelayed(() -> {
Context ctx = getContext();
@ -955,6 +956,65 @@ public class DispatchDialog extends DialogAbstract {
isGetProductByVMC = false; // 解鎖出貨成功判定
}
private void finalizeFailedDispatch(String message) {
if (isFinalizing) {
return;
}
isFinalizing = true;
if (finalizeBuilder == null) {
getLogs().info("finalizeBuilder is null, cannot publish failed dispatch finalize: " + message);
return;
}
addFailedDispenseRecordsFromCurrent();
if ("Cmuh".equalsIgnoreCase(com.unibuy.smartdevice.BuildConfig.FLAVOR_project)) {
insertDrgnoToMemo();
}
getLogs().info("出貨失敗,發送 MQTT Finalize 結案訊息: " + message);
MqttManager.getInstance().publishTransactionFinalize(finalizeBuilder.build());
getSrcHandlerMain().send(getClass().getSimpleName(), FontendActivity.Option.RESET_DATA.getOption(), "update data");
saveData();
}
private void addFailedDispenseRecordsFromCurrent() {
if (dispatchList == null || dispatchList.isEmpty()) {
return;
}
int startIndex = Math.max(0, dispatchIndex);
for (int i = startIndex; i < dispatchList.size(); i++) {
DispatchStructure dispatch = dispatchList.get(i);
int failedQuantity = dispatch.getQuantity() - dispatch.getCount();
if (failedQuantity <= 0) {
continue;
}
ProductStructure product = dispatch.getProduct();
int productId = 0;
try {
productId = Integer.parseInt(product.getProductID());
} catch (Exception ignored) {
}
int remaining = 0;
try {
remaining = MyApp.getInstance().getSlotData(dispatch.getField(), dispatch.getSlot()).getCount();
} catch (LogsEmptyException e) {
getLogs().warning(e);
}
int amount = product.getRealPrice() * failedQuantity;
finalizeBuilder.addDispenseRecord(dispatch.getSlot(), productId, amount, 0, false, remaining);
getLogs().info("[Finalize] 已累積出貨失敗記錄: slot=" + dispatch.getSlot()
+ ", product=" + productId
+ ", failedQuantity=" + failedQuantity
+ ", remaining=" + remaining);
}
}
private void deliverylot(int msgflag){
String productId = dispatchList.get(dispatchIndex).getProduct().getProductID();