@pisell/pisellos 2.3.28 → 2.3.30

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 (57) hide show
  1. package/dist/modules/Order/index.d.ts +32 -8
  2. package/dist/modules/Order/index.js +883 -521
  3. package/dist/modules/Order/payment-utils.d.ts +23 -0
  4. package/dist/modules/Order/payment-utils.js +203 -0
  5. package/dist/modules/Order/types.d.ts +33 -1
  6. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  7. package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
  8. package/dist/modules/Order/utils.d.ts +2 -1
  9. package/dist/modules/Order/utils.js +6 -12
  10. package/dist/modules/Payment/index.d.ts +2 -0
  11. package/dist/modules/Payment/index.js +78 -49
  12. package/dist/modules/Payment/types.d.ts +26 -24
  13. package/dist/modules/Payment/types.js +2 -0
  14. package/dist/modules/Product/index.d.ts +1 -1
  15. package/dist/server/index.d.ts +14 -0
  16. package/dist/server/index.js +1826 -1000
  17. package/dist/server/modules/order/index.d.ts +47 -4
  18. package/dist/server/modules/order/index.js +1415 -711
  19. package/dist/server/modules/order/types.d.ts +11 -3
  20. package/dist/server/modules/order/types.js +1 -1
  21. package/dist/solution/BaseSales/index.d.ts +40 -4
  22. package/dist/solution/BaseSales/index.js +1268 -749
  23. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  24. package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
  25. package/dist/solution/BookingByStep/index.d.ts +1 -1
  26. package/dist/solution/BookingTicket/index.d.ts +13 -1
  27. package/dist/solution/BookingTicket/index.js +2 -1
  28. package/dist/utils/payment-number.d.ts +9 -0
  29. package/dist/utils/payment-number.js +69 -0
  30. package/lib/modules/Order/index.d.ts +32 -8
  31. package/lib/modules/Order/index.js +270 -64
  32. package/lib/modules/Order/payment-utils.d.ts +23 -0
  33. package/lib/modules/Order/payment-utils.js +193 -0
  34. package/lib/modules/Order/types.d.ts +33 -1
  35. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  36. package/lib/modules/Order/utils/orderCollectionIdentity.js +415 -0
  37. package/lib/modules/Order/utils.d.ts +2 -1
  38. package/lib/modules/Order/utils.js +6 -14
  39. package/lib/modules/Payment/index.d.ts +2 -0
  40. package/lib/modules/Payment/index.js +33 -12
  41. package/lib/modules/Payment/types.d.ts +26 -24
  42. package/lib/modules/Product/index.d.ts +1 -1
  43. package/lib/server/index.d.ts +14 -0
  44. package/lib/server/index.js +604 -8
  45. package/lib/server/modules/order/index.d.ts +47 -4
  46. package/lib/server/modules/order/index.js +578 -116
  47. package/lib/server/modules/order/types.d.ts +11 -3
  48. package/lib/solution/BaseSales/index.d.ts +40 -4
  49. package/lib/solution/BaseSales/index.js +363 -37
  50. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  51. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
  52. package/lib/solution/BookingByStep/index.d.ts +1 -1
  53. package/lib/solution/BookingTicket/index.d.ts +13 -1
  54. package/lib/solution/BookingTicket/index.js +2 -1
  55. package/lib/utils/payment-number.d.ts +9 -0
  56. package/lib/utils/payment-number.js +64 -0
  57. package/package.json +1 -1
@@ -37,10 +37,13 @@ var import_types = require("./types");
37
37
  var import_utils = require("./utils");
38
38
  var import_utils2 = require("../Product/utils");
39
39
  var import_dayjs = __toESM(require("dayjs"));
40
+ var import_payment_utils = require("./payment-utils");
41
+ var import_payment_number = require("../../utils/payment-number");
40
42
  var import_cartPromotion = require("../../solution/BaseSales/utils/cartPromotion");
41
43
  var import_utils3 = require("../../solution/ScanOrder/utils");
42
44
  var import_manualProductDiscount = require("./utils/manualProductDiscount");
43
45
  var import_bundleDiscountHydration = require("./utils/bundleDiscountHydration");
