@pisell/pisellos 2.3.29 → 2.3.31

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 (48) 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 +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.js +4 -4
  7. package/dist/modules/Payment/index.d.ts +2 -0
  8. package/dist/modules/Payment/index.js +78 -49
  9. package/dist/modules/Payment/types.d.ts +26 -24
  10. package/dist/modules/Payment/types.js +2 -0
  11. package/dist/server/index.d.ts +14 -0
  12. package/dist/server/index.js +1850 -1024
  13. package/dist/server/modules/order/index.d.ts +40 -3
  14. package/dist/server/modules/order/index.js +1200 -501
  15. package/dist/server/modules/order/types.d.ts +11 -3
  16. package/dist/server/modules/order/types.js +1 -1
  17. package/dist/solution/BaseSales/index.d.ts +33 -3
  18. package/dist/solution/BaseSales/index.js +609 -322
  19. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
  20. package/dist/solution/BookingByStep/index.d.ts +1 -1
  21. package/dist/solution/BookingTicket/index.d.ts +1 -1
  22. package/dist/solution/BookingTicket/index.js +2 -1
  23. package/dist/utils/payment-number.d.ts +9 -0
  24. package/dist/utils/payment-number.js +69 -0
  25. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  26. package/lib/modules/Order/index.d.ts +27 -8
  27. package/lib/modules/Order/index.js +180 -60
  28. package/lib/modules/Order/payment-utils.d.ts +23 -0
  29. package/lib/modules/Order/payment-utils.js +193 -0
  30. package/lib/modules/Order/types.d.ts +33 -1
  31. package/lib/modules/Order/utils.js +2 -3
  32. package/lib/modules/Payment/index.d.ts +2 -0
  33. package/lib/modules/Payment/index.js +33 -12
  34. package/lib/modules/Payment/types.d.ts +26 -24
  35. package/lib/server/index.d.ts +14 -0
  36. package/lib/server/index.js +604 -8
  37. package/lib/server/modules/order/index.d.ts +40 -3
  38. package/lib/server/modules/order/index.js +434 -31
  39. package/lib/server/modules/order/types.d.ts +11 -3
  40. package/lib/solution/BaseSales/index.d.ts +33 -3
  41. package/lib/solution/BaseSales/index.js +167 -7
  42. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +6 -1
  43. package/lib/solution/BookingByStep/index.d.ts +1 -1
  44. package/lib/solution/BookingTicket/index.d.ts +1 -1
  45. package/lib/solution/BookingTicket/index.js +2 -1
  46. package/lib/utils/payment-number.d.ts +9 -0
  47. package/lib/utils/payment-number.js +64 -0
  48. 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;
@@ -3496,6 +3549,38 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3496
3549
  await this.saveDraft();
3497
3550
  return tempOrder;
3498
3551
  }
