@pisell/pisellos 2.2.263 → 2.2.265

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 (52) hide show
  1. package/dist/modules/Order/index.d.ts +27 -8
  2. package/dist/modules/Order/index.js +736 -473
  3. package/dist/modules/Order/payment-utils.d.ts +26 -0
  4. package/dist/modules/Order/payment-utils.js +225 -0
  5. package/dist/modules/Order/types.d.ts +33 -1
  6. package/dist/modules/Order/utils/orderCollectionIdentity.js +7 -2
  7. package/dist/modules/Order/utils.js +8 -5
  8. package/dist/modules/Payment/index.d.ts +2 -0
  9. package/dist/modules/Payment/index.js +78 -49
  10. package/dist/modules/Payment/types.d.ts +26 -24
  11. package/dist/modules/Payment/types.js +2 -0
  12. package/dist/server/index.d.ts +16 -0
  13. package/dist/server/index.js +1940 -1043
  14. package/dist/server/modules/order/index.d.ts +49 -4
  15. package/dist/server/modules/order/index.js +1577 -698
  16. package/dist/server/modules/order/types.d.ts +11 -3
  17. package/dist/server/modules/order/types.js +1 -1
  18. package/dist/solution/BaseSales/index.d.ts +33 -3
  19. package/dist/solution/BaseSales/index.js +653 -340
  20. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
  21. package/dist/solution/BookingByStep/index.d.ts +1 -1
  22. package/dist/solution/BookingTicket/index.js +2 -1
  23. package/dist/solution/Sales/index.d.ts +1 -0
  24. package/dist/solution/Sales/index.js +10 -2
  25. package/dist/utils/payment-number.d.ts +9 -0
  26. package/dist/utils/payment-number.js +69 -0
  27. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  28. package/lib/modules/Order/index.d.ts +27 -8
  29. package/lib/modules/Order/index.js +180 -60
  30. package/lib/modules/Order/payment-utils.d.ts +26 -0
  31. package/lib/modules/Order/payment-utils.js +224 -0
  32. package/lib/modules/Order/types.d.ts +33 -1
  33. package/lib/modules/Order/utils/orderCollectionIdentity.js +3 -0
  34. package/lib/modules/Order/utils.js +5 -3
  35. package/lib/modules/Payment/index.d.ts +2 -0
  36. package/lib/modules/Payment/index.js +33 -12
  37. package/lib/modules/Payment/types.d.ts +26 -24
  38. package/lib/server/index.d.ts +16 -0
  39. package/lib/server/index.js +670 -18
  40. package/lib/server/modules/order/index.d.ts +49 -4
  41. package/lib/server/modules/order/index.js +657 -66
  42. package/lib/server/modules/order/types.d.ts +11 -3
  43. package/lib/solution/BaseSales/index.d.ts +33 -3
  44. package/lib/solution/BaseSales/index.js +193 -9
  45. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
  46. package/lib/solution/BookingByStep/index.d.ts +1 -1
  47. package/lib/solution/BookingTicket/index.js +2 -1
  48. package/lib/solution/Sales/index.d.ts +1 -0
  49. package/lib/solution/Sales/index.js +5 -3
  50. package/lib/utils/payment-number.d.ts +9 -0
  51. package/lib/utils/payment-number.js +64 -0
  52. package/package.json +1 -1
@@ -37,6 +37,8 @@ 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");
@@ -313,11 +315,11 @@ var OrderModule = class extends import_BaseModule.BaseModule {
313
315
  this.store.availableWalletIds = [];
314
316
  }
315
317
  this.request = this.core.getPlugin("request");
316
- const appPlugin = this.core.getPlugin("app");
317
- if (!appPlugin) {
318
+ this.appPlugin = this.core.getPlugin("app");
319
+ if (!this.appPlugin) {
318
320
  throw new Error("Order 模块需要 app 插件支持");
319
321
  }
320
- const app = appPlugin.getApp();
322
+ const app = this.appPlugin.getApp();
321
323
  this.logger = app.logger;
322
324
  this.window = this.core.getPlugin("window");
323
325
  const otherParams = options.otherParams || {};
@@ -1053,17 +1055,40 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1053
1055
  const depositPaidAmount = this.calculateDepositPaidAmount(tempOrder.payments || []);
1054
1056
  return depositPaidAmount.lt(depositAmount) ? "deposit" : "normal";
1055
1057
  }