46
+ var import_orderCollectionIdentity = require("./utils/orderCollectionIdentity");
44
47
  var import_Discount = require("../Discount");
45
48
  var import_Rules = require("../Rules");
46
49
  var import_types2 = require("../Rules/types");
@@ -309,11 +312,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
309
312
  this.store.summary = (0, import_utils.createEmptySummary)();
310
313
  }
311
314
  this.request = this.core.getPlugin("request");
312
- const appPlugin = this.core.getPlugin("app");
313
- if (!appPlugin) {
315
+ this.appPlugin = this.core.getPlugin("app");
316
+ if (!this.appPlugin) {
314
317
  throw new Error("Order 模块需要 app 插件支持");
315
318
  }
316
- const app = appPlugin.getApp();
319
+ const app = this.appPlugin.getApp();
317
320
  this.logger = app.logger;
318
321
  this.window = this.core.getPlugin("window");
319
322
  const otherParams = options.otherParams || {};
@@ -1042,17 +1045,40 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1042
1045
  const depositPaidAmount = this.calculateDepositPaidAmount(tempOrder.payments || []);
1043
1046
  return depositPaidAmount.lt(depositAmount) ? "deposit" : "normal";
1044
1047
  }
1048
+ getPaymentNumberAppData(key) {
1049
+ var _a, _b, _c, _d, _e;
1050
+ const appPlugin = this.appPlugin;
1051
+ if (!appPlugin)
1052
+ return void 0;
1053
+ const getData = (_a = appPlugin.getData) == null ? void 0 : _a.call(appPlugin);
1054
+ if (typeof getData === "function")
1055
+ return getData(key);
1056
+ const app = appPlugin.getApp();
1057
+ const coreData = (_e = (_c = (_b = app == null ? void 0 : app.models) == null ? void 0 : _b.getStore) == null ? void 0 : (_d = _c.call(_b)).getDataByModel) == null ? void 0 : _e.call(_d, "core", "core");
1058
+ return coreData == null ? void 0 : coreData[key];
1059
+ }
1060
+ getPaymentNumberDevicePrefixSync() {
1061
+ return (0, import_payment_number.resolvePaymentNumberDevicePrefixFromDeviceId)(
1062
+ (key) => this.getPaymentNumberAppData(key)
1063
+ );
1064
+ }
1065
+ getPaymentNumberDevicePrefixAsync() {
1066
+ return (0, import_payment_number.resolvePaymentNumberDevicePrefix)(
1067
+ (key) => this.getPaymentNumberAppData(key)
1068
+ );
1069
+ }
1045
1070
  normalizePaymentSource(payment, options) {
1046
1071
  const paymentRecord = payment;
1047
1072
  const metadata = paymentRecord.metadata && typeof paymentRecord.metadata === "object" ? { ...paymentRecord.metadata } : {};
1048
- if (!metadata.unique_payment_number) {
1049
- metadata.unique_payment_number = (0, import_utils.createUuidV4)();
1050
- }
1051
- const normalized = {
1052
- ...paymentRecord,
1053
- metadata,
1054
- origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
1055
- };
1073
+ const normalized = (0, import_payment_utils.ensureOrderPaymentNumber)(
1074
+ {
1075
+ ...paymentRecord,
1076
+ metadata,
1077
+ origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
1078
+ },
1079
+ (options == null ? void 0 : options.devicePrefix) || this.getPaymentNumberDevicePrefixSync(),
1080
+ import_utils.createUuidV4
1081
+ );
1056
1082
  if (paymentRecord.status !== void 0) {
1057
1083
  normalized.status = paymentRecord.status;
1058
1084
  } else if ((options == null ? void 0 : options.defaultPaid) !== false) {
@@ -2471,17 +2497,36 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2471
2497
  * 用一组支付来源覆盖当前订单支付项。
2472
2498
  *
2473
2499
  * 入参允许来自 PaymentModule 的 PaymentItem,内部统一映射为 Sales 协议:
2474
- * uuid -> metadata.unique_payment_number,id -> custom_payment_id,
2500
+ * 新支付来源的 uuid 会作为 payment_number 的唯一号段,id -> custom_payment_id,
2475
2501
  * isSynced 等运行态字段不会进入 tempOrder.payments。
2476
2502
  */
2477
2503
  setOrderPayments(payments) {
2478
2504
  const tempOrder = this.ensureTempOrder();
2479
- tempOrder.payments = (0, import_utils.mapPaymentItemsToOrderPayments)(payments);
2505
+ tempOrder.payments = (0, import_utils.mapPaymentItemsToOrderPayments)(
2506
+ (payments || []).map((payment) => this.normalizePaymentSource(payment, { defaultPaid: false }))
2507
+ );
2480
2508
  this.persistTempOrder();
2481
2509
  return tempOrder.payments;
2482
2510
  }
2483
- /** 追加单个支付项,并立即持久化当前 tempOrder。 */
2511
+ /** 同步兼容入口:按调用当下的 device_id 或 LOCAL 生成支付编号。 */
2484
2512
  addOrderPayment(payment) {
2513
+ const hasPaymentNumber = String(
2514
+ payment.payment_number || ""
2515
+ ).trim() !== "";
2516
+ return this.addOrderPaymentWithDevicePrefix(
2517
+ payment,
2518
+ hasPaymentNumber ? "LOCAL" : this.getPaymentNumberDevicePrefixSync()
2519
+ );
2520
+ }
2521
+ /** 异步入口:创建支付项时读取最新 IoT 设备短号。 */
2522
+ async addOrderPaymentAsync(payment) {
2523
+ const hasPaymentNumber = String(
2524
+ payment.payment_number || ""
2525
+ ).trim() !== "";
2526
+ const devicePrefix = hasPaymentNumber ? "LOCAL" : await this.getPaymentNumberDevicePrefixAsync();
2527
+ return this.addOrderPaymentWithDevicePrefix(payment, devicePrefix);
2528
+ }
2529
+ addOrderPaymentWithDevicePrefix(payment, devicePrefix) {
2485
2530
  this.logInfo("addOrderPayment", {
2486
2531
  payment
2487
2532
  });
@@ -2494,7 +2539,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2494
2539
  type: orderPaymentType,
2495
2540
  order_payment_type: orderPaymentType
2496
2541
  },
2497
- { defaultPaid: true }
2542
+ { defaultPaid: true, devicePrefix }
2498
2543
  )
2499
2544
  ]);
