@pisell/pisellos 2.3.33 → 2.3.34

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.
@@ -10,6 +10,8 @@ export interface OrderPaymentIdentityMatch<T> {
10
10
  matchedBy: OrderPaymentIdentityType;
11
11
  }
12
12
  export declare function getOrderPaymentIdentityKeys(payment: unknown): string[];
13
+ export declare function isPendingOrderPayment(payment: unknown): boolean;
14
+ export declare function isIdentifiedPendingOrderPayment(payment: unknown): boolean;
13
15
  export declare function hasOrderPaymentIdentityOverlap(left: unknown, right: unknown): boolean;
14
16
  export declare function resolveOrderPaymentIdentity<T extends Record<string, any>>(payments: T[] | null | undefined, identity: string | number, mode?: 'payment_number' | 'compat'): OrderPaymentIdentityMatch<T> | null;
15
17
  export declare function ensureOrderPaymentNumber<T extends Record<string, any>>(payment: T, devicePrefix: string, createPaymentNumber: () => string): T & {
@@ -20,4 +22,5 @@ export declare function mergeOrderPaymentRecord<T extends Record<string, any>>(p
20
22
  export declare function mergeOrderPaymentSnapshot<T extends Record<string, any>>(current: T, incoming: T): T;
21
23
  export declare function mergeOrderPaymentListsByIdentity<T extends Record<string, any>>(existing: T[] | null | undefined, incoming: T[] | null | undefined, options?: {
22
24
  preserveUnmatchedExisting?: boolean;
25
+ preserveUnmatchedExistingWhen?: (payment: T) => boolean;
23
26
  }): T[];
@@ -31,6 +31,13 @@ export function getOrderPaymentIdentityKeys(payment) {
31
31
  return value === null ? [] : ["".concat(type, ":").concat(value)];
32
32
  });
33
33
  }
