@pisell/pisellos 0.10.2 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/core/index.d.ts +2 -0
  2. package/dist/core/index.js +7 -0
  3. package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
  4. package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
  5. package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
  6. package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
  7. package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
  8. package/dist/model/strategy/adapter/promotion/examples.js +99 -0
  9. package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
  10. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  11. package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
  12. package/dist/model/strategy/adapter/promotion/type.js +45 -0
  13. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -3
  14. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +6 -3
  15. package/dist/modules/OpenData/index.d.ts +2 -0
  16. package/dist/modules/OpenData/index.js +8 -0
  17. package/dist/modules/Order/index.d.ts +28 -8
  18. package/dist/modules/Order/index.js +818 -503
  19. package/dist/modules/Order/payment-utils.d.ts +26 -0
  20. package/dist/modules/Order/payment-utils.js +225 -0
  21. package/dist/modules/Order/types.d.ts +35 -1
  22. package/dist/modules/Order/utils/orderCollectionIdentity.js +7 -2
  23. package/dist/modules/Order/utils.js +10 -6
  24. package/dist/modules/Payment/index.d.ts +2 -0
  25. package/dist/modules/Payment/index.js +79 -50
  26. package/dist/modules/Payment/types.d.ts +107 -28
  27. package/dist/modules/Payment/types.js +20 -3
  28. package/dist/modules/Payment/walletpass.d.ts +38 -1
  29. package/dist/modules/Payment/walletpass.js +917 -114
  30. package/dist/modules/ProductList/index.js +1 -1
  31. package/dist/modules/Rules/index.d.ts +3 -0
  32. package/dist/modules/Rules/index.js +130 -99
  33. package/dist/server/index.d.ts +16 -0
  34. package/dist/server/index.js +2084 -1188
  35. package/dist/server/modules/index.d.ts +1 -1
  36. package/dist/server/modules/order/index.d.ts +70 -4
  37. package/dist/server/modules/order/index.js +1816 -728
  38. package/dist/server/modules/order/types.d.ts +25 -3
  39. package/dist/server/modules/order/types.js +7 -1
  40. package/dist/solution/BaseSales/index.d.ts +111 -13
  41. package/dist/solution/BaseSales/index.js +1799 -446
  42. package/dist/solution/BaseSales/types.d.ts +55 -1
  43. package/dist/solution/BaseSales/types.js +2 -1
  44. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
  45. package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
  46. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
  47. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -3
  48. package/dist/solution/BookingByStep/index.d.ts +1 -1
  49. package/dist/solution/BookingTicket/index.d.ts +7 -3
  50. package/dist/solution/BookingTicket/index.js +138 -52
  51. package/dist/solution/BookingTicket/types.d.ts +1 -0
  52. package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -0
  53. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
  54. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +173 -83
  55. package/dist/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
  56. package/dist/solution/BookingTicket/utils/weighingProductSku.js +45 -0
  57. package/dist/solution/Sales/index.d.ts +1 -0
  58. package/dist/solution/Sales/index.js +10 -2
  59. package/dist/solution/ScanOrder/index.js +31 -20
  60. package/dist/solution/UnifiedBookingSales/index.js +23 -3
  61. package/dist/solution/VenueBooking/index.d.ts +1 -0
  62. package/dist/solution/VenueBooking/index.js +34 -24
  63. package/dist/types/index.d.ts +1 -0
  64. package/dist/utils/payment-number.d.ts +9 -0
  65. package/dist/utils/payment-number.js +69 -0
  66. package/lib/core/index.d.ts +2 -0
  67. package/lib/core/index.js +4 -0
  68. package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
  69. package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
  70. package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
  71. package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
  72. package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
  73. package/lib/model/strategy/adapter/promotion/examples.js +91 -0
  74. package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
  75. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  76. package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
  77. package/lib/model/strategy/adapter/promotion/type.js +2 -0
  78. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
  79. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
  80. package/lib/modules/OpenData/index.d.ts +2 -0
  81. package/lib/modules/OpenData/index.js +5 -0
  82. package/lib/modules/Order/index.d.ts +28 -8
  83. package/lib/modules/Order/index.js +233 -68
  84. package/lib/modules/Order/payment-utils.d.ts +26 -0
  85. package/lib/modules/Order/payment-utils.js +224 -0
  86. package/lib/modules/Order/types.d.ts +35 -1
  87. package/lib/modules/Order/utils/orderCollectionIdentity.js +3 -0
  88. package/lib/modules/Order/utils.js +11 -4
  89. package/lib/modules/Payment/index.d.ts +2 -0
  90. package/lib/modules/Payment/index.js +34 -13
  91. package/lib/modules/Payment/types.d.ts +107 -28
  92. package/lib/modules/Payment/types.js +4 -3
  93. package/lib/modules/Payment/walletpass.d.ts +38 -1
  94. package/lib/modules/Payment/walletpass.js +730 -21
  95. package/lib/modules/ProductList/index.js +9 -1
  96. package/lib/modules/Rules/index.d.ts +3 -0
  97. package/lib/modules/Rules/index.js +39 -10
  98. package/lib/server/index.d.ts +16 -0
  99. package/lib/server/index.js +677 -28
  100. package/lib/server/modules/index.d.ts +1 -1
  101. package/lib/server/modules/order/index.d.ts +70 -4
  102. package/lib/server/modules/order/index.js +818 -69
  103. package/lib/server/modules/order/types.d.ts +25 -3
  104. package/lib/server/modules/order/types.js +1 -0
  105. package/lib/solution/BaseSales/index.d.ts +111 -13
  106. package/lib/solution/BaseSales/index.js +882 -46
  107. package/lib/solution/BaseSales/types.d.ts +55 -1
  108. package/lib/solution/BaseSales/types.js +2 -1
  109. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
  110. package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
  111. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
  112. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
  113. package/lib/solution/BookingByStep/index.d.ts +1 -1
  114. package/lib/solution/BookingTicket/index.d.ts +7 -3
  115. package/lib/solution/BookingTicket/index.js +63 -9
  116. package/lib/solution/BookingTicket/types.d.ts +1 -0
  117. package/lib/solution/BookingTicket/utils/addProductDecision.js +4 -0
  118. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.d.ts +8 -0
  119. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +37 -5
  120. package/lib/solution/BookingTicket/utils/weighingProductSku.d.ts +5 -0
  121. package/lib/solution/BookingTicket/utils/weighingProductSku.js +63 -0
  122. package/lib/solution/Sales/index.d.ts +1 -0
  123. package/lib/solution/Sales/index.js +5 -3
  124. package/lib/solution/ScanOrder/index.js +8 -0
  125. package/lib/solution/UnifiedBookingSales/index.js +10 -2
  126. package/lib/solution/VenueBooking/index.d.ts +1 -0
  127. package/lib/solution/VenueBooking/index.js +13 -6
  128. package/lib/types/index.d.ts +1 -0
  129. package/lib/utils/payment-number.d.ts +9 -0
  130. package/lib/utils/payment-number.js +64 -0
  131. package/package.json +1 -1