3552
+ async saveTempOrderAsDraft(params) {
3553
+ var _a, _b, _c, _d, _e;
3554
+ const tempOrder = this.ensureTempOrder();
3555
+ this.ensureExternalSaleNumber(tempOrder);
3556
+ this.persistTempOrder();
3557
+ const latestSummary = await this.recalculateSummary({ createIfMissing: true }) || this.store.summary || (0, import_utils.createEmptySummary)();
3558
+ const payload = (0, import_utils.buildSubmitPayload)({
3559
+ tempOrder,
3560
+ cacheId: (params == null ? void 0 : params.cacheId) ?? this.cacheId,
3561
+ platform: (params == null ? void 0 : params.platform) || ((_a = this.otherParams) == null ? void 0 : _a.platform),
3562
+ businessCode: (params == null ? void 0 : params.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code),
3563
+ channel: params == null ? void 0 : params.channel,
3564
+ type: (params == null ? void 0 : params.type) ?? ((_d = this.otherParams) == null ? void 0 : _d.type),
3565
+ summary: latestSummary,
3566
+ enhance: params == null ? void 0 : params.enhancePayload
3567
+ });
3568
+ if (!payload.created_at) {
3569
+ payload.created_at = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
3570
+ }
3571
+ payload.need_sync = 0;
3572
+ payload.is_draft_order = 1;
3573
+ this.logInfo("saveTempOrderAsDraft calling sales draft", {
3574
+ orderId: payload.order_id,
3575
+ externalSaleNumber: payload.external_sale_number,
3576
+ productsCount: ((_e = payload.products) == null ? void 0 : _e.length) || 0
3577
+ });
3578
+ return this.request.post("/order/sales/draft", payload, {
3579
+ osServer: true,
3580
+ customToast: () => {
3581
+ }
3582
+ });
3583
+ }
3499
3584
  /**
3500
3585
  * 提交当前 Sales tempOrder。
3501
3586
  *
@@ -3696,8 +3781,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
3696
3781
  }
3697
3782
  async syncPaymentsToOrder(params) {
3698
3783
  const tempOrder = this.ensureTempOrder();
3784
+ const needsPaymentNumber = (params.payments || []).some((payment) => String(payment.payment_number || "").trim() === "");
3785
+ const devicePrefix = needsPaymentNumber ? await this.getPaymentNumberDevicePrefixAsync() : "LOCAL";
3699
3786
  const mappedPayments = (0, import_utils.mapPaymentItemsToOrderPayments)(
3700
- params.payments || []
3787
+ (params.payments || []).map((payment) => this.normalizePaymentSource(payment, {
3788
+ defaultPaid: false,
3789
+ devicePrefix
3790
+ }))
3701
3791
  );
3702
3792
  const shouldConfirmPendingVoucherPayments = params.confirmPendingVoucherPayments ?? params.submitWhenPaid === true;
3703
3793
  const effectivePayments = shouldConfirmPendingVoucherPayments ? this.confirmPendingVoucherPaymentsInList(mappedPayments) : params.confirmPendingVoucherPayments === false ? this.discardPendingVoucherPaymentsFromList(mappedPayments) : mappedPayments;
@@ -4073,6 +4163,12 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4073
4163
  }
4074
4164
  }
4075
4165
  const nextTempOrder = this.normalizeTempOrderForRuntime(raw, { makeEditMark: true });
4166
+ const sourceLastOrderInfo = raw.lastOrderInfo || raw;
4167
+ const isDraftOrder = Number(nextTempOrder.is_draft_order || 0) === 1;
4168
+ const syntheticIdentityOptions = {
4169
+ isDraftOrder,
4170
+ externalSaleNumber: nextTempOrder.external_sale_number
4171
+ };
4076
4172
  const rawSummary = raw.summary && typeof raw.summary === "object" ? raw.summary : {};
4077
4173
  const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map((s) => ({ ...s || {} })) : (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []);
4078
4174
  this.store.tempOrder = nextTempOrder;
@@ -4093,7 +4189,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4093
4189
  productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || [])
4094
4190
  }
4095
4191
  };
4096
- this.store.lastOrderInfo = sourceRaw.lastOrderInfo || sourceRaw;
4192
+ this.store.lastOrderInfo = this.withoutSyntheticDraftOrderIdForRuntime(
4193
+ sourceLastOrderInfo,
4194
+ syntheticIdentityOptions
4195
+ );
4196
+ const hadSyntheticDraftOrderId = this.isSyntheticDraftOrderIdForRuntime(raw, syntheticIdentityOptions) || this.isSyntheticDraftOrderIdForRuntime(sourceLastOrderInfo, syntheticIdentityOptions);
4197
+ if (hadSyntheticDraftOrderId && this.store.syncState !== "submitting") {
4198
+ this.store.syncState = "local";
4199
+ }
4097
4200
  const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
4098
4201
  const currentDiscounts = typeof ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
4099
4202
  const currentScanDiscounts = currentDiscounts.filter((discount) => discount == null ? void 0 : discount.isScan);
@@ -4206,12 +4309,13 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4206
4309
  }
4207
4310
  normalizeTempOrderForRuntime(raw, options) {
4208
4311
  var _a, _b;
4312
+ const runtimeRaw = this.withoutSyntheticDraftOrderIdForRuntime(raw);
4209
4313
  const nextTempOrder = {
4210
4314
  ...this.createDefaultTempOrderInstance(),
4211
- ...raw || {}
4315
+ ...runtimeRaw || {}
4212
4316
  };
4213
- 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) {
4214
- nextTempOrder.order_id = raw.id;
4317
+ 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) {
4318
+ nextTempOrder.order_id = runtimeRaw.id;
4215
4319
  }
4216
4320
  delete nextTempOrder.summary;
4217
4321
  delete nextTempOrder.lastOrderInfo;
@@ -4279,6 +4383,22 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4279
4383
  nextTempOrder.vouchers = raw.vouchers || [];
4280
4384
  return nextTempOrder;
4281
4385
  }
4386
+ isSyntheticDraftOrderIdForRuntime(record, options) {
4387
+ const isDraftOrder = (options == null ? void 0 : options.isDraftOrder) ?? Number((record == null ? void 0 : record.is_draft_order) || 0) === 1;
4388
+ const externalSaleNumber = (record == null ? void 0 : record.external_sale_number) ?? (options == null ? void 0 : options.externalSaleNumber);
4389
+ const orderId = record == null ? void 0 : record.order_id;
4390
+ return Boolean(
4391
+ isDraftOrder && orderId !== void 0 && orderId !== null && orderId !== "" && externalSaleNumber !== void 0 && externalSaleNumber !== null && externalSaleNumber !== "" && String(orderId) === String(externalSaleNumber)
4392
+ );
4393
+ }
4394
+ withoutSyntheticDraftOrderIdForRuntime(record, options) {
4395
+ if (!this.isSyntheticDraftOrderIdForRuntime(record, options))
4396
+ return record;
4397
+ return {
4398
+ ...record,
4399
+ order_id: null
4400
+ };
4401
+ }
4282
4402
  hydrateLinkedBookingIdentity(tempOrder) {
4283
4403
  const bookingUidByProductUid = /* @__PURE__ */ new Map();