2500
2545
  tempOrder.payments = [...tempOrder.payments || [], ...mapped];
@@ -2507,57 +2552,55 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2507
2552
  return tempOrder.payments;
2508
2553
  }
2509
2554
  /**
2510
- * 按支付唯一号、后端支付 ID、自定义支付方式 ID 或旧 uuid 更新支付项。
2511
- *
2512
- * 该方法服务 PaymentModal 的 void / 编辑场景;更新 metadata 时会做浅合并,
2513
- * 避免覆盖 unique_payment_number、现金实付/找零等已有元数据。
2555
+ * 默认按支付唯一号精确更新;仅显式指定 legacy 时兼容历史支付标识。
2556
+ * metadata 与 transactions 会分别合并,避免覆盖支付会话号和已有交易记录。
2514
2557
  */
2515
- updateOrderPayment(paymentIdentity, updates) {
2558
+ async updateOrderPayment(paymentIdentity, updates, options = {}) {
2516
2559
  const tempOrder = this.ensureTempOrder();
2517
2560
  const identity = String(paymentIdentity);
2518
- tempOrder.payments = (tempOrder.payments || []).map((payment) => {
2519
- var _a;
2520
- const uniquePaymentNumber = (_a = payment == null ? void 0 : payment.metadata) == null ? void 0 : _a.unique_payment_number;
2521
- const orderPaymentId = payment == null ? void 0 : payment.order_payment_id;
2522
- const customPaymentId = payment == null ? void 0 : payment.custom_payment_id;
2523
- const uuid = payment == null ? void 0 : payment.uuid;
2524
- const matched = [
2525
- uniquePaymentNumber,
2526
- orderPaymentId,
2527
- customPaymentId,
2528
- uuid
2529
- ].some((value) => value !== void 0 && String(value) === identity);
2530
- if (!matched)
2561
+ const matchMode = options.matchBy === "compat" || options.matchBy === "legacy" ? "compat" : "payment_number";
2562
+ const matchedPayment = (0, import_payment_utils.resolveOrderPaymentIdentity)(
2563
+ tempOrder.payments || [],
2564
+ identity,
2565
+ matchMode
2566
+ );
2567
+ if (!matchedPayment) {
2568
+ throw new Error(`未找到支付项: ${identity}`);
2569
+ }
2570
+ let updatedPayment = null;
2571
+ tempOrder.payments = (tempOrder.payments || []).map((payment, index) => {
2572
+ if (index !== matchedPayment.index)
2531
2573
  return payment;
2532
- return {
2533
- ...payment,
2574
+ const nextPayment = (0, import_payment_utils.mergeOrderPaymentRecord)(payment, {
2534
2575
  ...updates,
2535
- metadata: {
2536
- ...payment.metadata || {},
2537
- ...updates.metadata || {}
2538
- }
2539
- };
2576
+ updated_at: updates.updated_at || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
2577
+ });
2578
+ updatedPayment = nextPayment;
2579
+ return nextPayment;
2540
2580
  });
2541
2581
  this.persistTempOrder();
2542
- return tempOrder.payments;
2582
+ const summary = await this.recalculateSummary({ createIfMissing: true });
2583
+ this.persistTempOrder();
2584
+ const payments = tempOrder.payments;
2585
+ return {
2586
+ updated: true,
2587
+ payment: payments[matchedPayment.index] || updatedPayment,
2588
+ payments,
2589
+ summary
2590
+ };
2543
2591
  }
2544
2592
  /** 从当前订单支付项中移除指定支付项。 */
2545
2593
  deleteOrderPayment(paymentIdentity) {
2546
2594
  const tempOrder = this.ensureTempOrder();
2547
2595
  const identity = String(paymentIdentity);
2548
- tempOrder.payments = (tempOrder.payments || []).filter((payment) => {
2549
- var _a;
2550
- const uniquePaymentNumber = (_a = payment == null ? void 0 : payment.metadata) == null ? void 0 : _a.unique_payment_number;
2551
- const orderPaymentId = payment == null ? void 0 : payment.order_payment_id;
2552
- const customPaymentId = payment == null ? void 0 : payment.custom_payment_id;
2553
- const uuid = payment == null ? void 0 : payment.uuid;
2554
- return ![
2555
- uniquePaymentNumber,
2556
- orderPaymentId,
2557
- customPaymentId,
2558
- uuid
2559
- ].some((value) => value !== void 0 && String(value) === identity);
2560
- });
2596
+ const matchedPayment = (0, import_payment_utils.resolveOrderPaymentIdentity)(
2597
+ tempOrder.payments || [],
2598
+ identity,
2599
+ "compat"
2600
+ );
2601
+ if (!matchedPayment)
2602
+ return tempOrder.payments;
2603
+ tempOrder.payments = (tempOrder.payments || []).filter((_, index) => index !== matchedPayment.index);
2561
2604
  this.persistTempOrder();
2562
2605
  return tempOrder.payments;
2563
2606
  }
@@ -2666,7 +2709,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2666
2709
  payments.map(
2667
2710
  (payment) => this.normalizePaymentSource(
2668
2711
  normalizeVoucherPaymentStatus(withVoucherPaymentType(payment)),
2669
- { defaultPaid: false }
2712
+ {
2713
+ defaultPaid: false,
2714
+ devicePrefix: options == null ? void 0 : options.devicePrefix
2715
+ }
2670
2716
  )
2671
2717
  )
2672
2718
  ).filter((payment) => {
@@ -2717,6 +2763,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2717
2763
  });
2718
2764
  return tempOrder.payments;
2719
2765
  }
2766
+ async updateVoucherOrderPaymentsAsync(payments, options) {
2767
+ const needsPaymentNumber = (payments || []).some((payment) => String(payment.payment_number || "").trim() === "");
2768
+ const devicePrefix = needsPaymentNumber ? await this.getPaymentNumberDevicePrefixAsync() : "LOCAL";
2769
+ return this.updateVoucherOrderPayments(payments, {
2770
+ ...options,
2771
+ devicePrefix
2772
+ });
2773
+ }
2720
2774
  async shouldMergeProductToOrder(params) {
2721
2775
  var _a;
2722
2776
  const onBeforeMergeProductToOrder = (_a = this.orderHooks) == null ? void 0 : _a.onBeforeMergeProductToOrder;
@@ -3483,6 +3537,38 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3483
3537
  await this.saveDraft();
3484
3538
  return tempOrder;
3485
3539
  }
3540
+ async saveTempOrderAsDraft(params) {
3541
+ var _a, _b, _c, _d, _e;
3542
+ const tempOrder = this.ensureTempOrder();
3543
+ this.ensureExternalSaleNumber(tempOrder);
3544
+ this.persistTempOrder();
3545
+ const latestSummary = await this.recalculateSummary({ createIfMissing: true }) || this.store.summary || (0, import_utils.createEmptySummary)();
3546
+ const payload = (0, import_utils.buildSubmitPayload)({
3547
+ tempOrder,
3548
+ cacheId: (params == null ? void 0 : params.cacheId) ?? this.cacheId,
3549
+ platform: (params == null ? void 0 : params.platform) || ((_a = this.otherParams) == null ? void 0 : _a.platform),
3550
+ businessCode: (params == null ? void 0 : params.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code),
3551
+ channel: params == null ? void 0 : params.channel,
3552
+ type: (params == null ? void 0 : params.type) ?? ((_d = this.otherParams) == null ? void 0 : _d.type),
3553
+ summary: latestSummary,
3554
+ enhance: params == null ? void 0 : params.enhancePayload
3555
+ });
3556
+ if (!payload.created_at) {
3557
+ payload.created_at = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
3558
+ }
3559
+ payload.need_sync = 0;
3560
+ payload.is_draft_order = 1;
3561
+ this.logInfo("saveTempOrderAsDraft calling sales draft", {
3562
+ orderId: payload.order_id,
3563
+ externalSaleNumber: payload.external_sale_number,
3564
+ productsCount: ((_e = payload.products) == null ? void 0 : _e.length) || 0
3565
+ });
3566
+ return this.request.post("/order/sales/draft", payload, {
3567
+ osServer: true,
3568
+ customToast: () => {
3569
+ }
3570
+ });
3571
+ }
3486
3572
  /**
3487
3573
  * 提交当前 Sales tempOrder。
3488
3574
  *
@@ -3683,8 +3769,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3683
3769
  }
3684
3770
  async syncPaymentsToOrder(params) {
3685
3771
  const tempOrder = this.ensureTempOrder();
3772
+ const needsPaymentNumber = (params.payments || []).some((payment) => String(payment.payment_number || "").trim() === "");
3773
+ const devicePrefix = needsPaymentNumber ? await this.getPaymentNumberDevicePrefixAsync() : "LOCAL";
3686
3774
  const mappedPayments = (0, import_utils.mapPaymentItemsToOrderPayments)(
3687
- params.payments || []
3775
+ (params.payments || []).map((payment) => this.normalizePaymentSource(payment, {
3776
+ defaultPaid: false,
3777
+ devicePrefix
3778
+ }))
3688
3779
  );
3689
3780
  const shouldConfirmPendingVoucherPayments = params.confirmPendingVoucherPayments ?? params.submitWhenPaid === true;
3690
3781
  const effectivePayments = shouldConfirmPendingVoucherPayments ? this.confirmPendingVoucherPaymentsInList(mappedPayments) : params.confirmPendingVoucherPayments === false ? this.discardPendingVoucherPaymentsFromList(mappedPayments) : mappedPayments;
@@ -4030,8 +4121,42 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4030
4121
  */
4031
4122
  async hydrateTempOrderFromRecord(record, options) {
4032
4123
  var _a, _b, _c;
4033
- const raw = record && typeof record === "object" && record.data && record.order_id == null ? record.data : record || {};
4124
+ const sourceRaw = record && typeof record === "object" && record.data && record.order_id == null ? record.data : record || {};
4125
+ const identityReadySource = this.seedAnonymousBookingUidsFromProducts(
4126
+ sourceRaw
4127
+ );
4128
+ const normalizedCollections = (0, import_orderCollectionIdentity.normalizeOrderCollections)(identityReadySource);
4129
+ const raw = normalizedCollections.order;
4130
+ const hasIdentityChanges = Object.values(normalizedCollections.stats).some(
4131
+ (stats) => stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0
4132
+ );
4133
+ if (hasIdentityChanges) {
4134
+ const identityLogMetadata = {
4135
+ collections: normalizedCollections.stats,
4136
+ uidRemapCount: normalizedCollections.uidRemaps.length
4137
+ };
4138
+ const hasIdentityWarnings = Object.values(normalizedCollections.stats).some(
4139
+ (stats) => stats.uidConflictCount > 0 || stats.anonymousRowCount > 0
4140
+ );
4141
+ if (hasIdentityWarnings) {
4142
+ this.logWarning(
4143
+ "Normalized hydrated order collection identities",
4144
+ identityLogMetadata
4145
+ );
4146
+ } else {
4147
+ this.logInfo(
4148
+ "Normalized hydrated order collection identities",
4149
+ identityLogMetadata
4150
+ );
4151
+ }
4152
+ }
4034
4153
  const nextTempOrder = this.normalizeTempOrderForRuntime(raw, { makeEditMark: true });
4154
+ const sourceLastOrderInfo = raw.lastOrderInfo || raw;
4155
+ const isDraftOrder = Number(nextTempOrder.is_draft_order || 0) === 1;
4156
+ const syntheticIdentityOptions = {
4157
+ isDraftOrder,
4158
+ externalSaleNumber: nextTempOrder.external_sale_number
4159
+ };
4035
4160
  const rawSummary = raw.summary && typeof raw.summary === "object" ? raw.summary : {};
4036
4161
  const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map((s) => ({ ...s || {} })) : (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []);
4037
4162
  this.store.tempOrder = nextTempOrder;
@@ -4045,13 +4170,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4045
4170
  originalSalesSnapshot: {
4046
4171
  summary: (0, import_lodash_es.cloneDeep)(this.store.summary),
4047
4172
  products: (0, import_lodash_es.cloneDeep)(nextTempOrder.products || []),
4173
+ bookings: (0, import_lodash_es.cloneDeep)(nextTempOrder.bookings || []),
4048
4174
  payments: (0, import_lodash_es.cloneDeep)(nextTempOrder.payments || []),
4049
4175
  surcharges: (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []),
4050
4176
  shop_discount: nextTempOrder.shop_discount || "0.00",
4051
4177
  productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || [])
4052
4178
  }
4053
4179
  };