1058
+ getPaymentNumberAppData(key) {
1059
+ var _a, _b, _c, _d, _e;
1060
+ const appPlugin = this.appPlugin;
1061
+ if (!appPlugin)
1062
+ return void 0;
1063
+ const getData = (_a = appPlugin.getData) == null ? void 0 : _a.call(appPlugin);
1064
+ if (typeof getData === "function")
1065
+ return getData(key);
1066
+ const app = appPlugin.getApp();
1067
+ 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");
1068
+ return coreData == null ? void 0 : coreData[key];
1069
+ }
1070
+ getPaymentNumberDevicePrefixSync() {
1071
+ return (0, import_payment_number.resolvePaymentNumberDevicePrefixFromDeviceId)(
1072
+ (key) => this.getPaymentNumberAppData(key)
1073
+ );
1074
+ }
1075
+ getPaymentNumberDevicePrefixAsync() {
1076
+ return (0, import_payment_number.resolvePaymentNumberDevicePrefix)(
1077
+ (key) => this.getPaymentNumberAppData(key)
1078
+ );
1079
+ }
1056
1080
  normalizePaymentSource(payment, options) {
1057
1081
  const paymentRecord = payment;
1058
1082
  const metadata = paymentRecord.metadata && typeof paymentRecord.metadata === "object" ? { ...paymentRecord.metadata } : {};
1059
- if (!metadata.unique_payment_number) {
1060
- metadata.unique_payment_number = (0, import_utils.createUuidV4)();
1061
- }
1062
- const normalized = {
1063
- ...paymentRecord,
1064
- metadata,
1065
- origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
1066
- };
1083
+ const normalized = (0, import_payment_utils.ensureOrderPaymentNumber)(
1084
+ {
1085
+ ...paymentRecord,
1086
+ metadata,
1087
+ origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
1088
+ },
1089
+ (options == null ? void 0 : options.devicePrefix) || this.getPaymentNumberDevicePrefixSync(),
1090
+ import_utils.createUuidV4
1091
+ );
1067
1092
  if (paymentRecord.status !== void 0) {
1068
1093
  normalized.status = paymentRecord.status;
1069
1094
  } else if ((options == null ? void 0 : options.defaultPaid) !== false) {
@@ -2484,17 +2509,36 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2484
2509
  * 用一组支付来源覆盖当前订单支付项。
2485
2510
  *
2486
2511
  * 入参允许来自 PaymentModule 的 PaymentItem,内部统一映射为 Sales 协议:
2487
- * uuid -> metadata.unique_payment_number,id -> custom_payment_id,
2512
+ * 新支付来源的 uuid 会作为 payment_number 的唯一号段,id -> custom_payment_id,
2488
2513
  * isSynced 等运行态字段不会进入 tempOrder.payments。
2489
2514
  */
2490
2515
  setOrderPayments(payments) {
2491
2516
  const tempOrder = this.ensureTempOrder();
2492
- tempOrder.payments = (0, import_utils.mapPaymentItemsToOrderPayments)(payments);
2517
+ tempOrder.payments = (0, import_utils.mapPaymentItemsToOrderPayments)(
2518
+ (payments || []).map((payment) => this.normalizePaymentSource(payment, { defaultPaid: false }))
2519
+ );
2493
2520
  this.persistTempOrder();
2494
2521
  return tempOrder.payments;
2495
2522
  }
2496
- /** 追加单个支付项,并立即持久化当前 tempOrder。 */
2523
+ /** 同步兼容入口:按调用当下的 device_id 或 LOCAL 生成支付编号。 */
2497
2524
  addOrderPayment(payment) {
2525
+ const hasPaymentNumber = String(
2526
+ payment.payment_number || ""
2527
+ ).trim() !== "";
2528
+ return this.addOrderPaymentWithDevicePrefix(
2529
+ payment,
2530
+ hasPaymentNumber ? "LOCAL" : this.getPaymentNumberDevicePrefixSync()
2531
+ );
2532
+ }
2533
+ /** 异步入口:创建支付项时读取最新 IoT 设备短号。 */
2534
+ async addOrderPaymentAsync(payment) {
2535
+ const hasPaymentNumber = String(
2536
+ payment.payment_number || ""
2537
+ ).trim() !== "";
2538
+ const devicePrefix = hasPaymentNumber ? "LOCAL" : await this.getPaymentNumberDevicePrefixAsync();
2539
+ return this.addOrderPaymentWithDevicePrefix(payment, devicePrefix);
2540
+ }
2541
+ addOrderPaymentWithDevicePrefix(payment, devicePrefix) {
2498
2542
  this.logInfo("addOrderPayment", {
2499
2543
  payment
2500
2544
  });
@@ -2507,7 +2551,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2507
2551
  type: orderPaymentType,
2508
2552
  order_payment_type: orderPaymentType
2509
2553
  },
2510
- { defaultPaid: true }
2554
+ { defaultPaid: true, devicePrefix }
2511
2555
  )
2512
2556
  ]);