4284
4404
  const productByUid = /* @__PURE__ */ new Map();
@@ -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[];
@@ -0,0 +1,193 @@
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
+ mergeOrderPaymentListsByIdentity: () => mergeOrderPaymentListsByIdentity,
26
+ mergeOrderPaymentRecord: () => mergeOrderPaymentRecord,
27
+ mergeOrderPaymentSnapshot: () => mergeOrderPaymentSnapshot,
28
+ mergeOrderPaymentTransactions: () => mergeOrderPaymentTransactions,
29
+ resolveOrderPaymentIdentity: () => resolveOrderPaymentIdentity
30
+ });
31
+ module.exports = __toCommonJS(payment_utils_exports);
32
+ var PAYMENT_IDENTITY_TYPES = [
33
+ "payment_number",
34
+ "order_payment_id",
35
+ "unique_payment_number"
36
+ ];
37
+ function normalizePaymentIdentityValue(value) {
38
+ if (value === void 0 || value === null || value === "")
39
+ return null;
40
+ return String(value);
41
+ }
42
+ function getPaymentIdentityValue(payment, type) {
43
+ var _a;
44
+ if (type === "unique_payment_number") {
45
+ return (_a = payment == null ? void 0 : payment.metadata) == null ? void 0 : _a.unique_payment_number;
46
+ }
47
+ return payment == null ? void 0 : payment[type];
48
+ }
49
+ function getOrderPaymentIdentityKeys(payment) {
50
+ const record = payment;
51
+ if (!record)
52
+ return [];
53
+ return PAYMENT_IDENTITY_TYPES.flatMap((type) => {
54
+ const value = normalizePaymentIdentityValue(getPaymentIdentityValue(record, type));
55
+ return value === null ? [] : [`${type}:${value}`];
56
+ });
57
+ }
58
+ function hasOrderPaymentIdentityOverlap(left, right) {
59
+ const leftKeys = new Set(getOrderPaymentIdentityKeys(left));
60
+ if (leftKeys.size === 0)
61
+ return false;
62
+ return getOrderPaymentIdentityKeys(right).some((key) => leftKeys.has(key));
63
+ }
64
+ function resolveOrderPaymentIdentity(payments, identity, mode = "payment_number") {
65
+ const target = String(identity);
66
+ const identityTypes = mode === "payment_number" ? ["payment_number"] : PAYMENT_IDENTITY_TYPES;
67
+ const matchesByIndex = /* @__PURE__ */ new Map();
68
+ for (const type of identityTypes) {
69
+ (payments || []).forEach((payment, index) => {
70
+ const value = normalizePaymentIdentityValue(getPaymentIdentityValue(payment, type));
71
+ if (value === target && !matchesByIndex.has(index)) {
72
+ matchesByIndex.set(index, { index, payment, matchedBy: type });
73
+ }
74
+ });
75
+ }
76
+ const matches = [...matchesByIndex.values()];
77
+ if (matches.length > 1) {
78
+ throw new Error(`支付项身份存在歧义: ${target}`);
79
+ }
80
+ return matches[0] || null;
81
+ }
82
+ function ensureOrderPaymentNumber(payment, devicePrefix, createPaymentNumber) {
83
+ const existing = normalizePaymentIdentityValue(payment.payment_number);
84
+ if (existing)
85
+ return { ...payment, payment_number: existing };
86
+ const uuid = normalizePaymentIdentityValue(payment.uuid) || createPaymentNumber();
87
+ const prefix = normalizePaymentIdentityValue(devicePrefix) || "LOCAL";
88
+ return { ...payment, payment_number: `${prefix}_${uuid}` };
89
+ }
90
+ function mergeOrderPaymentTransactions(current, incoming) {
91
+ const records = /* @__PURE__ */ new Map();
92
+ const append = (value) => {
93
+ if (!Array.isArray(value))
94
+ return;
95
+ value.forEach((item) => {
96
+ const number = item && typeof item === "object" ? String(item.number || "") : "";
97
+ const status = item && typeof item === "object" ? item.status : void 0;
98
+ if (!number || status !== "success" && status !== "fail")
99
+ return;
100
+ const previous = records.get(number);
101
+ if ((previous == null ? void 0 : previous.status) === "success" && status === "fail")
102
+ return;
103
+ records.set(number, { number, status });
104
+ });
105
+ };
106
+ append(current);
107
+ append(incoming);
108
+ return [...records.values()];
109
+ }
110
+ function mergeOrderPaymentRecord(payment, updates) {
111
+ const currentMetadata = payment.metadata || {};
112
+ const incomingMetadata = updates.metadata || {};
113
+ const transactions = mergeOrderPaymentTransactions(
114
+ currentMetadata.transactions,
115
+ incomingMetadata.transactions
116
+ );
117
+ const currentPaid = payment.status === "paid";
118
+ const nextStatus = currentPaid && updates.status !== "paid" ? "paid" : updates.status ?? payment.status;
119
+ return {
120
+ ...payment,
121
+ ...updates,
122
+ status: nextStatus,
123
+ updated_at: updates.updated_at ?? payment.updated_at,
124
+ metadata: {
125
+ ...currentMetadata,
126
+ ...incomingMetadata,
127
+ ...transactions.length > 0 || Array.isArray(incomingMetadata.transactions) ? { transactions } : {}
128
+ }
129
+ };
130
+ }
131
+ function mergeOrderPaymentSnapshot(current, incoming) {
132
+ const currentMetadata = current.metadata || {};
133
+ const incomingMetadata = incoming.metadata || {};
134
+ const transactions = mergeOrderPaymentTransactions(
135
+ currentMetadata.transactions,
136
+ incomingMetadata.transactions
137
+ );
138
+ return {
139
+ ...current,
140
+ ...incoming,
141
+ payment_number: incoming.payment_number || current.payment_number,
142
+ metadata: {
143
+ ...currentMetadata,
144
+ ...incomingMetadata,
145
+ ...transactions.length > 0 ? { transactions } : {}
146
+ }
147
+ };
148
+ }
149
+ function compactOrderPaymentList(payments) {
150
+ const result = [];
151
+ for (const payment of payments) {
152
+ const matchingIndexes = result.flatMap((existing, index) => hasOrderPaymentIdentityOverlap(existing, payment) ? [index] : []);
153
+ if (matchingIndexes.length === 0) {
154
+ result.push(mergeOrderPaymentSnapshot({}, payment));
155
+ continue;
156
+ }
157
+ const firstIndex = matchingIndexes[0];
158
+ let merged = result[firstIndex];
159
+ for (const index of matchingIndexes.slice(1)) {
160
+ merged = mergeOrderPaymentSnapshot(merged, result[index]);
161
+ }
162
+ result[firstIndex] = mergeOrderPaymentSnapshot(merged, payment);
163
+ for (const index of matchingIndexes.slice(1).sort((a, b) => b - a)) {
164
+ result.splice(index, 1);
165
+ }
166
+ }
167
+ return result;
168
+ }
169
+ function mergeOrderPaymentListsByIdentity(existing, incoming, options = {}) {
170
+ const existingList = compactOrderPaymentList([...existing || []]);
171
+ const incomingList = compactOrderPaymentList([...incoming || []]);
172
+ if (options.preserveUnmatchedExisting) {
173
+ return compactOrderPaymentList([...existingList, ...incomingList]);
174
+ }
175
+ return compactOrderPaymentList(incomingList.map((incomingPayment) => {
176
+ const matchingExisting = existingList.filter((existingPayment) => hasOrderPaymentIdentityOverlap(existingPayment, incomingPayment));
177
+ return matchingExisting.reduce(
178
+ (merged, existingPayment) => mergeOrderPaymentSnapshot(existingPayment, merged),
179
+ incomingPayment
180
+ );
181
+ }));
182
+ }
183
+ // Annotate the CommonJS export names for ESM import in node:
184
+ 0 && (module.exports = {
185
+ ensureOrderPaymentNumber,
186
+ getOrderPaymentIdentityKeys,
187
+ hasOrderPaymentIdentityOverlap,
188
+ mergeOrderPaymentListsByIdentity,
189
+ mergeOrderPaymentRecord,
190
+ mergeOrderPaymentSnapshot,
191
+ mergeOrderPaymentTransactions,
192
+ resolveOrderPaymentIdentity
193
+ });
@@ -468,6 +468,8 @@ export interface SubmitSalesOrderParams {
468
468
  export interface PaymentItemData {
469
469
  /** 当前支付项的唯一 ID */
470
470
  uuid: string;
471
+ /** 支付项稳定唯一号 */
472
+ payment_number?: string;
471
473
  /** 当前支付方式付出去多少钱 */
472
474
  amount: string;
473
475
  /** 支付类型代码 */
@@ -490,13 +492,22 @@ export interface PaymentItemData {
490
492
  export interface OrderPaymentMetadata {
491
493
  rounding_rule?: Record<string, any>;
492
494
  unique_payment_number?: string;
495
+ /** 刷卡机设备快照;OS 不解析内部字段,仅透传并持久化 */
496
+ card_reader_snapshot?: Record<string, unknown>;
493
497
  shop_wallet_pass_id?: number | string;
494
498
  actual_paid_amount?: number | string;
495
499
  change_given_amount?: number | string;
500
+ transactions?: OrderPaymentTransaction[];
496
501
  [key: string]: any;
497
502
  }
503
+ export interface OrderPaymentTransaction {
504
+ number: string;
505
+ status: 'success' | 'fail';
506
+ }
498
507
  export interface OrderPaymentData {
499
508
  order_payment_id?: number | string;
509
+ /** 支付项稳定唯一号;历史支付项允许缺失 */
510
+ payment_number?: string;
500
511
  amount: string;
501
512
  code: string;
502
513
  custom_payment_id: number;
@@ -523,6 +534,15 @@ export interface OrderPaymentData {
523
534
  created_at?: string;
524
535
  updated_at?: string;
525
536
  }
537
+ export interface OrderPaymentUpdateOptions {
538
+ matchBy?: 'payment_number' | 'compat' | 'legacy';
539
+ }
540
+ export interface OrderPaymentUpdateResult {
541
+ updated: boolean;
542
+ payment: OrderPaymentData | null;
543
+ payments: OrderPaymentData[];
544
+ summary: OrderSummary | null;
545
+ }
526
546
  export type OrderPaymentSource = PaymentItem | OrderPaymentData | Record<string, any>;
527
547
  export interface MapOrderPaymentsOptions {
528
548
  includeVoided?: boolean;
@@ -673,6 +693,14 @@ export interface OrderModuleAPI {
673
693
  channel?: string;
674
694
  type?: string;
675
695
  }) => OrderSubmitPayload;
696
+ saveTempOrderAsDraft: <T = any>(params?: {
697
+ cacheId?: string;
698
+ platform?: string;
699
+ businessCode?: string;
700
+ channel?: string;
701
+ type?: string;
702
+ enhancePayload?: SubmitPayloadEnhancer;
703
+ }) => Promise<T>;
676
704
  applyLocalPrintOrderNumbers: (order?: Record<string, any> | null) => Promise<OrderTempOrder>;
677
705
  getTempOrderNote: () => string;
678
706
  updateTempOrderNote: {
@@ -730,11 +758,15 @@ export interface OrderModuleAPI {
730
758
  getOrderPayments: () => OrderPaymentData[];
731
759
  setOrderPayments: (payments: OrderPaymentSource[]) => OrderPaymentData[];
732
760
  addOrderPayment: (payment: OrderPaymentSource) => OrderPaymentData[];
733
- updateOrderPayment: (paymentIdentity: string | number, updates: Partial<OrderPaymentData> & Record<string, any>) => OrderPaymentData[];
761
+ addOrderPaymentAsync: (payment: OrderPaymentSource) => Promise<OrderPaymentData[]>;
762
+ updateOrderPayment: (paymentIdentity: string | number, updates: Partial<OrderPaymentData> & Record<string, any>, options?: OrderPaymentUpdateOptions) => Promise<OrderPaymentUpdateResult>;
734
763
  deleteOrderPayment: (paymentIdentity: string | number) => OrderPaymentData[];
735
764
  updateVoucherOrderPayments: (payments: OrderPaymentSource[], options?: {
736
765
  status?: 'paid' | 'payment_pending';
737
766
  }) => OrderPaymentData[];
767
+ updateVoucherOrderPaymentsAsync: (payments: OrderPaymentSource[], options?: {
768
+ status?: 'paid' | 'payment_pending';
769
+ }) => Promise<OrderPaymentData[]>;
738
770
  confirmPendingVoucherPayments: (options?: {
739
771
  persist?: boolean;
740
772
  recalculateSummary?: boolean;