4054
- this.store.lastOrderInfo = raw.lastOrderInfo || raw;
4180
+ this.store.lastOrderInfo = this.withoutSyntheticDraftOrderIdForRuntime(
4181
+ sourceLastOrderInfo,
4182
+ syntheticIdentityOptions
4183
+ );
4184
+ const hadSyntheticDraftOrderId = this.isSyntheticDraftOrderIdForRuntime(raw, syntheticIdentityOptions) || this.isSyntheticDraftOrderIdForRuntime(sourceLastOrderInfo, syntheticIdentityOptions);
4185
+ if (hadSyntheticDraftOrderId && this.store.syncState !== "submitting") {
4186
+ this.store.syncState = "local";
4187
+ }
4055
4188
  const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
4056
4189
  const currentDiscounts = typeof ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
4057
4190
  const currentScanDiscounts = currentDiscounts.filter((discount) => discount == null ? void 0 : discount.isScan);
@@ -4104,14 +4237,73 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4104
4237
  }
4105
4238
  return next;
4106
4239
  }
4240
+ /**
4241
+ * 匿名 booking 没有服务端行 ID 时,商品侧已有的 booking_uid 就是唯一可用的强引用。
4242
+ * 在统一规范化生成 UUID 前先复用它;已落库 booking 仍按 schedule_event_id 派生稳定 UID。
4243
+ */
4244
+ seedAnonymousBookingUidsFromProducts(raw) {
4245
+ var _a, _b;
4246
+ if (!raw || typeof raw !== "object")
4247
+ return {};
4248
+ if (!Array.isArray(raw.bookings) || !Array.isArray(raw.products))
4249
+ return raw;
4250
+ const bookingUidsByProductUid = /* @__PURE__ */ new Map();
4251
+ for (const product of raw.products) {
4252
+ const productUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)("product", product);
4253
+ const bookingUid = (product == null ? void 0 : product.booking_uid) || ((_a = product == null ? void 0 : product.metadata) == null ? void 0 : _a.booking_uid);
4254
+ if (!productUid || bookingUid === void 0 || bookingUid === null || bookingUid === "") {
4255
+ continue;
4256
+ }
4257
+ const candidates = bookingUidsByProductUid.get(productUid) || /* @__PURE__ */ new Set();
4258
+ candidates.add(String(bookingUid));
4259
+ bookingUidsByProductUid.set(productUid, candidates);
4260
+ }
4261
+ if (bookingUidsByProductUid.size === 0)
4262
+ return raw;
4263
+ const anonymousBookingCountByProductUid = /* @__PURE__ */ new Map();
4264
+ for (const booking of raw.bookings) {
4265
+ if ((0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("booking", booking) || (0, import_orderCollectionIdentity.getOrderCollectionUid)("booking", booking)) {
4266
+ continue;
4267
+ }
4268
+ const productUid = (booking == null ? void 0 : booking.product_uid) || ((_b = booking == null ? void 0 : booking.metadata) == null ? void 0 : _b.product_uid);
4269
+ if (productUid === void 0 || productUid === null || productUid === "")
4270
+ continue;
4271
+ const key = String(productUid);
4272
+ anonymousBookingCountByProductUid.set(
4273
+ key,
4274
+ (anonymousBookingCountByProductUid.get(key) || 0) + 1
4275
+ );
4276
+ }
4277
+ return {
4278
+ ...raw,
4279
+ bookings: raw.bookings.map((booking) => {
4280
+ var _a2;
4281
+ if ((0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("booking", booking) || (0, import_orderCollectionIdentity.getOrderCollectionUid)("booking", booking)) {
4282
+ return booking;
4283
+ }
4284
+ const productUid = (booking == null ? void 0 : booking.product_uid) || ((_a2 = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a2.product_uid);
4285
+ if (productUid === void 0 || productUid === null || productUid === "") {
4286
+ return booking;
4287
+ }
4288
+ const productUidKey = String(productUid);
4289
+ if (anonymousBookingCountByProductUid.get(productUidKey) !== 1) {
4290
+ return booking;
4291
+ }
4292
+ const bookingUidCandidates = bookingUidsByProductUid.get(productUidKey);
4293
+ const bookingUid = (bookingUidCandidates == null ? void 0 : bookingUidCandidates.size) === 1 ? [...bookingUidCandidates][0] : null;
4294
+ return bookingUid ? (0, import_orderCollectionIdentity.setOrderCollectionUid)("booking", booking, bookingUid) : booking;
4295
+ })
4296
+ };
4297
+ }
4107
4298
  normalizeTempOrderForRuntime(raw, options) {
4108
4299
  var _a, _b;
4300
+ const runtimeRaw = this.withoutSyntheticDraftOrderIdForRuntime(raw);
4109
4301
  const nextTempOrder = {
4110
4302
  ...this.createDefaultTempOrderInstance(),
4111
- ...raw || {}
4303
+ ...runtimeRaw || {}
4112
4304
  };
4113
- if ((nextTempOrder.order_id === void 0 || nextTempOrder.order_id === null) && (raw == null ? void 0 : raw.id) !== void 0 && (raw == null ? void 0 : raw.id) !== null) {
4114
- nextTempOrder.order_id = raw.id;
4305
+ if ((nextTempOrder.order_id === void 0 || nextTempOrder.order_id === null) && (runtimeRaw == null ? void 0 : runtimeRaw.id) !== void 0 && (runtimeRaw == null ? void 0 : runtimeRaw.id) !== null) {
4306
+ nextTempOrder.order_id = runtimeRaw.id;
4115
4307
  }
4116
4308
  delete nextTempOrder.summary;
4117
4309
  delete nextTempOrder.lastOrderInfo;
@@ -4179,6 +4371,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4179
4371
  nextTempOrder.vouchers = raw.vouchers || [];
4180
4372
  return nextTempOrder;
4181
4373
  }
4374
+ isSyntheticDraftOrderIdForRuntime(record, options) {
4375
+ const isDraftOrder = (options == null ? void 0 : options.isDraftOrder) ?? Number((record == null ? void 0 : record.is_draft_order) || 0) === 1;
4376
+ const externalSaleNumber = (record == null ? void 0 : record.external_sale_number) ?? (options == null ? void 0 : options.externalSaleNumber);
4377
+ const orderId = record == null ? void 0 : record.order_id;
4378
+ return Boolean(
4379
+ isDraftOrder && orderId !== void 0 && orderId !== null && orderId !== "" && externalSaleNumber !== void 0 && externalSaleNumber !== null && externalSaleNumber !== "" && String(orderId) === String(externalSaleNumber)
4380
+ );
4381
+ }
4382
+ withoutSyntheticDraftOrderIdForRuntime(record, options) {
4383
+ if (!this.isSyntheticDraftOrderIdForRuntime(record, options))
4384
+ return record;
4385
+ return {
4386
+ ...record,
4387
+ order_id: null
4388
+ };
4389
+ }
4182
4390
  hydrateLinkedBookingIdentity(tempOrder) {
4183
4391
  const bookingUidByProductUid = /* @__PURE__ */ new Map();
4184
4392
  const productByUid = /* @__PURE__ */ new Map();
@@ -4218,9 +4426,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4218
4426
  if (!product.metadata || typeof product.metadata !== "object") {
4219
4427
  product.metadata = {};
4220
4428
  }
4221
- const linkedBookingUid = String(
4222
- product.booking_uid || product.metadata.booking_uid || bookingUid
4223
- );
4429
+ const linkedBookingUid = String(bookingUid);
4224
4430
  product.booking_uid = linkedBookingUid;
4225
4431
  product.metadata.booking_uid = linkedBookingUid;
4226
4432
  });
@@ -0,0 +1,23 @@
1
+ export type OrderPaymentTransactionStatus = 'success' | 'fail';
2
+ export interface OrderPaymentTransaction {
3
+ number: string;
4
+ status: OrderPaymentTransactionStatus;
5
+ }
6
+ export type OrderPaymentIdentityType = 'order_payment_id' | 'payment_number' | 'unique_payment_number';
7
+ export interface OrderPaymentIdentityMatch<T> {
8
+ index: number;
9
+ payment: T;
10
+ matchedBy: OrderPaymentIdentityType;
11
+ }
12
+ export declare function getOrderPaymentIdentityKeys(payment: unknown): string[];
13
+ export declare function hasOrderPaymentIdentityOverlap(left: unknown, right: unknown): boolean;
14
+ export declare function resolveOrderPaymentIdentity<T extends Record<string, any>>(payments: T[] | null | undefined, identity: string | number, mode?: 'payment_number' | 'compat'): OrderPaymentIdentityMatch<T> | null;
15
+ export declare function ensureOrderPaymentNumber<T extends Record<string, any>>(payment: T, devicePrefix: string, createPaymentNumber: () => string): T & {
16
+ payment_number: string;
17
+ };
18
+ export declare function mergeOrderPaymentTransactions(current: unknown, incoming: unknown): OrderPaymentTransaction[];
19
+ export declare function mergeOrderPaymentRecord<T extends Record<string, any>>(payment: T, updates: Record<string, any>): T;
20
+ export declare function mergeOrderPaymentSnapshot<T extends Record<string, any>>(current: T, incoming: T): T;
21
+ export declare function mergeOrderPaymentListsByIdentity<T extends Record<string, any>>(existing: T[] | null | undefined, incoming: T[] | null | undefined, options?: {
22
+ preserveUnmatchedExisting?: boolean;
23
+ }): T[];