2513
2557
  tempOrder.payments = [...tempOrder.payments || [], ...mapped];
@@ -2520,57 +2564,55 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2520
2564
  return tempOrder.payments;
2521
2565
  }
2522
2566
  /**
2523
- * 按支付唯一号、后端支付 ID、自定义支付方式 ID 或旧 uuid 更新支付项。
2524
- *
2525
- * 该方法服务 PaymentModal 的 void / 编辑场景;更新 metadata 时会做浅合并,
2526
- * 避免覆盖 unique_payment_number、现金实付/找零等已有元数据。
2567
+ * 默认按支付唯一号精确更新;仅显式指定 legacy 时兼容历史支付标识。
2568
+ * metadata 与 transactions 会分别合并,避免覆盖支付会话号和已有交易记录。
2527
2569
  */
2528
- updateOrderPayment(paymentIdentity, updates) {
2570
+ async updateOrderPayment(paymentIdentity, updates, options = {}) {
2529
2571
  const tempOrder = this.ensureTempOrder();
2530
2572
  const identity = String(paymentIdentity);
2531
- tempOrder.payments = (tempOrder.payments || []).map((payment) => {
2532
- var _a;
2533
- const uniquePaymentNumber = (_a = payment == null ? void 0 : payment.metadata) == null ? void 0 : _a.unique_payment_number;
2534
- const orderPaymentId = payment == null ? void 0 : payment.order_payment_id;
2535
- const customPaymentId = payment == null ? void 0 : payment.custom_payment_id;
2536
- const uuid = payment == null ? void 0 : payment.uuid;
2537
- const matched = [
2538
- uniquePaymentNumber,
2539
- orderPaymentId,
2540
- customPaymentId,
2541
- uuid
2542
- ].some((value) => value !== void 0 && String(value) === identity);
2543
- if (!matched)
2573
+ const matchMode = options.matchBy === "compat" || options.matchBy === "legacy" ? "compat" : "payment_number";
2574
+ const matchedPayment = (0, import_payment_utils.resolveOrderPaymentIdentity)(
2575
+ tempOrder.payments || [],
2576
+ identity,
2577
+ matchMode
2578
+ );
2579
+ if (!matchedPayment) {
2580
+ throw new Error(`未找到支付项: ${identity}`);
2581
+ }
2582
+ let updatedPayment = null;
2583
+ tempOrder.payments = (tempOrder.payments || []).map((payment, index) => {
2584
+ if (index !== matchedPayment.index)
2544
2585
  return payment;
2545
- return {
2546
- ...payment,
2586
+ const nextPayment = (0, import_payment_utils.mergeOrderPaymentRecord)(payment, {
2547
2587
  ...updates,
2548
- metadata: {
2549
- ...payment.metadata || {},
2550
- ...updates.metadata || {}
2551
- }
2552
- };
2588
+ updated_at: updates.updated_at || (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
2589
+ });
2590
+ updatedPayment = nextPayment;
2591
+ return nextPayment;
2553
2592
  });
2554
2593
  this.persistTempOrder();
2555
- return tempOrder.payments;
2594
+ const summary = await this.recalculateSummary({ createIfMissing: true });
2595
+ this.persistTempOrder();
2596
+ const payments = tempOrder.payments;
2597
+ return {
2598
+ updated: true,
2599
+ payment: payments[matchedPayment.index] || updatedPayment,
2600
+ payments,
2601
+ summary
2602
+ };
2556
2603
  }
2557
2604
  /** 从当前订单支付项中移除指定支付项。 */
2558
2605
  deleteOrderPayment(paymentIdentity) {
2559
2606
  const tempOrder = this.ensureTempOrder();
2560
2607
  const identity = String(paymentIdentity);
2561
- tempOrder.payments = (tempOrder.payments || []).filter((payment) => {
2562
- var _a;
2563
- const uniquePaymentNumber = (_a = payment == null ? void 0 : payment.metadata) == null ? void 0 : _a.unique_payment_number;
2564
- const orderPaymentId = payment == null ? void 0 : payment.order_payment_id;
2565
- const customPaymentId = payment == null ? void 0 : payment.custom_payment_id;
2566
- const uuid = payment == null ? void 0 : payment.uuid;
2567
- return ![
2568
- uniquePaymentNumber,
2569
- orderPaymentId,
2570
- customPaymentId,
2571
- uuid
2572
- ].some((value) => value !== void 0 && String(value) === identity);
2573
- });
2608
+ const matchedPayment = (0, import_payment_utils.resolveOrderPaymentIdentity)(
2609
+ tempOrder.payments || [],
2610
+ identity,
2611
+ "compat"
2612
+ );
2613
+ if (!matchedPayment)
2614
+ return tempOrder.payments;
2615
+ tempOrder.payments = (tempOrder.payments || []).filter((_, index) => index !== matchedPayment.index);
2574
2616
  this.persistTempOrder();
2575
2617
  return tempOrder.payments;
2576
2618
  }
@@ -2679,7 +2721,10 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2679
2721
  payments.map(
2680
2722
  (payment) => this.normalizePaymentSource(
2681
2723
  normalizeVoucherPaymentStatus(withVoucherPaymentType(payment)),
2682
- { defaultPaid: false }
2724
+ {
2725
+ defaultPaid: false,
2726
+ devicePrefix: options == null ? void 0 : options.devicePrefix
2727
+ }
2683
2728
  )
2684
2729
  )
2685
2730
  ).filter((payment) => {
@@ -2730,6 +2775,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2730
2775
  });
2731
2776
  return tempOrder.payments;
2732
2777
  }
2778
+ async updateVoucherOrderPaymentsAsync(payments, options) {
2779
+ const needsPaymentNumber = (payments || []).some((payment) => String(payment.payment_number || "").trim() === "");
2780
+ const devicePrefix = needsPaymentNumber ? await this.getPaymentNumberDevicePrefixAsync() : "LOCAL";
2781
+ return this.updateVoucherOrderPayments(payments, {
2782
+ ...options,
2783
+ devicePrefix
2784
+ });
2785
+ }
2733
2786
  async shouldMergeProductToOrder(params) {
2734
2787
  var _a;
2735
2788
  const onBeforeMergeProductToOrder = (_a = this.orderHooks) == null ? void 0 : _a.onBeforeMergeProductToOrder;
@@ -3560,6 +3613,38 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3560
3613
  await this.saveDraft();
3561
3614
  return tempOrder;
3562
3615
  }
3616
+ async saveTempOrderAsDraft(params) {
3617
+ var _a, _b, _c, _d, _e;
3618
+ const tempOrder = this.ensureTempOrder();
3619
+ this.ensureExternalSaleNumber(tempOrder);
3620
+ this.persistTempOrder();
3621
+ const latestSummary = await this.recalculateSummary({ createIfMissing: true }) || this.store.summary || (0, import_utils.createEmptySummary)();
3622
+ const payload = (0, import_utils.buildSubmitPayload)({
3623
+ tempOrder,
3624
+ cacheId: (params == null ? void 0 : params.cacheId) ?? this.cacheId,
3625
+ platform: (params == null ? void 0 : params.platform) || ((_a = this.otherParams) == null ? void 0 : _a.platform),
3626
+ businessCode: (params == null ? void 0 : params.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code),
3627
+ channel: params == null ? void 0 : params.channel,
3628
+ type: (params == null ? void 0 : params.type) ?? ((_d = this.otherParams) == null ? void 0 : _d.type),
3629
+ summary: latestSummary,
3630
+ enhance: params == null ? void 0 : params.enhancePayload
3631
+ });
3632
+ if (!payload.created_at) {
3633
+ payload.created_at = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
3634
+ }
3635
+ payload.need_sync = 0;
3636
+ payload.is_draft_order = 1;
3637
+ this.logInfo("saveTempOrderAsDraft calling sales draft", {
3638
+ orderId: payload.order_id,
3639
+ externalSaleNumber: payload.external_sale_number,
3640
+ productsCount: ((_e = payload.products) == null ? void 0 : _e.length) || 0
3641
+ });
3642
+ return this.request.post("/order/sales/draft", payload, {
3643
+ osServer: true,
3644
+ customToast: () => {
3645
+ }
3646
+ });
3647
+ }
3563
3648
  /**
3564
3649
  * 提交当前 Sales tempOrder。
3565
3650
  *
@@ -3760,8 +3845,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3760
3845
  }
3761
3846
  async syncPaymentsToOrder(params) {
3762
3847
  const tempOrder = this.ensureTempOrder();
3848
+ const needsPaymentNumber = (params.payments || []).some((payment) => String(payment.payment_number || "").trim() === "");
3849
+ const devicePrefix = needsPaymentNumber ? await this.getPaymentNumberDevicePrefixAsync() : "LOCAL";
3763
3850
  const mappedPayments = (0, import_utils.mapPaymentItemsToOrderPayments)(
3764
- params.payments || []
3851
+ (params.payments || []).map((payment) => this.normalizePaymentSource(payment, {
3852
+ defaultPaid: false,
3853
+ devicePrefix
3854
+ }))
3765
3855
  );
3766
3856
  const shouldConfirmPendingVoucherPayments = params.confirmPendingVoucherPayments ?? params.submitWhenPaid === true;
3767
3857
  const effectivePayments = shouldConfirmPendingVoucherPayments ? this.confirmPendingVoucherPaymentsInList(mappedPayments) : params.confirmPendingVoucherPayments === false ? this.discardPendingVoucherPaymentsFromList(mappedPayments) : mappedPayments;
@@ -4137,6 +4227,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4137
4227
  }
4138
4228
  }
4139
4229
  const nextTempOrder = this.normalizeTempOrderForRuntime(raw, { makeEditMark: true });
4230
+ const sourceLastOrderInfo = raw.lastOrderInfo || raw;
4231
+ const isDraftOrder = Number(nextTempOrder.is_draft_order || 0) === 1;
4232
+ const syntheticIdentityOptions = {
4233
+ isDraftOrder,
4234
+ externalSaleNumber: nextTempOrder.external_sale_number
4235
+ };
4140
4236
  const rawSummary = raw.summary && typeof raw.summary === "object" ? raw.summary : {};
4141
4237
  const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map((s) => ({ ...s || {} })) : (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []);
4142
4238
  this.store.tempOrder = nextTempOrder;
@@ -4157,7 +4253,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4157
4253
  productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || [])
4158
4254
  }
4159
4255
  };
4160
- this.store.lastOrderInfo = sourceRaw.lastOrderInfo || sourceRaw;
4256
+ this.store.lastOrderInfo = this.withoutSyntheticDraftOrderIdForRuntime(
4257
+ sourceLastOrderInfo,
4258
+ syntheticIdentityOptions
4259
+ );
4260
+ const hadSyntheticDraftOrderId = this.isSyntheticDraftOrderIdForRuntime(raw, syntheticIdentityOptions) || this.isSyntheticDraftOrderIdForRuntime(sourceLastOrderInfo, syntheticIdentityOptions);
4261
+ if (hadSyntheticDraftOrderId && this.store.syncState !== "submitting") {
4262
+ this.store.syncState = "local";
4263
+ }
4161
4264
  const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
4162
4265
  const currentDiscounts = typeof ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
4163
4266
  const currentScanDiscounts = currentDiscounts.filter((discount) => discount == null ? void 0 : discount.isScan);
@@ -4270,12 +4373,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4270
4373
  }
4271
4374
  normalizeTempOrderForRuntime(raw, options) {
4272
4375
  var _a, _b;
4376
+ const runtimeRaw = this.withoutSyntheticDraftOrderIdForRuntime(raw);
4273
4377
  const nextTempOrder = {
4274
4378
  ...this.createDefaultTempOrderInstance(),
4275
- ...raw || {}
4379
+ ...runtimeRaw || {}
4276
4380
  };
4277
- 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) {
4278
- nextTempOrder.order_id = raw.id;
4381
+ 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) {
4382
+ nextTempOrder.order_id = runtimeRaw.id;
4279
4383
  }
4280
4384
  delete nextTempOrder.summary;
4281
4385
  delete nextTempOrder.lastOrderInfo;
@@ -4343,6 +4447,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4343
4447
  nextTempOrder.vouchers = raw.vouchers || [];
4344
4448
  return nextTempOrder;
4345
4449
  }
4450
+ isSyntheticDraftOrderIdForRuntime(record, options) {
4451
+ const isDraftOrder = (options == null ? void 0 : options.isDraftOrder) ?? Number((record == null ? void 0 : record.is_draft_order) || 0) === 1;
4452
+ const externalSaleNumber = (record == null ? void 0 : record.external_sale_number) ?? (options == null ? void 0 : options.externalSaleNumber);
4453
+ const orderId = record == null ? void 0 : record.order_id;
4454
+ return Boolean(
4455
+ isDraftOrder && orderId !== void 0 && orderId !== null && orderId !== "" && externalSaleNumber !== void 0 && externalSaleNumber !== null && externalSaleNumber !== "" && String(orderId) === String(externalSaleNumber)
4456
+ );
4457
+ }
4458
+ withoutSyntheticDraftOrderIdForRuntime(record, options) {
4459
+ if (!this.isSyntheticDraftOrderIdForRuntime(record, options))
4460
+ return record;
4461
+ return {
4462
+ ...record,
4463
+ order_id: null
4464
+ };
4465
+ }
4346
4466
  hydrateLinkedBookingIdentity(tempOrder) {
4347
4467
  const bookingUidByProductUid = /* @__PURE__ */ new Map();
4348
4468
  const productByUid = /* @__PURE__ */ new Map();
@@ -0,0 +1,26 @@
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 isPendingOrderPayment(payment: unknown): boolean;
14
+ export declare function isIdentifiedPendingOrderPayment(payment: unknown): boolean;
15
+ export declare function hasOrderPaymentIdentityOverlap(left: unknown, right: unknown): boolean;
16
+ export declare function resolveOrderPaymentIdentity<T extends Record<string, any>>(payments: T[] | null | undefined, identity: string | number, mode?: 'payment_number' | 'compat'): OrderPaymentIdentityMatch<T> | null;
17
+ export declare function ensureOrderPaymentNumber<T extends Record<string, any>>(payment: T, devicePrefix: string, createPaymentNumber: () => string): T & {
18
+ payment_number: string;
19
+ };
20
+ export declare function mergeOrderPaymentTransactions(current: unknown, incoming: unknown): OrderPaymentTransaction[];
21
+ export declare function mergeOrderPaymentRecord<T extends Record<string, any>>(payment: T, updates: Record<string, any>): T;
22
+ export declare function mergeOrderPaymentSnapshot<T extends Record<string, any>>(current: T, incoming: T): T;
23
+ export declare function mergeOrderPaymentListsByIdentity<T extends Record<string, any>>(existing: T[] | null | undefined, incoming: T[] | null | undefined, options?: {
24
+ preserveUnmatchedExisting?: boolean;
25
+ preserveUnmatchedExistingWhen?: (payment: T) => boolean;
26
+ }): T[];
@@ -0,0 +1,224 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/modules/Order/payment-utils.ts
20
+ var payment_utils_exports = {};
21
+ __export(payment_utils_exports, {
22
+ ensureOrderPaymentNumber: () => ensureOrderPaymentNumber,
23
+ getOrderPaymentIdentityKeys: () => getOrderPaymentIdentityKeys,
24
+ hasOrderPaymentIdentityOverlap: () => hasOrderPaymentIdentityOverlap,
25
+ isIdentifiedPendingOrderPayment: () => isIdentifiedPendingOrderPayment,
26
+ isPendingOrderPayment: () => isPendingOrderPayment,
27
+ mergeOrderPaymentListsByIdentity: () => mergeOrderPaymentListsByIdentity,
28
+ mergeOrderPaymentRecord: () => mergeOrderPaymentRecord,
29
+ mergeOrderPaymentSnapshot: () => mergeOrderPaymentSnapshot,
30
+ mergeOrderPaymentTransactions: () => mergeOrderPaymentTransactions,
31
+ resolveOrderPaymentIdentity: () => resolveOrderPaymentIdentity
32
+ });
33
+ module.exports = __toCommonJS(payment_utils_exports);
34
+ var PAYMENT_IDENTITY_TYPES = [
35
+ "payment_number",
36
+ "order_payment_id",
37
+ "unique_payment_number"
38
+ ];
39
+ function normalizePaymentIdentityValue(value) {
40
+ if (value === void 0 || value === null || value === "")
41
+ return null;
42
+ return String(value);
43
+ }
44
+ function getPaymentIdentityValue(payment, type) {
45
+ var _a;
46
+ if (type === "unique_payment_number") {
47
+ return (_a = payment == null ? void 0 : payment.metadata) == null ? void 0 : _a.unique_payment_number;
48
+ }
49
+ return payment == null ? void 0 : payment[type];
50
+ }
51
+ function getOrderPaymentIdentityKeys(payment) {
52
+ const record = payment;
53
+ if (!record)
54
+ return [];
55
+ return PAYMENT_IDENTITY_TYPES.flatMap((type) => {
56
+ const value = normalizePaymentIdentityValue(getPaymentIdentityValue(record, type));
57
+ return value === null ? [] : [`${type}:${value}`];
58
+ });
59
+ }
60
+ function isPendingOrderPayment(payment) {
61
+ const record = payment;
62
+ return String((record == null ? void 0 : record.status) || "").toLowerCase() === "payment_pending";
63
+ }
64
+ function isIdentifiedPendingOrderPayment(payment) {
65
+ return isPendingOrderPayment(payment) && getOrderPaymentIdentityKeys(payment).length > 0;
66
+ }
67
+ function hasOrderPaymentIdentityOverlap(left, right) {
68
+ const leftKeys = new Set(getOrderPaymentIdentityKeys(left));
69
+ if (leftKeys.size === 0)
70
+ return false;
71
+ return getOrderPaymentIdentityKeys(right).some((key) => leftKeys.has(key));
72
+ }
73
+ function resolveOrderPaymentIdentity(payments, identity, mode = "payment_number") {
74
+ const target = String(identity);
75
+ const identityTypes = mode === "payment_number" ? ["payment_number"] : PAYMENT_IDENTITY_TYPES;
76
+ const matchesByIndex = /* @__PURE__ */ new Map();
77
+ for (const type of identityTypes) {
78
+ (payments || []).forEach((payment, index) => {
79
+ const value = normalizePaymentIdentityValue(getPaymentIdentityValue(payment, type));
80
+ if (value === target && !matchesByIndex.has(index)) {
81
+ matchesByIndex.set(index, { index, payment, matchedBy: type });
82
+ }
83
+ });
84
+ }
85
+ const matches = [...matchesByIndex.values()];
86
+ if (matches.length > 1) {
87
+ throw new Error(`支付项身份存在歧义: ${target}`);
88
+ }
89
+ return matches[0] || null;
90
+ }
91
+ function ensureOrderPaymentNumber(payment, devicePrefix, createPaymentNumber) {
92
+ const existing = normalizePaymentIdentityValue(payment.payment_number);
93
+ if (existing)
94
+ return { ...payment, payment_number: existing };
95
+ const uuid = normalizePaymentIdentityValue(payment.uuid) || createPaymentNumber();
96
+ const prefix = normalizePaymentIdentityValue(devicePrefix) || "LOCAL";
97
+ return { ...payment, payment_number: `${prefix}_${uuid}` };
98
+ }
99
+ function mergeOrderPaymentTransactions(current, incoming) {
100
+ const records = /* @__PURE__ */ new Map();
101
+ const append = (value) => {
102
+ if (!Array.isArray(value))
103
+ return;
104
+ value.forEach((item) => {
105
+ const number = item && typeof item === "object" ? String(item.number || "") : "";
106
+ const status = item && typeof item === "object" ? item.status : void 0;
107
+ if (!number || status !== "success" && status !== "fail")
108
+ return;
109
+ const previous = records.get(number);
110
+ if ((previous == null ? void 0 : previous.status) === "success" && status === "fail")
111
+ return;
112
+ records.set(number, { number, status });
113
+ });
114
+ };
115
+ append(current);
116
+ append(incoming);
117
+ return [...records.values()];
118
+ }
119
+ function mergeOrderPaymentRecord(payment, updates) {
120
+ const currentMetadata = payment.metadata || {};
121
+ const incomingMetadata = updates.metadata || {};
122
+ const transactions = mergeOrderPaymentTransactions(
123
+ currentMetadata.transactions,
124
+ incomingMetadata.transactions
125
+ );
126
+ const currentPaid = payment.status === "paid";
127
+ const nextStatus = currentPaid && updates.status !== "paid" ? "paid" : updates.status ?? payment.status;
128
+ return {
129
+ ...payment,
130
+ ...updates,
131
+ status: nextStatus,
132
+ updated_at: updates.updated_at ?? payment.updated_at,
133
+ metadata: {
134
+ ...currentMetadata,
135
+ ...incomingMetadata,
136
+ ...transactions.length > 0 || Array.isArray(incomingMetadata.transactions) ? { transactions } : {}
137
+ }
138
+ };
139
+ }
140
+ function mergeOrderPaymentSnapshot(current, incoming) {
141
+ const currentMetadata = current.metadata || {};
142
+ const incomingMetadata = incoming.metadata || {};
143
+ const currentUniquePaymentNumber = normalizePaymentIdentityValue(
144
+ currentMetadata.unique_payment_number
145
+ );
146
+ const incomingUniquePaymentNumber = normalizePaymentIdentityValue(
147
+ incomingMetadata.unique_payment_number
148
+ );
149
+ const incomingOrderPaymentId = normalizePaymentIdentityValue(
150
+ incoming.order_payment_id
151
+ );
152
+ const incomingFallbackPrefix = incomingOrderPaymentId ? `os-fallback:payment:order-payment:${incomingOrderPaymentId}` : null;
153
+ const incomingUsesDerivedUniquePaymentNumber = Boolean(
154
+ incomingUniquePaymentNumber && incomingFallbackPrefix && (incomingUniquePaymentNumber === incomingFallbackPrefix || incomingUniquePaymentNumber.startsWith(`${incomingFallbackPrefix}:conflict:`))
155
+ );
156
+ const transactions = mergeOrderPaymentTransactions(
157
+ currentMetadata.transactions,
158
+ incomingMetadata.transactions
159
+ );
160
+ return {
161
+ ...current,
162
+ ...incoming,
163
+ order_payment_id: normalizePaymentIdentityValue(incoming.order_payment_id) !== null ? incoming.order_payment_id : current.order_payment_id,
164
+ payment_number: incoming.payment_number || current.payment_number,
165
+ metadata: {
166
+ ...currentMetadata,
167
+ ...incomingMetadata,
168
+ ...incomingUsesDerivedUniquePaymentNumber && currentUniquePaymentNumber ? { unique_payment_number: currentUniquePaymentNumber } : {},
169
+ ...transactions.length > 0 ? { transactions } : {}
170
+ }
171
+ };
172
+ }
173
+ function compactOrderPaymentList(payments) {
174
+ const result = [];
175
+ for (const payment of payments) {
176
+ const matchingIndexes = result.flatMap((existing, index) => hasOrderPaymentIdentityOverlap(existing, payment) ? [index] : []);
177
+ if (matchingIndexes.length === 0) {
178
+ result.push(mergeOrderPaymentSnapshot({}, payment));
179
+ continue;
180
+ }
181
+ const firstIndex = matchingIndexes[0];
182
+ let merged = result[firstIndex];
183
+ for (const index of matchingIndexes.slice(1)) {
184
+ merged = mergeOrderPaymentSnapshot(merged, result[index]);
185
+ }
186
+ result[firstIndex] = mergeOrderPaymentSnapshot(merged, payment);
187
+ for (const index of matchingIndexes.slice(1).sort((a, b) => b - a)) {
188
+ result.splice(index, 1);
189
+ }
190
+ }
191
+ return result;
192
+ }
193
+ function mergeOrderPaymentListsByIdentity(existing, incoming, options = {}) {
194
+ const existingList = compactOrderPaymentList([...existing || []]);
195
+ const incomingList = compactOrderPaymentList([...incoming || []]);
196
+ if (options.preserveUnmatchedExisting) {
197
+ return compactOrderPaymentList([...existingList, ...incomingList]);
198
+ }
199
+ const mergedIncoming = incomingList.map((incomingPayment) => {
200
+ const matchingExisting = existingList.filter((existingPayment) => hasOrderPaymentIdentityOverlap(existingPayment, incomingPayment));
201
+ return matchingExisting.reduce(
202
+ (merged, existingPayment) => mergeOrderPaymentSnapshot(existingPayment, merged),
203
+ incomingPayment
204
+ );
205
+ });
206
+ const preservedExisting = options.preserveUnmatchedExistingWhen ? existingList.filter((existingPayment) => {
207
+ var _a;
208
+ return !incomingList.some((incomingPayment) => hasOrderPaymentIdentityOverlap(existingPayment, incomingPayment)) && ((_a = options.preserveUnmatchedExistingWhen) == null ? void 0 : _a.call(options, existingPayment));
209
+ }) : [];
210
+ return compactOrderPaymentList([...mergedIncoming, ...preservedExisting]);
211
+ }
212
+ // Annotate the CommonJS export names for ESM import in node:
213
+ 0 && (module.exports = {
214
+ ensureOrderPaymentNumber,
215
+ getOrderPaymentIdentityKeys,
216
+ hasOrderPaymentIdentityOverlap,
217
+ isIdentifiedPendingOrderPayment,
218
+ isPendingOrderPayment,
219
+ mergeOrderPaymentListsByIdentity,
220
+ mergeOrderPaymentRecord,
221
+ mergeOrderPaymentSnapshot,
222
+ mergeOrderPaymentTransactions,
223
+ resolveOrderPaymentIdentity
224
+ });