34
+ export function isPendingOrderPayment(payment) {
35
+ var record = payment;
36
+ return String((record === null || record === void 0 ? void 0 : record.status) || '').toLowerCase() === 'payment_pending';
37
+ }
38
+ export function isIdentifiedPendingOrderPayment(payment) {
39
+ return isPendingOrderPayment(payment) && getOrderPaymentIdentityKeys(payment).length > 0;
40
+ }
34
41
  export function hasOrderPaymentIdentityOverlap(left, right) {
35
42
  var leftKeys = new Set(getOrderPaymentIdentityKeys(left));
36
43
  if (leftKeys.size === 0) return false;
@@ -123,10 +130,18 @@ export function mergeOrderPaymentRecord(payment, updates) {
123
130
  export function mergeOrderPaymentSnapshot(current, incoming) {
124
131
  var currentMetadata = current.metadata || {};
125
132
  var incomingMetadata = incoming.metadata || {};
133
+ var currentUniquePaymentNumber = normalizePaymentIdentityValue(currentMetadata.unique_payment_number);
134
+ var incomingUniquePaymentNumber = normalizePaymentIdentityValue(incomingMetadata.unique_payment_number);
135
+ var incomingOrderPaymentId = normalizePaymentIdentityValue(incoming.order_payment_id);
136
+ var incomingFallbackPrefix = incomingOrderPaymentId ? "os-fallback:payment:order-payment:".concat(incomingOrderPaymentId) : null;
137
+ var incomingUsesDerivedUniquePaymentNumber = Boolean(incomingUniquePaymentNumber && incomingFallbackPrefix && (incomingUniquePaymentNumber === incomingFallbackPrefix || incomingUniquePaymentNumber.startsWith("".concat(incomingFallbackPrefix, ":conflict:"))));
126
138
  var transactions = mergeOrderPaymentTransactions(currentMetadata.transactions, incomingMetadata.transactions);
127
139
  return _objectSpread(_objectSpread(_objectSpread({}, current), incoming), {}, {
140
+ order_payment_id: normalizePaymentIdentityValue(incoming.order_payment_id) !== null ? incoming.order_payment_id : current.order_payment_id,
128
141
  payment_number: incoming.payment_number || current.payment_number,
129
- metadata: _objectSpread(_objectSpread(_objectSpread({}, currentMetadata), incomingMetadata), transactions.length > 0 ? {
142
+ metadata: _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, currentMetadata), incomingMetadata), incomingUsesDerivedUniquePaymentNumber && currentUniquePaymentNumber ? {
143
+ unique_payment_number: currentUniquePaymentNumber
144
+ } : {}), transactions.length > 0 ? {
130
145
  transactions: transactions
131
146
  } : {})
132
147
  });
@@ -192,12 +207,19 @@ export function mergeOrderPaymentListsByIdentity(existing, incoming) {
192
207
  if (options.preserveUnmatchedExisting) {
193
208
  return compactOrderPaymentList([].concat(_toConsumableArray(existingList), _toConsumableArray(incomingList)));
194
209
  }
195
- return compactOrderPaymentList(incomingList.map(function (incomingPayment) {
210
+ var mergedIncoming = incomingList.map(function (incomingPayment) {
196
211
  var matchingExisting = existingList.filter(function (existingPayment) {
197
212
  return hasOrderPaymentIdentityOverlap(existingPayment, incomingPayment);
198
213
  });
199
214
  return matchingExisting.reduce(function (merged, existingPayment) {
200
215
  return mergeOrderPaymentSnapshot(existingPayment, merged);
201
216
  }, incomingPayment);
202
- }));
217
+ });
218
+ var preservedExisting = options.preserveUnmatchedExistingWhen ? existingList.filter(function (existingPayment) {
219
+ var _options$preserveUnma;
220
+ return !incomingList.some(function (incomingPayment) {
221
+ return hasOrderPaymentIdentityOverlap(existingPayment, incomingPayment);
222
+ }) && ((_options$preserveUnma = options.preserveUnmatchedExistingWhen) === null || _options$preserveUnma === void 0 ? void 0 : _options$preserveUnma.call(options, existingPayment));
223
+ }) : [];
224
+ return compactOrderPaymentList([].concat(_toConsumableArray(mergedIncoming), _toConsumableArray(preservedExisting)));
203
225
  }
@@ -209,6 +209,11 @@ export function normalizeOrderCollection(kind, items, options) {
209
209
  var persistentId = getOrderCollectionPersistentId(kind, item);
210
210
  var uid = getOrderCollectionUid(kind, item);
211
211
  if (!uid) {
212
+ var _item;
213
+ if (kind === 'payment' && !isBlankOrderCollectionIdentity((_item = item) === null || _item === void 0 ? void 0 : _item.payment_number)) {
214
+ // payment_number 已提供稳定身份,不占用真实交易流水字段作为内部 UID。
215
+ continue;
216
+ }
212
217
  uid = persistentId ? buildOrderCollectionFallbackUid(kind, persistentId) : allocateAnonymousUid(occupiedUids, createAnonymousUid);
213
218
  item = setOrderCollectionUid(kind, item, uid);
214
219
  result[index] = item;
@@ -216,7 +221,7 @@ export function normalizeOrderCollection(kind, items, options) {
216
221
  if (!persistentId) stats.anonymousRowCount += 1;
217
222
  }
218
223
  if (occupiedUids.has(uid)) {
219
- var _item, _item2, _item3, _item4;
224
+ var _item2, _item3, _item4, _item5;
220
225
  var replacementUid = persistentId ? allocatePersistentConflictUid(kind, persistentId, occupiedUids) : allocateAnonymousUid(occupiedUids, createAnonymousUid);
221
226
  result[index] = setOrderCollectionUid(kind, item, replacementUid);
222
227
  uidRemaps.push({
@@ -225,7 +230,7 @@ export function normalizeOrderCollection(kind, items, options) {
225
230
  to: replacementUid,
226
231
  persistentId: persistentId,
227
232
  scope: 'linked-owner',
228
- referenceOwnerUid: kind === 'product' ? String(((_item = item) === null || _item === void 0 ? void 0 : _item.booking_uid) || ((_item2 = item) === null || _item2 === void 0 || (_item2 = _item2.metadata) === null || _item2 === void 0 ? void 0 : _item2.booking_uid) || '') || null : kind === 'booking' ? String(((_item3 = item) === null || _item3 === void 0 ? void 0 : _item3.product_uid) || ((_item4 = item) === null || _item4 === void 0 || (_item4 = _item4.metadata) === null || _item4 === void 0 ? void 0 : _item4.product_uid) || '') || null : null
233
+ referenceOwnerUid: kind === 'product' ? String(((_item2 = item) === null || _item2 === void 0 ? void 0 : _item2.booking_uid) || ((_item3 = item) === null || _item3 === void 0 || (_item3 = _item3.metadata) === null || _item3 === void 0 ? void 0 : _item3.booking_uid) || '') || null : kind === 'booking' ? String(((_item4 = item) === null || _item4 === void 0 ? void 0 : _item4.product_uid) || ((_item5 = item) === null || _item5 === void 0 || (_item5 = _item5.metadata) === null || _item5 === void 0 ? void 0 : _item5.product_uid) || '') || null : null
229
234
  });
230
235
  uid = replacementUid;
231
236
  stats.uidConflictCount += 1;
@@ -121,6 +121,8 @@ declare class Server {
121
121
  private handleSyncSalesTask;
122
122
  private runCheckoutSync;
123
123
  private omitCheckoutSyncMode;
124
+ private buildRemoteCheckoutData;
125
+ private mergeCheckoutSyncPayments;
124
126
  private persistSyncedCheckoutOrder;
125
127
  /**
126
128
  * 将普通层 QuotationModule 的报价单计算能力桥接到 Server Products 模块。
@@ -23,6 +23,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
23
23
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
24
24
  import dayjs from 'dayjs';
25
25
  import Decimal from 'decimal.js';
26
+ import { cloneDeep } from 'lodash-es';
26
27
  import { ProductsModule } from "./modules/products";
27
28
  import { MenuModule } from "./modules/menu";
28
29
  import { QuotationModule } from "./modules/quotation";
@@ -40,6 +41,7 @@ import { filterOrders } from "./modules/order/utils/filterOrders";
40
41
  import { filterBookingsFromOrders, sortBookings } from "./modules/order/utils/filterBookings";
41
42
  import { buildSmallTicketData, hasSmallTicketData } from "./utils/small-ticket";
42
43
  import { BaseSalesImpl } from "../solution/BaseSales";
44
+ import { getOrderPaymentIdentityKeys, isIdentifiedPendingOrderPayment, isPendingOrderPayment, mergeOrderPaymentListsByIdentity } from "../modules/Order/payment-utils";
43
45
 
44
46
  // 重新导出类型供外部使用
45
47
 
@@ -2472,7 +2474,7 @@ var Server = /*#__PURE__*/function () {
2472
2474
  return this.ensureCheckoutOrderNumbers(normalizedData, title);
2473
2475
  case 6:
2474
2476
  checkoutData = _context31.sent;
2475
- remoteCheckoutData = this.omitCheckoutSyncMode(checkoutData);
2477
+ remoteCheckoutData = this.buildRemoteCheckoutData(checkoutData, title);
2476
2478
  if ((_this$app6 = this.app) !== null && _this$app6 !== void 0 && (_this$app6 = _this$app6.request) !== null && _this$app6 !== void 0 && _this$app6.post) {
2477
2479
  _context31.next = 10;
2478
2480
  break;
@@ -2496,18 +2498,18 @@ var Server = /*#__PURE__*/function () {
2496
2498
  errorResponse: response,
2497
2499
  response: response,
2498
2500
  normalizedResponse: this.normalizeCheckoutResponse(response),
2499
- checkoutData: remoteCheckoutData
2501
+ checkoutData: checkoutData
2500
2502
  });
2501
2503
  case 15:
2502
2504
  fresh = this.extractOrderDataFromCheckoutResponse(response);
2503
- externalSaleNumber = this.getCheckoutExternalSaleNumber(remoteCheckoutData, {
2505
+ externalSaleNumber = this.getCheckoutExternalSaleNumber(checkoutData, {
2504
2506
  external_sale_number: params.externalSaleNumber,
2505
- data: remoteCheckoutData
2507
+ data: checkoutData
2506
2508
  });
2507
2509
  _context31.next = 19;
2508
2510
  return this.persistSyncedCheckoutOrder({
2509
2511
  backendPath: backendPath,
2510
- checkoutData: remoteCheckoutData,
2512
+ checkoutData: checkoutData,
2511
2513
  externalSaleNumber: externalSaleNumber,
2512
2514
  fresh: fresh,
2513
2515
  title: title,
@@ -2520,7 +2522,7 @@ var Server = /*#__PURE__*/function () {
2520
2522
  checkoutResponseOrder: fresh
2521
2523
  }) : undefined;
2522
2524
  if (!(printableSyncedOrder && this.shouldPrintSyncedOrder({
2523
- checkoutData: remoteCheckoutData,
2525
+ checkoutData: checkoutData,
2524
2526
  syncedOrder: printableSyncedOrder
2525
2527
  }))) {
2526
2528
  _context31.next = 24;
@@ -2528,7 +2530,7 @@ var Server = /*#__PURE__*/function () {
2528
2530
  }
2529
2531
  _context31.next = 24;
2530
2532
  return this.dispatchPrintOtherReceiptTask({
2531
- checkoutData: remoteCheckoutData,
2533
+ checkoutData: checkoutData,
2532
2534
  syncedOrder: printableSyncedOrder,
2533
2535
  response: response,
2534
2536
  deviceId: params.deviceId
@@ -2538,7 +2540,7 @@ var Server = /*#__PURE__*/function () {
2538
2540
  rejected: false,
2539
2541
  response: response,
2540
2542
  normalizedResponse: this.normalizeCheckoutResponse(response),
2541
- checkoutData: remoteCheckoutData,
2543
+ checkoutData: checkoutData,
2542
2544
  syncedOrder: syncedOrder,
2543
2545
  fresh: fresh
2544
2546
  });
@@ -2562,6 +2564,67 @@ var Server = /*#__PURE__*/function () {
2562
2564
  delete next.syncMode;
2563
2565
  return next;
2564
2566
  }
2567
+ }, {
2568
+ key: "buildRemoteCheckoutData",
2569
+ value: function buildRemoteCheckoutData(data, title) {
2570
+ var next = cloneDeep(this.omitCheckoutSyncMode(data));
2571
+ if (!next || _typeof(next) !== 'object') return next;
2572
+ var record = next;
2573
+ if (!Array.isArray(record.payments)) return next;
2574
+ var originalPayments = record.payments;
2575
+ var filteredPayments = originalPayments.filter(function (payment) {
2576
+ return !isPendingOrderPayment(payment);
2577
+ });
2578
+ var removedPayments = originalPayments.filter(function (payment) {
2579
+ return isPendingOrderPayment(payment);
2580
+ });
2581
+ record.payments = filteredPayments;
2582
+ this.logInfo("".concat(title, ": checkout \u4E91\u7AEF\u652F\u4ED8\u9879\u5DF2\u8FC7\u6EE4"), {
2583
+ external_sale_number: record.external_sale_number,
2584
+ original_payment_count: originalPayments.length,
2585
+ remote_payment_count: filteredPayments.length,
2586
+ filtered_pending_count: removedPayments.length,
2587
+ filtered_payment_identities: removedPayments.map(function (payment) {
2588
+ return getOrderPaymentIdentityKeys(payment);
2589
+ })
2590
+ });
2591
+ return next;
2592
+ }
2593
+ }, {
2594
+ key: "mergeCheckoutSyncPayments",
2595
+ value: function mergeCheckoutSyncPayments(checkoutData, fresh, title) {
2596
+ var localPayments = Array.isArray(checkoutData === null || checkoutData === void 0 ? void 0 : checkoutData.payments) ? checkoutData.payments : [];
2597
+ var freshRecord = fresh;
2598
+ if (!Array.isArray(freshRecord.payments)) {
2599
+ return localPayments.length > 0 ? _objectSpread(_objectSpread({}, freshRecord), {}, {
2600
+ payments: cloneDeep(localPayments)
2601
+ }) : freshRecord;
2602
+ }
2603
+ var freshPayments = freshRecord.payments;
2604
+ var mergedPayments = mergeOrderPaymentListsByIdentity(localPayments, freshPayments, {
2605
+ preserveUnmatchedExistingWhen: isIdentifiedPendingOrderPayment
2606
+ });
2607
+ var remoteIdentityKeys = new Set(freshPayments.flatMap(function (payment) {
2608
+ return getOrderPaymentIdentityKeys(payment);
2609
+ }));
2610
+ var preservedPending = localPayments.filter(function (payment) {
2611
+ return isIdentifiedPendingOrderPayment(payment) && !getOrderPaymentIdentityKeys(payment).some(function (key) {
2612
+ return remoteIdentityKeys.has(key);
2613
+ });
2614
+ });
2615
+ if (preservedPending.length > 0) {
2616
+ this.logInfo("".concat(title, ": checkout \u54CD\u5E94\u5408\u5E76\u4FDD\u7559\u672C\u5730 pending \u652F\u4ED8\u9879"), {
2617
+ external_sale_number: checkoutData === null || checkoutData === void 0 ? void 0 : checkoutData.external_sale_number,
2618
+ preserved_pending_count: preservedPending.length,
2619
+ preserved_payment_identities: preservedPending.map(function (payment) {
2620
+ return getOrderPaymentIdentityKeys(payment);
2621
+ })
2622
+ });
2623
+ }
2624
+ return _objectSpread(_objectSpread({}, freshRecord), {}, {
2625
+ payments: mergedPayments
2626
+ });
2627
+ }
2565
2628
  }, {
2566
2629
  key: "persistSyncedCheckoutOrder",
2567
2630
  value: function () {
@@ -2576,11 +2639,11 @@ var Server = /*#__PURE__*/function () {
2576
2639
  _context32.next = 9;
2577
2640
  break;
2578
2641
  }
2579
- syncedOrder = persistCheckoutDataWithResponse ? _objectSpread(_objectSpread(_objectSpread({}, checkoutData), fresh), {}, {
2642
+ syncedOrder = persistCheckoutDataWithResponse ? _objectSpread(_objectSpread(_objectSpread({}, checkoutData), this.mergeCheckoutSyncPayments(checkoutData, fresh, title)), {}, {
2580
2643
  external_sale_number: (_external_sale_number2 = fresh.external_sale_number) !== null && _external_sale_number2 !== void 0 ? _external_sale_number2 : externalSaleNumber,
2581
2644
  need_sync: 0,
2582
2645
  is_draft_order: 0
2583
- }) : _objectSpread(_objectSpread({}, fresh), {}, {
2646
+ }) : _objectSpread(_objectSpread({}, this.mergeCheckoutSyncPayments(checkoutData, fresh, title)), {}, {
2584
2647
  external_sale_number: (_external_sale_number3 = fresh.external_sale_number) !== null && _external_sale_number3 !== void 0 ? _external_sale_number3 : externalSaleNumber,
2585
2648
  need_sync: 0,
2586
2649
  is_draft_order: 0
@@ -260,6 +260,9 @@ export declare class OrderModule extends BaseModule implements Module {
260
260
  private getProductIdentityKeys;
261
261
  private mergeOrderProductLists;
262
262
  private mergeOrderPaymentLists;
263
+ private getIdentifiedPendingPayments;
264
+ private shouldProtectLocalOrderFromRemoteSnapshot;
265
+ private getUnmatchedIdentifiedPendingPayments;
263
266
  private mergeOrderRecords;
264
267
  private summarizeDuplicateOrders;
265
268
  private logDuplicateOrders;
@@ -305,7 +308,7 @@ export declare class OrderModule extends BaseModule implements Module {
305
308
  */
306
309
  private updateOrderInSQLite;
307
310
  /**
308
- * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync 订单。
311
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
309
312
  * 用于 SSE 全量拉取与营业日窗口裁剪。
310
313
  *
311
314
  * @example
@@ -7,11 +7,11 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableTo
7
7
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
8
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
9
9
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
10
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
12
10
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
13
11
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
14
12
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
13
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
15
15
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
16
16
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
17
17
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -35,7 +35,7 @@ import dayjs from 'dayjs';
35
35
  import { BaseModule } from "../../../modules/BaseModule";
36
36
  import { applyOrderCollectionUidRemaps, getOrderCollectionPersistentId, getOrderCollectionReferenceUid, getOrderCollectionUid, isSameOrderCollectionItem, mergeOrderCollectionItems, normalizeOrderCollections } from "../../../modules/Order/utils/orderCollectionIdentity";
37
37
  import { OrderHooks } from "./types";
38
- import { mergeOrderPaymentListsByIdentity, mergeOrderPaymentRecord, resolveOrderPaymentIdentity } from "../../../modules/Order/payment-utils";
38
+ import { getOrderPaymentIdentityKeys, isIdentifiedPendingOrderPayment, isPendingOrderPayment, mergeOrderPaymentListsByIdentity, mergeOrderPaymentRecord, resolveOrderPaymentIdentity } from "../../../modules/Order/payment-utils";
39
39
 
40
40
  /**
41
41
  * SQLite 存储名称
@@ -57,6 +57,7 @@ var ORDER_BUSINESS_WRITE_SOURCES = new Set(['upsertOrdersFromRemote', 'upsertPen
57
57
  * 仅用于排查增量身份索引是否遗漏了重复订单,不应在生产常开。
58
58
  */
59
59
  var ORDER_MERGE_SELF_CHECK = false;
60
+ var PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER = '__pisell_os_pending_payment_without_unique_number__';
60
61
  var ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ['products', 'bookings', 'payments'];
61
62
  var ORDER_COLLECTION_KIND_BY_FIELD = {
62
63
  products: 'product',
@@ -245,7 +246,31 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
245
246
  }, {
246
247
  key: "normalizeOrderCollectionsForIngress",
247
248
  value: function normalizeOrderCollectionsForIngress(order, source) {
248
- var result = normalizeOrderCollections(order);
249
+ var sourceOrder = cloneDeep(order);
250
+ var sourceOrderRecord = sourceOrder;
251
+ if (Array.isArray(sourceOrderRecord.payments)) {
252
+ sourceOrderRecord.payments = sourceOrderRecord.payments.map(function (payment) {
253
+ if (!isPendingOrderPayment(payment) || getOrderPaymentIdentityKeys(payment).some(function (key) {
254
+ return key.startsWith('unique_payment_number:');
255
+ })) {
256
+ return payment;
257
+ }
258
+ return _objectSpread(_objectSpread({}, payment), {}, _defineProperty({}, PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER, true));
259
+ });
260
+ }
261
+ var result = normalizeOrderCollections(sourceOrder);
262
+ var normalizedOrderRecord = result.order;
263
+ if (Array.isArray(normalizedOrderRecord.payments)) {
264
+ normalizedOrderRecord.payments = normalizedOrderRecord.payments.map(function (payment) {
265
+ if (!(payment !== null && payment !== void 0 && payment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER])) return payment;
266
+ var nextPayment = _objectSpread({}, payment);
267
+ var metadata = _objectSpread({}, nextPayment.metadata || {});
268
+ delete metadata.unique_payment_number;
269
+ delete nextPayment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER];
270
+ nextPayment.metadata = metadata;
271
+ return nextPayment;
272
+ });
273
+ }
249
274
  var kinds = ['product', 'booking', 'payment'];
250
275
  var hasChanges = kinds.some(function (kind) {
251
276
  var stats = result.stats[kind];
@@ -289,8 +314,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
289
314
  key: "mergeAuthoritativeOrderCollection",
290
315
  value: function mergeAuthoritativeOrderCollection(field, existing, incoming) {
291
316
  var uidRemaps = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
317
+ var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
292
318
  var kind = ORDER_COLLECTION_KIND_BY_FIELD[field];
293
319
  var existingItems = Array.isArray(existing) ? existing : [];
320
+ if (field === 'payments' && options.preserveIdentifiedPendingPayments) {
321
+ return mergeOrderPaymentListsByIdentity(existingItems, incoming, {
322
+ preserveUnmatchedExistingWhen: isIdentifiedPendingOrderPayment
323
+ });
324
+ }
294
325
  return incoming.map(function (incomingItem) {
295
326
  var existingItem = existingItems.find(function (item) {
296
327
  return isSameOrderCollectionItem(kind, item, incomingItem);
@@ -961,12 +992,15 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
961
992
  return this.loadOrdersFromSQLite();
962
993
  case 3:
963
994
  protectedOrdersBeforeRemoteFetch = _context7.sent.filter(function (order) {
964
- return _this5.isPendingSyncOrder(order) || _this5.isDraftOrder(order);
995
+ return _this5.shouldProtectLocalOrderFromRemoteSnapshot(order);
965
996
  });
966
997
  this.logInfo('loadOrdersByServer-开始', {
967
998
  hasOrderDataSource: !!this.orderDataSource,
968
999
  query: ((_this$store = this.store) === null || _this$store === void 0 ? void 0 : _this$store.createdAtQuery) || null,
969
- protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length
1000
+ protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length,
1001
+ protectedPendingPaymentCount: protectedOrdersBeforeRemoteFetch.reduce(function (count, order) {
1002
+ return count + _this5.getIdentifiedPendingPayments(order).length;
1003
+ }, 0)
970
1004
  });
971
1005
  if (!this.orderDataSource) {
972
1006
  _context7.next = 20;
@@ -2745,6 +2779,33 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2745
2779
  if (incomingList.length === 0) return cloneDeep(existingList);
2746
2780
  return mergeOrderPaymentListsByIdentity(existingList, incomingList);
2747
2781
  }
2782
+ }, {
2783
+ key: "getIdentifiedPendingPayments",
2784
+ value: function getIdentifiedPendingPayments(order) {
2785
+ var payments = Array.isArray(order === null || order === void 0 ? void 0 : order.payments) ? order.payments : [];
2786
+ return payments.filter(function (payment) {
2787
+ return isIdentifiedPendingOrderPayment(payment);
2788
+ });
2789
+ }
2790
+ }, {
2791
+ key: "shouldProtectLocalOrderFromRemoteSnapshot",
2792
+ value: function shouldProtectLocalOrderFromRemoteSnapshot(order) {
2793
+ return this.isPendingSyncOrder(order) || this.isDraftOrder(order) || this.getIdentifiedPendingPayments(order).length > 0;
2794
+ }
2795
+ }, {
2796
+ key: "getUnmatchedIdentifiedPendingPayments",
2797
+ value: function getUnmatchedIdentifiedPendingPayments(existing, incoming) {
2798
+ var existingPayments = Array.isArray(existing) ? existing : [];
2799
+ var incomingPayments = Array.isArray(incoming) ? incoming : [];
2800
+ var incomingIdentityKeys = new Set(incomingPayments.flatMap(function (payment) {
2801
+ return getOrderPaymentIdentityKeys(payment);
2802
+ }));
2803
+ return existingPayments.filter(function (payment) {
2804
+ return isIdentifiedPendingOrderPayment(payment) && !getOrderPaymentIdentityKeys(payment).some(function (key) {
2805
+ return incomingIdentityKeys.has(key);
2806
+ });
2807
+ });
2808
+ }
2748
2809
  }, {
2749
2810
  key: "mergeOrderRecords",
2750
2811
  value: function mergeOrderRecords(existing, incoming) {
@@ -2782,7 +2843,23 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2782
2843
  for (var _i6 = 0, _ORDER_AUTHORITATIVE_2 = ORDER_AUTHORITATIVE_COLLECTION_FIELDS; _i6 < _ORDER_AUTHORITATIVE_2.length; _i6++) {
2783
2844
  var _field2 = _ORDER_AUTHORITATIVE_2[_i6];
2784
2845
  if (Array.isArray(incomingRecord[_field2])) {
2785
- mergedRecord[_field2] = this.mergeAuthoritativeOrderCollection(_field2, existingRecord[_field2], incomingRecord[_field2], childUidRemaps);
2846
+ if (_field2 === 'payments') {
2847
+ var preservedPending = this.getUnmatchedIdentifiedPendingPayments(existingRecord[_field2], incomingRecord[_field2]);
2848
+ if (preservedPending.length > 0) {
2849
+ var _ref5, _existing$order_id, _ref6, _existingRecord$exter;
2850
+ this.logInfo('mergeOrderRecords-保留本地 pending 支付项', {
2851
+ order_id: (_ref5 = (_existing$order_id = existing.order_id) !== null && _existing$order_id !== void 0 ? _existing$order_id : incoming.order_id) !== null && _ref5 !== void 0 ? _ref5 : null,
2852
+ external_sale_number: (_ref6 = (_existingRecord$exter = existingRecord.external_sale_number) !== null && _existingRecord$exter !== void 0 ? _existingRecord$exter : incomingRecord.external_sale_number) !== null && _ref6 !== void 0 ? _ref6 : null,
2853
+ preserved_pending_count: preservedPending.length,
2854
+ preserved_payment_identities: preservedPending.map(function (payment) {
2855
+ return getOrderPaymentIdentityKeys(payment);
2856
+ })
2857
+ });
2858
+ }
2859
+ }
2860
+ mergedRecord[_field2] = this.mergeAuthoritativeOrderCollection(_field2, existingRecord[_field2], incomingRecord[_field2], childUidRemaps, {
2861
+ preserveIdentifiedPendingPayments: _field2 === 'payments'
2862
+ });
2786
2863
  continue;
2787
2864
  }
2788
2865
  if (Object.prototype.hasOwnProperty.call(existingRecord, _field2)) {
@@ -2825,14 +2902,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2825
2902
  } finally {
2826
2903
  _iterator26.f();
2827
2904
  }
2828
- return _toConsumableArray(groups.entries()).filter(function (_ref5) {
2829
- var _ref6 = _slicedToArray(_ref5, 2),
2830
- group = _ref6[1];
2831
- return group.length > 1;
2832
- }).slice(0, 20).map(function (_ref7) {
2905
+ return _toConsumableArray(groups.entries()).filter(function (_ref7) {
2833
2906
  var _ref8 = _slicedToArray(_ref7, 2),
2834
- key = _ref8[0],
2835
2907
  group = _ref8[1];
2908
+ return group.length > 1;
2909
+ }).slice(0, 20).map(function (_ref9) {
2910
+ var _ref10 = _slicedToArray(_ref9, 2),
2911
+ key = _ref10[0],
2912
+ group = _ref10[1];
2836
2913
  return {
2837
2914
  key: key,
2838
2915
  count: group.length,
@@ -3069,7 +3146,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3069
3146
  for (_iterator29.s(); !(_step29 = _iterator29.n()).done;) {
3070
3147
  var rawOrder = _step29.value;
3071
3148
  var order = this.normalizeOrderCollectionsForIngress(rawOrder, 'mergeRemoteSnapshotWithPendingOrders.existingSQLite');
3072
- if (!this.isPendingSyncOrder(order) && !this.isDraftOrder(order)) continue;
3149
+ if (!this.shouldProtectLocalOrderFromRemoteSnapshot(order)) continue;
3073
3150
  var matchIndex = this.findOrderIndexByIdentity(merged, order);
3074
3151
  if (matchIndex >= 0) {
3075
3152
  if (this.isDraftOrder(order)) {
@@ -3443,7 +3520,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3443
3520
  return updateOrderInSQLite;
3444
3521
  }()
3445
3522
  /**
3446
- * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync 订单。
3523
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
3447
3524
  * 用于 SSE 全量拉取与营业日窗口裁剪。
3448
3525
  *
3449
3526
  * @example
@@ -3501,7 +3578,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3501
3578
  protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map(function (order) {
3502
3579
  return _this23.normalizeOrderCollectionsForIngress(order, "".concat(source, ".protectedBeforeRemoteFetch"));
3503
3580
  }).filter(function (order) {
3504
- return _this23.isPendingSyncOrder(order) || _this23.isDraftOrder(order);
3581
+ return _this23.shouldProtectLocalOrderFromRemoteSnapshot(order);
3505
3582
  });
3506
3583
  _iterator31 = _createForOfIteratorHelper(existingOrders || []);
3507
3584
  _context25.prev = 10;
@@ -3514,7 +3591,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3514
3591
  rawCurrentOrder = _step31.value;
3515
3592
  currentOrder = _this23.normalizeOrderCollectionsForIngress(rawCurrentOrder, "".concat(source, ".currentSQLite"));
3516
3593
  protectedIndex = _this23.findOrderIndexByIdentity(protectedLocalOrders, currentOrder);
3517
- currentNeedsProtection = _this23.isPendingSyncOrder(currentOrder) || _this23.isDraftOrder(currentOrder);
3594
+ currentNeedsProtection = _this23.shouldProtectLocalOrderFromRemoteSnapshot(currentOrder);
3518
3595
  if (!(protectedIndex >= 0)) {
3519
3596
  _context25.next = 20;
3520
3597
  break;
@@ -3550,7 +3627,20 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3550
3627
  remoteCount: remoteSnapshot.length,
3551
3628
  protectedBeforeRemoteFetchCount: protectedOrdersBeforeRemoteFetch.length,
3552
3629
  protectedLocalOrderCount: protectedLocalOrders.length,
3553
- preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length
3630
+ preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length,
3631
+ protectedPendingPaymentCount: protectedLocalOrders.reduce(function (count, order) {
3632
+ return count + _this23.getIdentifiedPendingPayments(order).length;
3633
+ }, 0),
3634
+ protectedPendingPaymentIdentities: protectedLocalOrders.flatMap(function (order) {
3635
+ return _this23.getIdentifiedPendingPayments(order).map(function (payment) {
3636
+ var _order$order_id5, _external_sale_number5;
3637
+ return {
3638
+ order_id: (_order$order_id5 = order.order_id) !== null && _order$order_id5 !== void 0 ? _order$order_id5 : null,
3639
+ external_sale_number: (_external_sale_number5 = order.external_sale_number) !== null && _external_sale_number5 !== void 0 ? _external_sale_number5 : null,
3640
+ payment_identities: getOrderPaymentIdentityKeys(payment)
3641
+ };
3642
+ });
3643
+ })
3554
3644
  });
3555
3645
  _context25.next = 36;
3556
3646
  return _this23.dbManager.clear(INDEXDB_STORE_NAME);
@@ -37,7 +37,7 @@ import Decimal from 'decimal.js';
37
37
  import { cloneDeep, mergeWith } from 'lodash-es';
38
38
  import { createModule } from "../BookingByStep/types";
39
39
  import { composeLinePrice, createUuidV4, ensureProductSku, getProductSkuOptions, resolveIsFormSubject, sumOptionUnitPrice } from "../../modules/Order/utils";
40
- import { ensureOrderPaymentNumber, mergeOrderPaymentListsByIdentity, resolveOrderPaymentIdentity } from "../../modules/Order/payment-utils";
40
+ import { ensureOrderPaymentNumber, isIdentifiedPendingOrderPayment, mergeOrderPaymentListsByIdentity, resolveOrderPaymentIdentity } from "../../modules/Order/payment-utils";
41
41
  import { resolvePaymentNumberDevicePrefix, resolvePaymentNumberDevicePrefixFromDeviceId } from "../../utils/payment-number";
42
42
  import { applyOrderCollectionUidRemaps, getOrderCollectionPersistentId, getOrderCollectionReferenceUid, getOrderCollectionUid, isSameOrderCollectionItem, mergeOrderCollectionItems, normalizeOrderCollection, normalizeOrderCollections, setOrderCollectionUid } from "../../modules/Order/utils/orderCollectionIdentity";
43
43
  import dayjs from 'dayjs';
@@ -149,6 +149,15 @@ function mergeBaseSalesCollectionItem(kind, currentItem, incomingItem, uidRemaps
149
149
  return kind === 'product' ? mergeBaseSalesProductSnapshotFields(currentItem, mergedItem) : mergedItem;
150
150
  }
151
151
  function mergeBaseSalesOrderCollection(kind, currentValue, incomingValue, strategy, uidRemaps) {
152
+ if (kind === 'payment') {
153
+ return mergeOrderPaymentListsByIdentity(currentValue, incomingValue, strategy === 'preserve-local' ? {
154
+ preserveUnmatchedExisting: true
155
+ } : {
156
+ preserveUnmatchedExistingWhen: function preserveUnmatchedExistingWhen(payment) {
157
+ return isIdentifiedPendingOrderPayment(payment) || !getOrderCollectionPersistentId('payment', payment);
158
+ }
159
+ });
160
+ }
152
161
  var currentItems = normalizeOrderCollection(kind, currentValue, {
153
162
  ensureUid: false
154
163
  }).items;
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
314
+ weekNum: 0 | 3 | 1 | 2 | 5 | 4 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -322,7 +322,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
322
322
  * 获取当前的客户搜索条件
323
323
  * @returns 当前搜索条件
324
324
  */
325
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
325
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
326
326
  /**
327
327
  * 获取客户列表状态(包含滚动加载相关状态)
328
328
  * @returns 客户状态
@@ -1,49 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
-
29
- // src/model/strategy/adapter/promotion/index.ts
30
- var promotion_exports = {};
31
- __export(promotion_exports, {
32
- BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
33
- PromotionAdapter: () => import_adapter.PromotionAdapter,
34
- PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
35
- X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
36
- default: () => import_adapter2.default
37
- });
38
- module.exports = __toCommonJS(promotion_exports);
39
- var import_evaluator = require("./evaluator");
40
- var import_adapter = require("./adapter");
41
- var import_adapter2 = __toESM(require("./adapter"));
42
- var import_examples = require("./examples");
43
- // Annotate the CommonJS export names for ESM import in node:
44
- 0 && (module.exports = {
45
- BUY_X_GET_Y_FREE_STRATEGY,
46
- PromotionAdapter,
47
- PromotionEvaluator,
48
- X_ITEMS_FOR_Y_PRICE_STRATEGY
49
- });
@@ -10,6 +10,8 @@ export interface OrderPaymentIdentityMatch<T> {
10
10
  matchedBy: OrderPaymentIdentityType;
11
11
  }
12
12
  export declare function getOrderPaymentIdentityKeys(payment: unknown): string[];
13
+ export declare function isPendingOrderPayment(payment: unknown): boolean;
14
+ export declare function isIdentifiedPendingOrderPayment(payment: unknown): boolean;
13
15
  export declare function hasOrderPaymentIdentityOverlap(left: unknown, right: unknown): boolean;
14
16
  export declare function resolveOrderPaymentIdentity<T extends Record<string, any>>(payments: T[] | null | undefined, identity: string | number, mode?: 'payment_number' | 'compat'): OrderPaymentIdentityMatch<T> | null;
15
17
  export declare function ensureOrderPaymentNumber<T extends Record<string, any>>(payment: T, devicePrefix: string, createPaymentNumber: () => string): T & {
@@ -20,4 +22,5 @@ export declare function mergeOrderPaymentRecord<T extends Record<string, any>>(p
20
22
  export declare function mergeOrderPaymentSnapshot<T extends Record<string, any>>(current: T, incoming: T): T;
21
23
  export declare function mergeOrderPaymentListsByIdentity<T extends Record<string, any>>(existing: T[] | null | undefined, incoming: T[] | null | undefined, options?: {
22
24
  preserveUnmatchedExisting?: boolean;
25
+ preserveUnmatchedExistingWhen?: (payment: T) => boolean;
23
26
  }): T[];
@@ -22,6 +22,8 @@ __export(payment_utils_exports, {
22
22
  ensureOrderPaymentNumber: () => ensureOrderPaymentNumber,
23
23
  getOrderPaymentIdentityKeys: () => getOrderPaymentIdentityKeys,
24
24
  hasOrderPaymentIdentityOverlap: () => hasOrderPaymentIdentityOverlap,
25
+ isIdentifiedPendingOrderPayment: () => isIdentifiedPendingOrderPayment,
26
+ isPendingOrderPayment: () => isPendingOrderPayment,
25
27
  mergeOrderPaymentListsByIdentity: () => mergeOrderPaymentListsByIdentity,
26
28
  mergeOrderPaymentRecord: () => mergeOrderPaymentRecord,
27
29
  mergeOrderPaymentSnapshot: () => mergeOrderPaymentSnapshot,
@@ -55,6 +57,13 @@ function getOrderPaymentIdentityKeys(payment) {
55
57
  return value === null ? [] : [`${type}:${value}`];
56
58
  });
57
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
+ }
58
67
  function hasOrderPaymentIdentityOverlap(left, right) {
59
68
  const leftKeys = new Set(getOrderPaymentIdentityKeys(left));
60
69
  if (leftKeys.size === 0)
@@ -131,6 +140,19 @@ function mergeOrderPaymentRecord(payment, updates) {
131
140
  function mergeOrderPaymentSnapshot(current, incoming) {
132
141
  const currentMetadata = current.metadata || {};
133
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
+ );
134
156
  const transactions = mergeOrderPaymentTransactions(
135
157
  currentMetadata.transactions,
136
158
  incomingMetadata.transactions
@@ -138,10 +160,12 @@ function mergeOrderPaymentSnapshot(current, incoming) {
138
160
  return {
139
161
  ...current,
140
162
  ...incoming,
163
+ order_payment_id: normalizePaymentIdentityValue(incoming.order_payment_id) !== null ? incoming.order_payment_id : current.order_payment_id,
141
164
  payment_number: incoming.payment_number || current.payment_number,
142
165
  metadata: {
143
166
  ...currentMetadata,
144
167
  ...incomingMetadata,
168
+ ...incomingUsesDerivedUniquePaymentNumber && currentUniquePaymentNumber ? { unique_payment_number: currentUniquePaymentNumber } : {},
145
169
  ...transactions.length > 0 ? { transactions } : {}
146
170
  }
147
171
  };
@@ -172,19 +196,26 @@ function mergeOrderPaymentListsByIdentity(existing, incoming, options = {}) {
172
196
  if (options.preserveUnmatchedExisting) {
173
197
  return compactOrderPaymentList([...existingList, ...incomingList]);
174
198
  }
175
- return compactOrderPaymentList(incomingList.map((incomingPayment) => {
199
+ const mergedIncoming = incomingList.map((incomingPayment) => {
176
200
  const matchingExisting = existingList.filter((existingPayment) => hasOrderPaymentIdentityOverlap(existingPayment, incomingPayment));
177
201
  return matchingExisting.reduce(
178
202
  (merged, existingPayment) => mergeOrderPaymentSnapshot(existingPayment, merged),
179
203
  incomingPayment
180
204
  );
181
- }));
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]);
182
211
  }
183
212
  // Annotate the CommonJS export names for ESM import in node:
184
213
  0 && (module.exports = {
185
214
  ensureOrderPaymentNumber,
186
215
  getOrderPaymentIdentityKeys,
187
216
  hasOrderPaymentIdentityOverlap,
217
+ isIdentifiedPendingOrderPayment,
218
+ isPendingOrderPayment,
188
219
  mergeOrderPaymentListsByIdentity,
189
220
  mergeOrderPaymentRecord,
190
221
  mergeOrderPaymentSnapshot,
@@ -220,6 +220,9 @@ function normalizeOrderCollection(kind, items, options) {
220
220
  const persistentId = getOrderCollectionPersistentId(kind, item);
221
221
  let uid = getOrderCollectionUid(kind, item);
222
222
  if (!uid) {
223
+ if (kind === "payment" && !isBlankOrderCollectionIdentity(item == null ? void 0 : item.payment_number)) {
224
+ continue;
225
+ }
223
226
  uid = persistentId ? buildOrderCollectionFallbackUid(kind, persistentId) : allocateAnonymousUid(occupiedUids, createAnonymousUid);
224
227
  item = setOrderCollectionUid(kind, item, uid);
225
228
  result[index] = item;
@@ -121,6 +121,8 @@ declare class Server {
121
121
  private handleSyncSalesTask;
122
122
  private runCheckoutSync;
123
123
  private omitCheckoutSyncMode;
124
+ private buildRemoteCheckoutData;
125
+ private mergeCheckoutSyncPayments;
124
126
  private persistSyncedCheckoutOrder;
125
127
  /**
126
128
  * 将普通层 QuotationModule 的报价单计算能力桥接到 Server Products 模块。
@@ -35,6 +35,7 @@ __export(server_exports, {
35
35
  module.exports = __toCommonJS(server_exports);
36
36
  var import_dayjs = __toESM(require("dayjs"));
37
37
  var import_decimal = __toESM(require("decimal.js"));
38
+ var import_lodash_es = require("lodash-es");
38
39
  var import_products = require("./modules/products");
39
40
  var import_menu = require("./modules/menu");
40
41
  var import_quotation = require("./modules/quotation");
@@ -52,6 +53,7 @@ var import_filterOrders = require("./modules/order/utils/filterOrders");
52
53
  var import_filterBookings = require("./modules/order/utils/filterBookings");
53
54
  var import_small_ticket = require("./utils/small-ticket");
54
55
  var import_BaseSales = require("../solution/BaseSales");
56
+ var import_payment_utils = require("../modules/Order/payment-utils");
55
57
  __reExport(server_exports, require("./modules"), module.exports);
56
58
  var PRODUCT_TITLE_SNAPSHOT_KEYS = [
57
59
  "en",
@@ -1481,7 +1483,7 @@ var Server = class {
1481
1483
  const { backendPath, title } = params;
1482
1484
  const normalizedData = await this.normalizeCheckoutSubmitData(params.data, title);
1483
1485
  const checkoutData = await this.ensureCheckoutOrderNumbers(normalizedData, title);
1484
- const remoteCheckoutData = this.omitCheckoutSyncMode(checkoutData);
1486
+ const remoteCheckoutData = this.buildRemoteCheckoutData(checkoutData, title);
1485
1487
  if (!((_b = (_a = this.app) == null ? void 0 : _a.request) == null ? void 0 : _b.post)) {
1486
1488
  throw new Error("app.request 不可用");
1487
1489
  }
@@ -1497,20 +1499,20 @@ var Server = class {
1497
1499
  errorResponse: response,
1498
1500
  response,
1499
1501
  normalizedResponse: this.normalizeCheckoutResponse(response),
1500
- checkoutData: remoteCheckoutData
1502
+ checkoutData
1501
1503
  };
1502
1504
  }
1503
1505
  const fresh = this.extractOrderDataFromCheckoutResponse(response);
1504
1506
  const externalSaleNumber = this.getCheckoutExternalSaleNumber(
1505
- remoteCheckoutData,
1507
+ checkoutData,
1506
1508
  {
1507
1509
  external_sale_number: params.externalSaleNumber,
1508
- data: remoteCheckoutData
1510
+ data: checkoutData
1509
1511
  }
1510
1512
  );
1511
1513
  const syncedOrder = await this.persistSyncedCheckoutOrder({
1512
1514
  backendPath,
1513
- checkoutData: remoteCheckoutData,
1515
+ checkoutData,
1514
1516
  externalSaleNumber,
1515
1517
  fresh,
1516
1518
  title,
@@ -1521,11 +1523,11 @@ var Server = class {
1521
1523
  checkoutResponseOrder: fresh
1522
1524
  }) : void 0;
1523
1525
  if (printableSyncedOrder && this.shouldPrintSyncedOrder({
1524
- checkoutData: remoteCheckoutData,
1526
+ checkoutData,
1525
1527
  syncedOrder: printableSyncedOrder
1526
1528
  })) {
1527
1529
  await this.dispatchPrintOtherReceiptTask({
1528
- checkoutData: remoteCheckoutData,
1530
+ checkoutData,
1529
1531
  syncedOrder: printableSyncedOrder,
1530
1532
  response,
1531
1533
  deviceId: params.deviceId
@@ -1535,7 +1537,7 @@ var Server = class {
1535
1537
  rejected: false,
1536
1538
  response,
1537
1539
  normalizedResponse: this.normalizeCheckoutResponse(response),
1538
- checkoutData: remoteCheckoutData,
1540
+ checkoutData,
1539
1541
  syncedOrder,
1540
1542
  fresh
1541
1543
  };
@@ -1548,6 +1550,54 @@ var Server = class {
1548
1550
  delete next.syncMode;
1549
1551
  return next;
1550
1552
  }
1553
+ buildRemoteCheckoutData(data, title) {
1554
+ const next = (0, import_lodash_es.cloneDeep)(this.omitCheckoutSyncMode(data));
1555
+ if (!next || typeof next !== "object")
1556
+ return next;
1557
+ const record = next;
1558
+ if (!Array.isArray(record.payments))
1559
+ return next;
1560
+ const originalPayments = record.payments;
1561
+ const filteredPayments = originalPayments.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
1562
+ const removedPayments = originalPayments.filter((payment) => (0, import_payment_utils.isPendingOrderPayment)(payment));
1563
+ record.payments = filteredPayments;
1564
+ this.logInfo(`${title}: checkout 云端支付项已过滤`, {
1565
+ external_sale_number: record.external_sale_number,
1566
+ original_payment_count: originalPayments.length,
1567
+ remote_payment_count: filteredPayments.length,
1568
+ filtered_pending_count: removedPayments.length,
1569
+ filtered_payment_identities: removedPayments.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1570
+ });
1571
+ return next;
1572
+ }
1573
+ mergeCheckoutSyncPayments(checkoutData, fresh, title) {
1574
+ const localPayments = Array.isArray(checkoutData == null ? void 0 : checkoutData.payments) ? checkoutData.payments : [];
1575
+ const freshRecord = fresh;
1576
+ if (!Array.isArray(freshRecord.payments)) {
1577
+ return localPayments.length > 0 ? { ...freshRecord, payments: (0, import_lodash_es.cloneDeep)(localPayments) } : freshRecord;
1578
+ }
1579
+ const freshPayments = freshRecord.payments;
1580
+ const mergedPayments = (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
1581
+ localPayments,
1582
+ freshPayments,
1583
+ { preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
1584
+ );
1585
+ const remoteIdentityKeys = new Set(
1586
+ freshPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1587
+ );
1588
+ const preservedPending = localPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => remoteIdentityKeys.has(key)));
1589
+ if (preservedPending.length > 0) {
1590
+ this.logInfo(`${title}: checkout 响应合并保留本地 pending 支付项`, {
1591
+ external_sale_number: checkoutData == null ? void 0 : checkoutData.external_sale_number,
1592
+ preserved_pending_count: preservedPending.length,
1593
+ preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1594
+ });
1595
+ }
1596
+ return {
1597
+ ...freshRecord,
1598
+ payments: mergedPayments
1599
+ };
1600
+ }
1551
1601
  async persistSyncedCheckoutOrder(params) {
1552
1602
  const {
1553
1603
  backendPath,
@@ -1562,12 +1612,12 @@ var Server = class {
1562
1612
  if (this.order && fresh && (shouldMergeRemoteOrder || persistCheckoutDataWithResponse)) {
1563
1613
  syncedOrder = persistCheckoutDataWithResponse ? {
1564
1614
  ...checkoutData,
1565
- ...fresh,
1615
+ ...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
1566
1616
  external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
1567
1617
  need_sync: 0,
1568
1618
  is_draft_order: 0
1569
1619
  } : {
1570
- ...fresh,
1620
+ ...this.mergeCheckoutSyncPayments(checkoutData, fresh, title),
1571
1621
  external_sale_number: fresh.external_sale_number ?? externalSaleNumber,
1572
1622
  need_sync: 0,
1573
1623
  is_draft_order: 0
@@ -260,6 +260,9 @@ export declare class OrderModule extends BaseModule implements Module {
260
260
  private getProductIdentityKeys;
261
261
  private mergeOrderProductLists;
262
262
  private mergeOrderPaymentLists;
263
+ private getIdentifiedPendingPayments;
264
+ private shouldProtectLocalOrderFromRemoteSnapshot;
265
+ private getUnmatchedIdentifiedPendingPayments;
263
266
  private mergeOrderRecords;
264
267
  private summarizeDuplicateOrders;
265
268
  private logDuplicateOrders;
@@ -305,7 +308,7 @@ export declare class OrderModule extends BaseModule implements Module {
305
308
  */
306
309
  private updateOrderInSQLite;
307
310
  /**
308
- * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync 订单。
311
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
309
312
  * 用于 SSE 全量拉取与营业日窗口裁剪。
310
313
  *
311
314
  * @example
@@ -53,6 +53,7 @@ var ORDER_BUSINESS_WRITE_SOURCES = /* @__PURE__ */ new Set([
53
53
  "updateLocalPayment"
54
54
  ]);
55
55
  var ORDER_MERGE_SELF_CHECK = false;
56
+ var PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER = "__pisell_os_pending_payment_without_unique_number__";
56
57
  var ORDER_AUTHORITATIVE_COLLECTION_FIELDS = ["products", "bookings", "payments"];
57
58
  var ORDER_COLLECTION_KIND_BY_FIELD = {
58
59
  products: "product",
@@ -172,7 +173,35 @@ var OrderModule = class extends import_BaseModule.BaseModule {
172
173
  * 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
173
174
  */
174
175
  normalizeOrderCollectionsForIngress(order, source) {
175
- const result = (0, import_orderCollectionIdentity.normalizeOrderCollections)(order);
176
+ const sourceOrder = (0, import_lodash_es.cloneDeep)(order);
177
+ const sourceOrderRecord = sourceOrder;
178
+ if (Array.isArray(sourceOrderRecord.payments)) {
179
+ sourceOrderRecord.payments = sourceOrderRecord.payments.map((payment) => {
180
+ if (!(0, import_payment_utils.isPendingOrderPayment)(payment) || (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => key.startsWith("unique_payment_number:"))) {
181
+ return payment;
182
+ }
183
+ return {
184
+ ...payment,
185
+ [PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]: true
186
+ };
187
+ });
188
+ }
189
+ const result = (0, import_orderCollectionIdentity.normalizeOrderCollections)(sourceOrder);
190
+ const normalizedOrderRecord = result.order;
191
+ if (Array.isArray(normalizedOrderRecord.payments)) {
192
+ normalizedOrderRecord.payments = normalizedOrderRecord.payments.map(
193
+ (payment) => {
194
+ if (!(payment == null ? void 0 : payment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER]))
195
+ return payment;
196
+ const nextPayment = { ...payment };
197
+ const metadata = { ...nextPayment.metadata || {} };
198
+ delete metadata.unique_payment_number;
199
+ delete nextPayment[PENDING_PAYMENT_WITHOUT_UNIQUE_MARKER];
200
+ nextPayment.metadata = metadata;
201
+ return nextPayment;
202
+ }
203
+ );
204
+ }
176
205
  const kinds = ["product", "booking", "payment"];
177
206
  const hasChanges = kinds.some((kind) => {
178
207
  const stats = result.stats[kind];
@@ -208,9 +237,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
208
237
  /**
209
238
  * incoming 决定权威成员集合;同一持久化行仍从 existing 补齐 incoming 省略的本地展示字段。
210
239
  */
211
- mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = []) {
240
+ mergeAuthoritativeOrderCollection(field, existing, incoming, uidRemaps = [], options = {}) {
212
241
  const kind = ORDER_COLLECTION_KIND_BY_FIELD[field];
213
242
  const existingItems = Array.isArray(existing) ? existing : [];
243
+ if (field === "payments" && options.preserveIdentifiedPendingPayments) {
244
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
245
+ existingItems,
246
+ incoming,
247
+ { preserveUnmatchedExistingWhen: import_payment_utils.isIdentifiedPendingOrderPayment }
248
+ );
249
+ }
214
250
  return incoming.map((incomingItem) => {
215
251
  const existingItem = existingItems.find(
216
252
  (item) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, item, incomingItem)
@@ -695,12 +731,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
695
731
  var _a;
696
732
  let orderList = [];
697
733
  const protectedOrdersBeforeRemoteFetch = (await this.loadOrdersFromSQLite()).filter(
698
- (order) => this.isPendingSyncOrder(order) || this.isDraftOrder(order)
734
+ (order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order)
699
735
  );
700
736
  this.logInfo("loadOrdersByServer-开始", {
701
737
  hasOrderDataSource: !!this.orderDataSource,
702
738
  query: ((_a = this.store) == null ? void 0 : _a.createdAtQuery) || null,
703
- protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length
739
+ protectedLocalOrderCount: protectedOrdersBeforeRemoteFetch.length,
740
+ protectedPendingPaymentCount: protectedOrdersBeforeRemoteFetch.reduce(
741
+ (count, order) => count + this.getIdentifiedPendingPayments(order).length,
742
+ 0
743
+ )
704
744
  });
705
745
  if (this.orderDataSource) {
706
746
  try {
@@ -1745,6 +1785,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1745
1785
  return (0, import_lodash_es.cloneDeep)(existingList);
1746
1786
  return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(existingList, incomingList);
1747
1787
  }
1788
+ getIdentifiedPendingPayments(order) {
1789
+ const payments = Array.isArray(order == null ? void 0 : order.payments) ? order.payments : [];
1790
+ return payments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment));
1791
+ }
1792
+ shouldProtectLocalOrderFromRemoteSnapshot(order) {
1793
+ return this.isPendingSyncOrder(order) || this.isDraftOrder(order) || this.getIdentifiedPendingPayments(order).length > 0;
1794
+ }
1795
+ getUnmatchedIdentifiedPendingPayments(existing, incoming) {
1796
+ const existingPayments = Array.isArray(existing) ? existing : [];
1797
+ const incomingPayments = Array.isArray(incoming) ? incoming : [];
1798
+ const incomingIdentityKeys = new Set(
1799
+ incomingPayments.flatMap((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1800
+ );
1801
+ return existingPayments.filter((payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) && !(0, import_payment_utils.getOrderPaymentIdentityKeys)(payment).some((key) => incomingIdentityKeys.has(key)));
1802
+ }
1748
1803
  mergeOrderRecords(existing, incoming) {
1749
1804
  const preferred = this.pickPreferredOrder(existing, incoming);
1750
1805
  const secondary = preferred === existing ? incoming : existing;
@@ -1803,11 +1858,26 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1803
1858
  }
1804
1859
  for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
1805
1860
  if (Array.isArray(incomingRecord[field])) {
1861
+ if (field === "payments") {
1862
+ const preservedPending = this.getUnmatchedIdentifiedPendingPayments(
1863
+ existingRecord[field],
1864
+ incomingRecord[field]
1865
+ );
1866
+ if (preservedPending.length > 0) {
1867
+ this.logInfo("mergeOrderRecords-保留本地 pending 支付项", {
1868
+ order_id: existing.order_id ?? incoming.order_id ?? null,
1869
+ external_sale_number: existingRecord.external_sale_number ?? incomingRecord.external_sale_number ?? null,
1870
+ preserved_pending_count: preservedPending.length,
1871
+ preserved_payment_identities: preservedPending.map((payment) => (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment))
1872
+ });
1873
+ }
1874
+ }
1806
1875
  mergedRecord[field] = this.mergeAuthoritativeOrderCollection(
1807
1876
  field,
1808
1877
  existingRecord[field],
1809
1878
  incomingRecord[field],
1810
- childUidRemaps
1879
+ childUidRemaps,
1880
+ { preserveIdentifiedPendingPayments: field === "payments" }
1811
1881
  );
1812
1882
  continue;
1813
1883
  }
@@ -2009,7 +2079,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2009
2079
  rawOrder,
2010
2080
  "mergeRemoteSnapshotWithPendingOrders.existingSQLite"
2011
2081
  );
2012
- if (!this.isPendingSyncOrder(order) && !this.isDraftOrder(order))
2082
+ if (!this.shouldProtectLocalOrderFromRemoteSnapshot(order))
2013
2083
  continue;
2014
2084
  const matchIndex = this.findOrderIndexByIdentity(merged, order);
2015
2085
  if (matchIndex >= 0) {
@@ -2170,7 +2240,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2170
2240
  }
2171
2241
  }
2172
2242
  /**
2173
- * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync 订单。
2243
+ * 全量快照替换 orders 表(clear + bulkAdd),并保留本地 draft / need_sync / pending 支付订单。
2174
2244
  * 用于 SSE 全量拉取与营业日窗口裁剪。
2175
2245
  *
2176
2246
  * @example
@@ -2196,7 +2266,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2196
2266
  const protectedLocalOrders = protectedOrdersBeforeRemoteFetch.map((order) => this.normalizeOrderCollectionsForIngress(
2197
2267
  order,
2198
2268
  `${source}.protectedBeforeRemoteFetch`
2199
- )).filter((order) => this.isPendingSyncOrder(order) || this.isDraftOrder(order));
2269
+ )).filter((order) => this.shouldProtectLocalOrderFromRemoteSnapshot(order));
2200
2270
  for (const rawCurrentOrder of existingOrders || []) {
2201
2271
  const currentOrder = this.normalizeOrderCollectionsForIngress(
2202
2272
  rawCurrentOrder,
@@ -2206,7 +2276,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2206
2276
  protectedLocalOrders,
2207
2277
  currentOrder
2208
2278
  );
2209
- const currentNeedsProtection = this.isPendingSyncOrder(currentOrder) || this.isDraftOrder(currentOrder);
2279
+ const currentNeedsProtection = this.shouldProtectLocalOrderFromRemoteSnapshot(currentOrder);
2210
2280
  if (protectedIndex >= 0) {
2211
2281
  if (currentNeedsProtection) {
2212
2282
  protectedLocalOrders[protectedIndex] = currentOrder;
@@ -2229,7 +2299,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2229
2299
  remoteCount: remoteSnapshot.length,
2230
2300
  protectedBeforeRemoteFetchCount: protectedOrdersBeforeRemoteFetch.length,
2231
2301
  protectedLocalOrderCount: protectedLocalOrders.length,
2232
- preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length
2302
+ preservedLocalUnsyncedCount: mergedSnapshot.length - remoteSnapshot.length,
2303
+ protectedPendingPaymentCount: protectedLocalOrders.reduce(
2304
+ (count, order) => count + this.getIdentifiedPendingPayments(order).length,
2305
+ 0
2306
+ ),
2307
+ protectedPendingPaymentIdentities: protectedLocalOrders.flatMap((order) => this.getIdentifiedPendingPayments(order).map((payment) => ({
2308
+ order_id: order.order_id ?? null,
2309
+ external_sale_number: order.external_sale_number ?? null,
2310
+ payment_identities: (0, import_payment_utils.getOrderPaymentIdentityKeys)(payment)
2311
+ })))
2233
2312
  });
2234
2313
  await this.dbManager.clear(INDEXDB_STORE_NAME);
2235
2314
  this.logInfo("replaceOrdersSnapshotInSQLite-clear完成", {
@@ -157,6 +157,15 @@ function mergeBaseSalesCollectionItem(kind, currentItem, incomingItem, uidRemaps
157
157
  return kind === "product" ? mergeBaseSalesProductSnapshotFields(currentItem, mergedItem) : mergedItem;
158
158
  }
159
159
  function mergeBaseSalesOrderCollection(kind, currentValue, incomingValue, strategy, uidRemaps) {
160
+ if (kind === "payment") {
161
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
162
+ currentValue,
163
+ incomingValue,
164
+ strategy === "preserve-local" ? { preserveUnmatchedExisting: true } : {
165
+ preserveUnmatchedExistingWhen: (payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) || !(0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("payment", payment)
166
+ }
167
+ );
168
+ }
160
169
  const currentItems = (0, import_orderCollectionIdentity.normalizeOrderCollection)(kind, currentValue, {
161
170
  ensureUid: false
162
171
  }).items;
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
314
+ weekNum: 0 | 3 | 1 | 2 | 5 | 4 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -322,7 +322,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
322
322
  * 获取当前的客户搜索条件
323
323
  * @returns 当前搜索条件
324
324
  */
325
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
325
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
326
326
  /**
327
327
  * 获取客户列表状态(包含滚动加载相关状态)
328
328
  * @returns 客户状态
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.3.33",
4
+ "version": "2.3.34",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",