@@ -34,6 +34,8 @@ __export(server_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(server_exports);
36
36
  var import_dayjs = __toESM(require("dayjs"));
37
+ var import_decimal = __toESM(require("decimal.js"));
38
+ var import_lodash_es = require("lodash-es");
37
39
  var import_products = require("./modules/products");
38
40
  var import_menu = require("./modules/menu");
39
41
  var import_quotation = require("./modules/quotation");
@@ -50,6 +52,8 @@ var import_types3 = require("./modules/order/types");
50
52
  var import_filterOrders = require("./modules/order/utils/filterOrders");
51
53
  var import_filterBookings = require("./modules/order/utils/filterBookings");
52
54
  var import_small_ticket = require("./utils/small-ticket");
55
+ var import_BaseSales = require("../solution/BaseSales");
56
+ var import_payment_utils = require("../modules/Order/payment-utils");
53
57
  __reExport(server_exports, require("./modules"), module.exports);
54
58
  var PRODUCT_TITLE_SNAPSHOT_KEYS = [
55
59
  "en",
@@ -91,6 +95,7 @@ var Server = class {
91
95
  this.BOOKING_REMOTE_CACHE_MAX_ENTRIES = 80;
92
96
  this.salesSearchSubscribers = /* @__PURE__ */ new Map();
93
97
  this.deviceTaskActionsRegistered = false;
98
+ this.localPaymentUpdateQueues = /* @__PURE__ */ new Map();
94
99
  this.floorPlanQuerySubscribers = /* @__PURE__ */ new Map();
95
100
  // 模块注册表 - 定义所有可用的模块配置
96
101
  this.moduleRegistry = {
@@ -583,6 +588,128 @@ var Server = class {
583
588
  title: "handleOrderSalesCheckout"
584
589
  });
585
590
  };
591
+ this.handleOrderSalesDraft = async ({ data }) => {
592
+ return this.handleOrderDraftSubmit({
593
+ data,
594
+ title: "handleOrderSalesDraft"
595
+ });
596
+ };
597
+ this.handleGetLocalPayment = async ({ data }) => {
598
+ const saleId = data == null ? void 0 : data.sale_id;
599
+ const paymentNumber = data == null ? void 0 : data.payment_number;
600
+ const operationId = this.createLocalPaymentOperationId("get");
601
+ const requestContext = {
602
+ operation_id: operationId,
603
+ sale_id: saleId ?? null,
604
+ payment_number: paymentNumber ?? null
605
+ };
606
+ this.logInfo("handleGetLocalPayment: 请求进入", requestContext);
607
+ if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "") {
608
+ this.logWarning("handleGetLocalPayment: 参数校验失败", {
609
+ ...requestContext,
610
+ missing_fields: [
611
+ ...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
612
+ ...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : []
613
+ ]
614
+ });
615
+ return {
616
+ code: 400,
617
+ status: false,
618
+ message: "sale_id 和 payment_number 必填",
619
+ data: null
620
+ };
621
+ }
622
+ if (!this.order) {
623
+ this.logError("handleGetLocalPayment: Order 模块未注册", requestContext);
624
+ return { code: 500, status: false, message: "Order 模块未注册", data: null };
625
+ }
626
+ const startedAt = Date.now();
627
+ try {
628
+ this.logInfo("handleGetLocalPayment: 开始查询本地支付项", requestContext);
629
+ const found = await this.order.getLocalPayment({
630
+ saleId,
631
+ paymentNumber,
632
+ operationId
633
+ });
634
+ if (!found) {
635
+ this.logWarning("handleGetLocalPayment: 本地支付项不存在", {
636
+ ...requestContext,
637
+ duration_ms: Date.now() - startedAt
638
+ });
639
+ return { code: 404, status: false, message: "本地支付项不存在", data: null };
640
+ }
641
+ this.logInfo("handleGetLocalPayment: 查询命中", {
642
+ ...requestContext,
643
+ duration_ms: Date.now() - startedAt,
644
+ matched_by: found.matchedBy,
645
+ payment_index: found.paymentIndex,
646
+ ...this.buildLocalPaymentOrderLogContext(found.order),
647
+ payment: found.payment
648
+ });
649
+ return { code: 200, status: true, message: "", data: found.payment };
650
+ } catch (error) {
651
+ this.logError("handleGetLocalPayment: 查询异常", {
652
+ ...requestContext,
653
+ duration_ms: Date.now() - startedAt,
654
+ error: error instanceof Error ? error.message : String(error),
655
+ error_detail: this.normalizeUnknownError(error)
656
+ });
657
+ throw error;
658
+ }
659
+ };
660
+ this.handleUpdateLocalPayment = async ({ data }) => {
661
+ const saleId = data == null ? void 0 : data.sale_id;
662
+ const paymentNumber = data == null ? void 0 : data.payment_number;
663
+ const number = data == null ? void 0 : data.number;
664
+ const status = data == null ? void 0 : data.status;
665
+ const serviceCharge = data == null ? void 0 : data.service_charge;
666
+ const cardReaderSurcharge = data == null ? void 0 : data.card_reader_surcharge;
667
+ const hasSurchargeInput = serviceCharge !== void 0 || cardReaderSurcharge !== void 0;
668
+ const invalidSurchargeFields = this.getInvalidLocalPaymentSurchargeFields(
669
+ serviceCharge,
670
+ cardReaderSurcharge
671
+ );
672
+ const operationId = this.createLocalPaymentOperationId("update");
673
+ const requestContext = {
674
+ operation_id: operationId,
675
+ sale_id: saleId ?? null,
676
+ payment_number: paymentNumber ?? null,
677
+ transaction_number: number ?? null,
678
+ requested_status: status ?? null,
679
+ service_charge: serviceCharge ?? null,
680
+ card_reader_surcharge: cardReaderSurcharge ?? null
681
+ };
682
+ this.logInfo("handleUpdateLocalPayment: 请求进入", requestContext);
683
+ if (saleId === void 0 || saleId === null || saleId === "" || paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" || number === void 0 || number === null || number === "" || status !== "success" && status !== "fail" || invalidSurchargeFields.length > 0) {
684
+ this.logWarning("handleUpdateLocalPayment: 参数校验失败", {
685
+ ...requestContext,
686
+ missing_or_invalid_fields: [
687
+ ...saleId === void 0 || saleId === null || saleId === "" ? ["sale_id"] : [],
688
+ ...paymentNumber === void 0 || paymentNumber === null || paymentNumber === "" ? ["payment_number"] : [],
689
+ ...number === void 0 || number === null || number === "" ? ["number"] : [],
690
+ ...status !== "success" && status !== "fail" ? ["status"] : [],
691
+ ...invalidSurchargeFields
692
+ ]
693
+ });
694
+ return {
695
+ code: 400,
696
+ status: false,
697
+ message: invalidSurchargeFields.length > 0 ? `手续费参数非法: ${invalidSurchargeFields.join(", ")}` : "sale_id、payment_number、number 必填,status 仅支持 success/fail",
698
+ data: null
699
+ };
700
+ }
701
+ const queueKey = `${String(saleId)}:${String(paymentNumber)}`;
702
+ return this.runLocalPaymentUpdateInQueue(queueKey, () => this.processLocalPaymentUpdate({
703
+ operationId,
704
+ saleId,
705
+ paymentNumber,
706
+ number: String(number),
707
+ status,
708
+ serviceCharge,
709
+ cardReaderSurcharge,
710
+ hasSurchargeInput
711
+ }), requestContext);
712
+ };
586
713
  this.handleOrderCheckout = async ({ data }) => {
587
714
  return this.handleOrderCheckoutSubmit({
588
715
  backendPath: "/order/checkout",
@@ -1364,7 +1491,7 @@ var Server = class {
1364
1491
  const { backendPath, title } = params;
1365
1492
  const normalizedData = await this.normalizeCheckoutSubmitData(params.data, title);
1366
1493
  const checkoutData = await this.ensureCheckoutOrderNumbers(normalizedData, title);
1367
- const remoteCheckoutData = this.omitCheckoutSyncMode(checkoutData);
1494
+ const remoteCheckoutData = this.buildRemoteCheckoutData(checkoutData, title);
1368
1495
  if (!((_b = (_a = this.app) == null ? void 0 : _a.request) == null ? void 0 : _b.post)) {
1369
1496
  throw new Error("app.request 不可用");
1370
1497
  }
@@ -1380,20 +1507,20 @@ var Server = class {
1380
1507
  errorResponse: response,
1381
1508
  response,
1382
1509
  normalizedResponse: this.normalizeCheckoutResponse(response),
1383
- checkoutData: remoteCheckoutData
1510
+ checkoutData
1384
1511
  };
1385
1512
  }
1386
1513
  const fresh = this.extractOrderDataFromCheckoutResponse(response);
1387
1514
  const externalSaleNumber = this.getCheckoutExternalSaleNumber(
1388
- remoteCheckoutData,
1515
+ checkoutData,
1389
1516
  {
1390
1517
  external_sale_number: params.externalSaleNumber,
1391
- data: remoteCheckoutData
1518
+ data: checkoutData
1392
1519
  }
1393
1520
  );
1394
1521
  const syncedOrder = await this.persistSyncedCheckoutOrder({
1395
1522
  backendPath,
1396
- checkoutData: remoteCheckoutData,
1523
+ checkoutData,
1397
1524
  externalSaleNumber,
1398
1525
  fresh,
1399
1526
  title,
@@ -1404,11 +1531,11 @@ var Server = class {
1404
1531
  checkoutResponseOrder: fresh
1405
1532
  }) : void 0;
1406
1533
  if (printableSyncedOrder && this.shouldPrintSyncedOrder({
1407
- checkoutData: remoteCheckoutData,
1534
+ checkoutData,
1408
1535
  syncedOrder: printableSyncedOrder
1409
1536
  })) {
1410
1537
  await this.dispatchPrintOtherReceiptTask({
1411
- checkoutData: remoteCheckoutData,
1538
+ checkoutData,
1412
1539
  syncedOrder: printableSyncedOrder,
1413
1540
  response,
1414
1541
  deviceId: params.deviceId
@@ -1418,7 +1545,7 @@ var Server = class {
1418
1545
  rejected: false,
1419
1546
  response,
1420
1547
  normalizedResponse: this.normalizeCheckoutResponse(response),
1421
- checkoutData: remoteCheckoutData,
1548
+ checkoutData,
1422
1549
  syncedOrder,
1423
1550
  fresh
1424
1551
  };
@@ -1431,6 +1558,54 @@ var Server = class {
1431
1558
  delete next.syncMode;
1432
1559
  return next;
1433
1560
  }
1561
+ buildRemoteCheckoutData(data, title) {
1562
+ const next = (0, import_lodash_es.cloneDeep)(this.omitCheckoutSyncMode(data));
1563
+ if (!next || typeof next !== "object")
1564
+ return next;
1565
+ const record = next;
1566
+ if (!Array.isArray(record.payments))
1567
+ return next;
1568
+ const originalPayments = record.payments;
1569
+ const filteredPayments = originalPayments.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
1570
+ const removedPayments = originalPayments.filter((payment) => (0, import_payment_utils.isPendingOrderPayment)(payment));
1571
+ record.payments = filteredPayments;
1572
+ this.logInfo(`${title}: checkout 云端支付项已过滤`, {
1573
+ external_sale_number: record.external_sale_number,
1574
+ original_payment_count: originalPayments.length,
1575
+ remote_payment_count: filteredPayments.length,
1576
+ filtered_pending_count: removedPayments.length,
1577
+ filtered_payment_identities: removedPayments.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1578
+ });
1579
+ return next;
1580
+ }
1581
+ mergeCheckoutSyncPayments(checkoutData, fresh, title) {
1582
+ const localPayments = Array.isArray(checkoutData == null ? void 0 : checkoutData.payments) ? checkoutData.payments : [];
1583
+ const freshRecord = fresh;
1584
+ if (!Array.isArray(freshRecord.payments)) {
1585
+ return localPayments.length > 0 ? { ...freshRecord, payments: (0, import_lodash_es.cloneDeep)(localPayments) } : freshRecord;
1586
+ }
1587
+ const freshPayments = freshRecord.payments;
1588
+ const mergedPayments = (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
1589
+ localPayments,
1590
+ freshPayments,
1591
+ { preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
1592
+ );
1593
+ const remoteIdentityKeys = new Set(
1594
+ freshPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1595
+ );
1596
+ const preservedPending = localPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => remoteIdentityKeys.has(key)));
1597
+ if (preservedPending.length > 0) {
1598
+ this.logInfo(`${title}: checkout 响应合并保留本地 pending 支付项`, {
1599
+ external_sale_number: checkoutData == null ? void 0 : checkoutData.external_sale_number,
1600
+ preserved_pending_count: preservedPending.length,
1601
+ preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1602
+ });
1603
+ }
1604
+ return {
1605
+ ...freshRecord,
1606
+ payments: mergedPayments
1607
+ };
1608
+ }
1434
1609
  async persistSyncedCheckoutOrder(params) {
1435
1610
  const {
1436
1611
  backendPath,
@@ -1445,15 +1620,17 @@ var Server = class {
1445
1620
  if (this.order && fresh && (shouldMergeRemoteOrder || persistCheckoutDataWithResponse)) {
1446
1621
  syncedOrder = persistCheckoutDataWithResponse ? {
1447
1622
  ...checkoutData,
1448
- ...fresh,
1623
+ ...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
1449
1624
  external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
1450
- need_sync: 0
1625
+ need_sync: 0,
1626
+ is_draft_order: 0
1451
1627
  } : {
1452
- ...fresh,
1628
+ ...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
1453
1629
  external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
1454
- need_sync: 0
1630
+ need_sync: 0,
1631
+ is_draft_order: 0
1455
1632
  };
1456
- await this.order.upsertOrdersFromRemote([syncedOrder]);
1633
+ await this.order.upsertOrdersFromRemote([syncedOrder], "checkoutSync");
1457
1634
  this.logInfo(`${title}: sync_sales 完整订单已同步到本地`, {
1458
1635
  order_id: fresh.order_id,
1459
1636
  external_sale_number: syncedOrder.external_sale_number,
@@ -1471,7 +1648,8 @@ var Server = class {
1471
1648
  ...checkoutData,
1472
1649
  ...patch,
1473
1650
  external_sale_number: externalSaleNumber,
1474
- need_sync: 0
1651
+ need_sync: 0,
1652
+ is_draft_order: 0
1475
1653
  };
1476
1654
  this.logInfo(`${title}: sync_sales 已按 external_sale_number 标记本地订单`, {
1477
1655
  order_id: (syncedOrder == null ? void 0 : syncedOrder.order_id) ?? null,
@@ -1851,6 +2029,11 @@ var Server = class {
1851
2029
  path: "/shop/order/sales/checkout",
1852
2030
  handler: this.handleOrderSalesCheckout.bind(this)
1853
2031
  },
2032
+ {
2033
+ method: "post",
2034
+ path: "/shop/order/sales/draft",
2035
+ handler: this.handleOrderSalesDraft.bind(this)
2036
+ },
1854
2037
  {
1855
2038
  method: "post",
1856
2039
  path: "/order/checkout",
@@ -1861,6 +2044,16 @@ var Server = class {
1861
2044
  path: "/shop/local/print-order",
1862
2045
  handler: this.handleLocalPrintOrder.bind(this)
1863
2046
  },
2047
+ {
2048
+ method: "post",
2049
+ path: "/shop/local/getLocalPayment",
2050
+ handler: this.handleGetLocalPayment.bind(this)
2051
+ },
2052
+ {
2053
+ method: "post",
2054
+ path: "/shop/local/updateLocalPayment",
2055
+ handler: this.handleUpdateLocalPayment.bind(this)
2056
+ },
1864
2057
  {
1865
2058
  method: "post",
1866
2059
  path: "/shop/machinecode/batch",
@@ -2026,15 +2219,12 @@ var Server = class {
2026
2219
  return;
2027
2220
  const scheduleDate = subscriber.context.schedule_date || (0, import_dayjs.default)().format("YYYY-MM-DD");
2028
2221
  const timerIds = [];
2029
- for (const timePoint of timePoints) {
2030
- const delayMs = this.computeScheduleTimePointDelayMs(scheduleDate, timePoint);
2031
- if (delayMs < 0)
2032
- continue;
2033
- const timerId = setTimeout(() => {
2034
- void this.onScheduleTimePointTimerFire(subscriberId, timerId);
2035
- }, delayMs);
2036
- timerIds.push(timerId);
2037
- }
2222
+ setInterval(() => {
2223
+ const currentTime = (0, import_dayjs.default)().format("hh:mm");
2224
+ if (timePoints.includes(currentTime)) {
2225
+ this.onScheduleTimePointTimerFire(subscriberId);
2226
+ }
2227
+ }, 6e4);
2038
2228
  if (timerIds.length > 0) {
2039
2229
  this.productQueryScheduleTimers.set(subscriberId, timerIds);
2040
2230
  subscriber.scheduleTimerIds = timerIds;
@@ -2049,7 +2239,7 @@ var Server = class {
2049
2239
  * schedule 变价时间点定时器触发:刷新 schedule_datetime 后重算并 callback。
2050
2240
  */
2051
2241
  async onScheduleTimePointTimerFire(subscriberId, timerId) {
2052
- this.removeScheduleTimerRef(subscriberId, timerId);
2242
+ timerId && this.removeScheduleTimerRef(subscriberId, timerId);
2053
2243
  if (!this.productQuerySubscribers.has(subscriberId))
2054
2244
  return;
2055
2245
  const subscriber = this.productQuerySubscribers.get(subscriberId);
@@ -2739,6 +2929,405 @@ var Server = class {
2739
2929
  };
2740
2930
  }
2741
2931
  }
2932
+ createLocalPaymentOperationId(action) {
2933
+ return `local_payment_${action}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
2934
+ }
2935
+ buildLocalPaymentOrderLogContext(order) {
2936
+ if (!order)
2937
+ return {};
2938
+ return {
2939
+ order_id: order.order_id ?? null,
2940
+ external_sale_number: order.external_sale_number ?? null,
2941
+ order_number: order.order_number ?? null,
2942
+ shop_order_number: order.shop_order_number ?? null,
2943
+ shop_full_order_number: order.shop_full_order_number ?? null,
2944
+ order_status: order.status ?? null,
2945
+ payment_status: order.payment_status ?? null,
2946
+ is_draft_order: Number(order.is_draft_order || 0),
2947
+ need_sync: Number(order.need_sync || 0),
2948
+ platform: order.platform ?? null,
2949
+ business_code: order.business_code ?? null,
2950
+ order_sales_channel: order.order_sales_channel ?? null,
2951
+ sales_channel: order.sales_channel ?? null,
2952
+ order_type: order.type ?? null,
2953
+ payments_count: Array.isArray(order.payments) ? order.payments.length : 0
2954
+ };
2955
+ }
2956
+ isValidLocalPaymentDecimal(value) {
2957
+ if (typeof value !== "string" && typeof value !== "number")
2958
+ return false;
2959
+ if (typeof value === "string" && value.trim() === "")
2960
+ return false;
2961
+ try {
2962
+ return new import_decimal.default(value).isFinite();
2963
+ } catch {
2964
+ return false;
2965
+ }
2966
+ }
2967
+ getInvalidLocalPaymentSurchargeFields(serviceCharge, cardReaderSurcharge) {
2968
+ const invalidFields = [];
2969
+ if (serviceCharge !== void 0) {
2970
+ if (serviceCharge === null || typeof serviceCharge !== "object" || Array.isArray(serviceCharge)) {
2971
+ invalidFields.push("service_charge");
2972
+ } else {
2973
+ const input = serviceCharge;
2974
+ if (input.fixed !== void 0 && !this.isValidLocalPaymentDecimal(input.fixed)) {
2975
+ invalidFields.push("service_charge.fixed");
2976
+ }
2977
+ if (input.percentage !== void 0 && !this.isValidLocalPaymentDecimal(input.percentage)) {
2978
+ invalidFields.push("service_charge.percentage");
2979
+ }
2980
+ }
2981
+ }
2982
+ if (cardReaderSurcharge !== void 0 && !this.isValidLocalPaymentDecimal(cardReaderSurcharge)) {
2983
+ invalidFields.push("card_reader_surcharge");
2984
+ }
2985
+ return invalidFields;
2986
+ }
2987
+ buildLocalPaymentSurchargeUpdate(params) {
2988
+ var _a, _b, _c;
2989
+ const amount = new import_decimal.default(((_a = params.serviceCharge) == null ? void 0 : _a.fixed) || 0).plus(params.cardReaderSurcharge || 0).toFixed(2);
2990
+ const serviceFee = new import_decimal.default(params.paymentAmount || 0).times(((_b = params.serviceCharge) == null ? void 0 : _b.percentage) || 0).plus(amount).toDecimalPlaces(2).toFixed(2);
2991
+ return {
2992
+ service_charge: {
2993
+ amount,
2994
+ ...((_c = params.serviceCharge) == null ? void 0 : _c.percentage) !== void 0 ? { percentage: params.serviceCharge.percentage } : {}
2995
+ },
2996
+ service_fee: serviceFee
2997
+ };
2998
+ }
2999
+ async runLocalPaymentUpdateInQueue(key, task, context) {
3000
+ var _a;
3001
+ const queuedAt = Date.now();
3002
+ const hasPreviousTask = this.localPaymentUpdateQueues.has(key);
3003
+ const previous = this.localPaymentUpdateQueues.get(key) || Promise.resolve();
3004
+ this.logInfo("handleUpdateLocalPayment: 串行队列入队", {
3005
+ ...context,
3006
+ queue_key: key,
3007
+ waiting_for_previous: hasPreviousTask,
3008
+ active_queue_count: this.localPaymentUpdateQueues.size
3009
+ });
3010
+ const current = previous.catch(() => void 0).then(async () => {
3011
+ this.logInfo("handleUpdateLocalPayment: 串行队列开始执行", {
3012
+ ...context,
3013
+ queue_key: key,
3014
+ queue_wait_ms: Date.now() - queuedAt
3015
+ });
3016
+ return task();
3017
+ });
3018
+ const tail = current.then(() => void 0, () => void 0);
3019
+ this.localPaymentUpdateQueues.set(key, tail);
3020
+ try {
3021
+ const result = await current;
3022
+ this.logInfo("handleUpdateLocalPayment: 串行队列执行完成", {
3023
+ ...context,
3024
+ queue_key: key,
3025
+ total_duration_ms: Date.now() - queuedAt,
3026
+ result_code: result == null ? void 0 : result.code,
3027
+ result_status: result == null ? void 0 : result.status,
3028
+ payment: (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.payment
3029
+ });
3030
+ return result;
3031
+ } catch (error) {
3032
+ this.logError("handleUpdateLocalPayment: 串行队列执行失败", {
3033
+ ...context,
3034
+ queue_key: key,
3035
+ total_duration_ms: Date.now() - queuedAt,
3036
+ error: error instanceof Error ? error.message : String(error),
3037
+ error_detail: this.normalizeUnknownError(error)
3038
+ });
3039
+ throw error;
3040
+ } finally {
3041
+ let released = false;
3042
+ if (this.localPaymentUpdateQueues.get(key) === tail) {
3043
+ this.localPaymentUpdateQueues.delete(key);
3044
+ released = true;
3045
+ }
3046
+ this.logInfo("handleUpdateLocalPayment: 串行队列释放", {
3047
+ ...context,
3048
+ queue_key: key,
3049
+ released,
3050
+ active_queue_count: this.localPaymentUpdateQueues.size
3051
+ });
3052
+ }
3053
+ }
3054
+ async processLocalPaymentUpdate(params) {
3055
+ var _a, _b, _c;
3056
+ const requestContext = {
3057
+ operation_id: params.operationId,
3058
+ sale_id: params.saleId,
3059
+ payment_number: params.paymentNumber,
3060
+ transaction_number: params.number,
3061
+ requested_status: params.status,
3062
+ service_charge: params.serviceCharge ?? null,
3063
+ card_reader_surcharge: params.cardReaderSurcharge ?? null
3064
+ };
3065
+ this.logInfo("processLocalPaymentUpdate: 开始处理", requestContext);
3066
+ if (!this.order) {
3067
+ this.logError("processLocalPaymentUpdate: Order 模块未注册", requestContext);
3068
+ return { code: 500, status: false, message: "Order 模块未注册", data: null };
3069
+ }
3070
+ this.logInfo("processLocalPaymentUpdate: 开始查询本地支付项", requestContext);
3071
+ const found = await this.order.getLocalPayment({
3072
+ saleId: params.saleId,
3073
+ paymentNumber: params.paymentNumber,
3074
+ operationId: params.operationId
3075
+ });
3076
+ if (!found) {
3077
+ this.logWarning("processLocalPaymentUpdate: 本地支付项不存在", requestContext);
3078
+ return { code: 404, status: false, message: "本地支付项不存在", data: null };
3079
+ }
3080
+ const surchargeUpdate = params.status === "success" && params.hasSurchargeInput ? this.buildLocalPaymentSurchargeUpdate({
3081
+ paymentAmount: (_a = found.payment) == null ? void 0 : _a.amount,
3082
+ serviceCharge: params.serviceCharge,
3083
+ cardReaderSurcharge: params.cardReaderSurcharge
3084
+ }) : void 0;
3085
+ const incomingPaymentUpdate = params.status === "success" ? {
3086
+ status: "paid",
3087
+ ...surchargeUpdate || {},
3088
+ metadata: {
3089
+ unique_payment_number: params.number,
3090
+ transactions: [{ number: params.number, status: "success" }]
3091
+ }
3092
+ } : {
3093
+ metadata: {
3094
+ transactions: [{ number: params.number, status: "fail" }]
3095
+ }
3096
+ };
3097
+ const transactions = Array.isArray((_c = (_b = found.payment) == null ? void 0 : _b.metadata) == null ? void 0 : _c.transactions) ? found.payment.metadata.transactions : [];
3098
+ const existingTransaction = transactions.find((item) => String((item == null ? void 0 : item.number) || "") === params.number);
3099
+ const hasRecordedSuccess = transactions.some((item) => (item == null ? void 0 : item.status) === "success");
3100
+ const orderIsDraft = Number(found.order.is_draft_order || 0) === 1;
3101
+ const foundContext = {
3102
+ ...requestContext,
3103
+ matched_by: found.matchedBy,
3104
+ payment_index: found.paymentIndex,
3105
+ ...this.buildLocalPaymentOrderLogContext(found.order),
3106
+ payment: found.payment,
3107
+ incoming_payment_update: incomingPaymentUpdate,
3108
+ existing_transaction: existingTransaction || null,
3109
+ has_recorded_success: hasRecordedSuccess
3110
+ };
3111
+ this.logInfo("processLocalPaymentUpdate: 查询命中", foundContext);
3112
+ if (params.status === "fail" && (found.payment.status === "paid" || hasRecordedSuccess)) {
3113
+ this.logInfo("processLocalPaymentUpdate: 幂等返回", {
3114
+ ...foundContext,
3115
+ idempotent_reason: "ignore_failure_after_success"
3116
+ });
3117
+ return {
3118
+ code: 200,
3119
+ status: true,
3120
+ message: "",
3121
+ data: { payment: found.payment, order: found.order, idempotent: true }
3122
+ };
3123
+ }
3124
+ const alreadyRecordedFailure = params.status === "fail" && (existingTransaction == null ? void 0 : existingTransaction.status) === "fail";
3125
+ if (alreadyRecordedFailure) {
3126
+ this.logInfo("processLocalPaymentUpdate: 幂等返回", {
3127
+ ...foundContext,
3128
+ idempotent_reason: "failure_already_recorded"
3129
+ });
3130
+ return {
3131
+ code: 200,
3132
+ status: true,
3133
+ message: "",
3134
+ data: { payment: found.payment, order: found.order, idempotent: true }
3135
+ };
3136
+ }
3137
+ if (params.status === "success" && (existingTransaction == null ? void 0 : existingTransaction.status) === "success" && found.payment.status === "paid" && !orderIsDraft) {
3138
+ this.logInfo("processLocalPaymentUpdate: 幂等返回", {
3139
+ ...foundContext,
3140
+ idempotent_reason: "success_already_committed"
3141
+ });
3142
+ return {
3143
+ code: 200,
3144
+ status: true,
3145
+ message: "",
3146
+ data: { payment: found.payment, order: found.order, idempotent: true }
3147
+ };
3148
+ }
3149
+ if (params.status === "success") {
3150
+ this.logInfo("processLocalPaymentUpdate: 进入 success 恢复分支", {
3151
+ ...foundContext,
3152
+ force_submit_if_paid: found.payment.status === "paid" && orderIsDraft
3153
+ });
3154
+ return this.processSuccessfulLocalPayment({
3155
+ ...params,
3156
+ order: found.order,
3157
+ payment: found.payment,
3158
+ matchBy: found.matchedBy === "payment_number" ? "payment_number" : "compat",
3159
+ forceSubmitIfPaid: found.payment.status === "paid" && orderIsDraft,
3160
+ paymentUpdate: incomingPaymentUpdate
3161
+ });
3162
+ }
3163
+ this.logInfo("processLocalPaymentUpdate: 进入 fail 本地更新分支", {
3164
+ ...foundContext,
3165
+ incoming_payment_update: incomingPaymentUpdate
3166
+ });
3167
+ let updated;
3168
+ try {
3169
+ updated = await this.order.updateLocalPayment({
3170
+ saleId: params.saleId,
3171
+ paymentNumber: params.paymentNumber,
3172
+ operationId: params.operationId,
3173
+ updates: incomingPaymentUpdate
3174
+ });
3175
+ } catch (error) {
3176
+ this.logError("processLocalPaymentUpdate: fail 本地更新失败", {
3177
+ ...foundContext,
3178
+ incoming_payment_update: incomingPaymentUpdate,
3179
+ error: error instanceof Error ? error.message : String(error),
3180
+ error_detail: this.normalizeUnknownError(error)
3181
+ });
3182
+ throw error;
3183
+ }
3184
+ if (!updated) {
3185
+ this.logWarning("processLocalPaymentUpdate: fail 本地更新未命中", foundContext);
3186
+ return { code: 404, status: false, message: "本地支付项不存在", data: null };
3187
+ }
3188
+ this.logInfo("processLocalPaymentUpdate: fail 本地更新完成", {
3189
+ ...requestContext,
3190
+ ...this.buildLocalPaymentOrderLogContext(updated.order),
3191
+ previous_payment: updated.previousPayment,
3192
+ payment: updated.payment
3193
+ });
3194
+ return {
3195
+ code: 200,
3196
+ status: true,
3197
+ message: "",
3198
+ data: {
3199
+ local_only: true,
3200
+ payment: updated.payment,
3201
+ order: updated.order
3202
+ }
3203
+ };
3204
+ }
3205
+ async processSuccessfulLocalPayment(params) {
3206
+ var _a, _b, _c, _d, _e;
3207
+ const moduleName = `local_payment_recovery_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
3208
+ const baseSales = new import_BaseSales.BaseSalesImpl(moduleName);
3209
+ const startedAt = Date.now();
3210
+ const recoveryContext = {
3211
+ operation_id: params.operationId,
3212
+ sale_id: params.saleId,
3213
+ payment_number: params.paymentNumber,
3214
+ transaction_number: params.number,
3215
+ requested_status: "success",
3216
+ match_by: params.matchBy,
3217
+ force_submit_if_paid: params.forceSubmitIfPaid,
3218
+ incoming_payment_update: params.paymentUpdate,
3219
+ base_sales_module_name: moduleName,
3220
+ ...this.buildLocalPaymentOrderLogContext(params.order),
3221
+ payment: params.payment
3222
+ };
3223
+ this.logInfo("processSuccessfulLocalPayment: 创建临时 BaseSales", recoveryContext);
3224
+ try {
3225
+ const order = this.sanitizeLocalRecoveryOrder(params.order);
3226
+ this.logInfo("processSuccessfulLocalPayment: 本地订单清洗完成", {
3227
+ ...recoveryContext,
3228
+ sanitized_order_id: order.order_id ?? null,
3229
+ removed_synthetic_order_id: params.order.order_id != null && order.order_id == null
3230
+ });
3231
+ await baseSales.initialize(this.core, {
3232
+ otherParams: {
3233
+ platform: order.platform,
3234
+ businessCode: order.business_code,
3235
+ business_code: order.business_code,
3236
+ channel: order.order_sales_channel || order.sales_channel,
3237
+ type: order.type,
3238
+ enableTempOrderPersist: false
3239
+ }
3240
+ });
3241
+ this.logInfo("processSuccessfulLocalPayment: BaseSales 初始化完成", recoveryContext);
3242
+ await baseSales.replaceTempOrder(order);
3243
+ this.logInfo("processSuccessfulLocalPayment: 本地订单 tempOrder 恢复完成", recoveryContext);
3244
+ this.logInfo("processSuccessfulLocalPayment: 开始更新支付项并提交", {
3245
+ ...recoveryContext,
3246
+ incoming_payment_update: params.paymentUpdate
3247
+ });
3248
+ const result = await baseSales.updateOrderPayment(
3249
+ params.paymentNumber,
3250
+ params.paymentUpdate,
3251
+ {
3252
+ submitWhenPaid: true,
3253
+ matchBy: params.matchBy,
3254
+ forceSubmitIfPaid: params.forceSubmitIfPaid,
3255
+ applyUpdatesWhenPaid: params.forceSubmitIfPaid,
3256
+ smallTicketDataFlag: 1
3257
+ }
3258
+ );
3259
+ this.logInfo("processSuccessfulLocalPayment: 支付恢复完成", {
3260
+ ...recoveryContext,
3261
+ duration_ms: Date.now() - startedAt,
3262
+ payment: result.payment,
3263
+ payments_count: ((_a = result.payments) == null ? void 0 : _a.length) || 0,
3264
+ summary: result.summary,
3265
+ sync_result: result.syncResult ? {
3266
+ is_fully_paid: result.syncResult.isFullyPaid,
3267
+ is_order_fully_paid: result.syncResult.isOrderFullyPaid,
3268
+ is_deposit_fully_paid: result.syncResult.isDepositFullyPaid,
3269
+ payment_stage: result.syncResult.paymentStage,
3270
+ deposit_amount: result.syncResult.depositAmount,
3271
+ order_expected_amount: result.syncResult.orderExpectedAmount,
3272
+ submit_result_code: (_b = result.syncResult.submitResult) == null ? void 0 : _b.code,
3273
+ submit_result_status: (_c = result.syncResult.submitResult) == null ? void 0 : _c.status
3274
+ } : null,
3275
+ draft_result: result.draftResult ? {
3276
+ code: (_d = result.draftResult) == null ? void 0 : _d.code,
3277
+ status: (_e = result.draftResult) == null ? void 0 : _e.status
3278
+ } : null,
3279
+ draft_error: result.draftError instanceof Error ? result.draftError.message : result.draftError
3280
+ });
3281
+ return {
3282
+ code: 200,
3283
+ status: true,
3284
+ message: "",
3285
+ data: {
3286
+ payment: result.payment,
3287
+ payments: result.payments,
3288
+ summary: result.summary,
3289
+ sync_result: result.syncResult
3290
+ }
3291
+ };
3292
+ } catch (error) {
3293
+ const message = error instanceof Error ? error.message : String(error);
3294
+ this.logError("processSuccessfulLocalPayment: 支付恢复失败", {
3295
+ ...recoveryContext,
3296
+ duration_ms: Date.now() - startedAt,
3297
+ error: message,
3298
+ error_detail: this.normalizeUnknownError(error)
3299
+ });
3300
+ return { code: 500, status: false, message, data: null };
3301
+ } finally {
3302
+ try {
3303
+ await baseSales.destroy();
3304
+ this.logInfo("processSuccessfulLocalPayment: 临时 BaseSales 销毁完成", {
3305
+ ...recoveryContext,
3306
+ duration_ms: Date.now() - startedAt
3307
+ });
3308
+ } catch (error) {
3309
+ this.logError("processSuccessfulLocalPayment: 临时 BaseSales 销毁失败", {
3310
+ ...recoveryContext,
3311
+ duration_ms: Date.now() - startedAt,
3312
+ error: error instanceof Error ? error.message : String(error),
3313
+ error_detail: this.normalizeUnknownError(error)
3314
+ });
3315
+ }
3316
+ }
3317
+ }
3318
+ sanitizeLocalRecoveryOrder(order) {
3319
+ const next = {
3320
+ ...order,
3321
+ country_calling_code: String(order.country_calling_code ?? ""),
3322
+ phone: String(order.phone ?? ""),
3323
+ email: String(order.email ?? "")
3324
+ };
3325
+ const externalSaleNumber = next.external_sale_number;
3326
+ if (Number(next.is_draft_order || 0) === 1 && next.order_id !== void 0 && externalSaleNumber !== void 0 && String(next.order_id) === String(externalSaleNumber)) {
3327
+ delete next.order_id;
3328
+ }
3329
+ return next;
3330
+ }
2742
3331
  getDeviceTaskPlugin() {
2743
3332
  var _a, _b;
2744
3333
  return ((_b = (_a = this.app) == null ? void 0 : _a.getPlugin) == null ? void 0 : _b.call(_a, "deviceTask")) || null;
@@ -3273,6 +3862,59 @@ var Server = class {
3273
3862
  };
3274
3863
  }
3275
3864
  }
3865
+ async handleOrderDraftSubmit(params) {
3866
+ var _a, _b, _c;
3867
+ const { data, title } = params;
3868
+ this.logInfo(`${title}: 开始处理`, {
3869
+ order_id: data == null ? void 0 : data.order_id,
3870
+ external_sale_number: data == null ? void 0 : data.external_sale_number,
3871
+ order_number: data == null ? void 0 : data.order_number
3872
+ });
3873
+ const normalizedData = await this.normalizeCheckoutSubmitData(data, title);
3874
+ const createdAt = normalizedData.created_at || normalizedData.create_date || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
3875
+ const draftOrder = {
3876
+ ...normalizedData,
3877
+ external_sale_number: normalizedData.external_sale_number || `LOCAL_DRAFT_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
3878
+ created_at: createdAt,
3879
+ schedule_date: normalizedData.schedule_date || createdAt,
3880
+ need_sync: 0,
3881
+ is_draft_order: 1
3882
+ };
3883
+ if (!this.order || typeof this.order.upsertLocalDraftOrders !== "function") {
3884
+ this.logError(`${title}: Order 模块不支持本地草稿写入`);
3885
+ return {
3886
+ code: 500,
3887
+ status: false,
3888
+ message: "Order 模块不支持本地草稿写入",
3889
+ data: null
3890
+ };
3891
+ }
3892
+ try {
3893
+ await this.order.upsertLocalDraftOrders([draftOrder]);
3894
+ this.logInfo(`${title}: 草稿订单已写入本地`, {
3895
+ order_id: draftOrder.order_id,
3896
+ external_sale_number: draftOrder.external_sale_number
3897
+ });
3898
+ return {
3899
+ code: 200,
3900
+ status: true,
3901
+ message: "",
3902
+ data: {
3903
+ ...draftOrder,
3904
+ amount_gap: (_a = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _a.amount_gap,
3905
+ expect_amount: (_b = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _b.expect_amount,
3906
+ total_amount: (_c = draftOrder == null ? void 0 : draftOrder.summary) == null ? void 0 : _c.total_amount,
3907
+ payment_status: draftOrder == null ? void 0 : draftOrder.payment_status
3908
+ }
3909
+ };
3910
+ } catch (error) {
3911
+ const errorMessage = error instanceof Error ? error.message : String(error);
3912
+ this.logError(`${title}: 写入本地草稿订单失败`, {
3913
+ error: errorMessage
3914
+ });
3915
+ return { code: 500, status: false, message: errorMessage, data: null };
3916
+ }
3917
+ }
3276
3918
  async handlePendingSyncCheckoutOrder(params) {
3277
3919
  var _a, _b, _c, _d;
3278
3920
  const { backendPath, data, title, reason } = params;
@@ -3348,7 +3990,8 @@ var Server = class {
3348
3990
  return null;
3349
3991
  const pendingOrder = {
3350
3992
  ...data,
3351
- need_sync: 1
3993
+ need_sync: 1,
3994
+ is_draft_order: 0
3352
3995
  };
3353
3996
  const productMap = await this.buildSmallTicketProductMap(pendingOrder);
3354
3997
  const orderWithProductTitles = this.withPendingSyncProductTitles(
@@ -3401,7 +4044,7 @@ var Server = class {
3401
4044
  return 0;
3402
4045
  return payments.reduce((sum, payment) => {
3403
4046
  const status = String((payment == null ? void 0 : payment.status) || "").toLowerCase();
3404
- if (status === "voided" || status === "failed" || status === "cancelled")
4047
+ if (status !== "paid")
3405
4048
  return sum;
3406
4049
  return sum + this.toAmountNumber((payment == null ? void 0 : payment.amount) ?? (payment == null ? void 0 : payment.origin_amount));
3407
4050
  }, 0);
@@ -3968,9 +4611,11 @@ var Server = class {
3968
4611
  return value === void 0 ? void 0 : String(value);
3969
4612
  }
3970
4613
  buildCheckoutSyncSuccessPatch(fresh) {
4614
+ const patch = {
4615
+ is_draft_order: 0
4616
+ };
3971
4617
  if (!fresh)
3972
- return {};
3973
- const patch = {};
4618
+ return patch;
3974
4619
  if (fresh.order_id !== void 0 && fresh.order_id !== null)
3975
4620
  patch.order_id = fresh.order_id;
3976
4621
  if (fresh.order_number !== void 0 && fresh.order_number !== null) {
@@ -4251,6 +4896,10 @@ var Server = class {
4251
4896
  const rawList = this.order.getOrders();
4252
4897
  this.logInfo("computeOrderQueryResult: 本地订单数量", { rawCount: rawList.length });
4253
4898
  const result = (0, import_filterOrders.filterOrders)(rawList, data);
4899
+ result.list.forEach((order) => {
4900
+ var _a;
4901
+ order.payments = (_a = order.payments) == null ? void 0 : _a.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
4902
+ });
4254
4903
  this.logInfo("computeOrderQueryResult: 过滤结果", {
4255
4904
  rawCount: rawList.length,
4256
4905
  filteredCount: result.count,