@pisell/pisellos 2.2.290 → 2.2.291

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.
@@ -322,8 +322,17 @@ export var DataVariantEvaluator = /*#__PURE__*/function () {
322
322
  if (!(appliedInfo !== null && appliedInfo !== void 0 && (_appliedInfo$appliedF = appliedInfo.appliedFields) !== null && _appliedInfo$appliedF !== void 0 && _appliedInfo$appliedF.length)) {
323
323
  return originalItem;
324
324
  }
325
+
326
+ // 套餐加价/减价使用配置价;仅商品原价模式跟随子商品的 Data Variant 价格。
327
+ var isOriginalPriceBundleItem = originalItem.price_type === 'markup' && originalItem.price_type_ext === 'product_price';
328
+ var appliedFields = appliedInfo.appliedFields.filter(function (field) {
329
+ return field !== 'price' || isOriginalPriceBundleItem;
330
+ });
331
+ if (!appliedFields.length) {
332
+ return originalItem;
333
+ }
325
334
  var result = _objectSpread({}, originalItem);
326
- var _iterator6 = _createForOfIteratorHelper(appliedInfo.appliedFields),
335
+ var _iterator6 = _createForOfIteratorHelper(appliedFields),
327
336
  _step6;
328
337
  try {
329
338
  for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
@@ -337,7 +346,9 @@ export var DataVariantEvaluator = /*#__PURE__*/function () {
337
346
  } finally {
338
347
  _iterator6.f();
339
348
  }
340
- result._dataVariant = appliedInfo;
349
+ result._dataVariant = _objectSpread(_objectSpread({}, appliedInfo), {}, {
350
+ appliedFields: appliedFields
351
+ });
341
352
  return result;
342
353
  }
343
354
  }, {
@@ -0,0 +1,9 @@
1
+ // 导出评估器
2
+ export { PromotionEvaluator } from "./evaluator";
3
+
4
+ // 导出适配器
5
+ export { PromotionAdapter } from "./adapter";
6
+ export { default } from "./adapter";
7
+
8
+ // 导出策略配置示例常量
9
+ export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
@@ -179,6 +179,8 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
179
179
  private calculateOrderPaidPaymentTotal;
180
180
  private getDepositAmount;
181
181
  private normalizeDepositAmount;
182
+ private normalizeDepositFlag;
183
+ private getHistoricalDepositSnapshot;
182
184
  private getLastOrderDepositSnapshot;
183
185
  private getLastOrderSubmitSnapshot;
184
186
  private applyDepositAmountToSummary;
@@ -512,7 +514,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
512
514
  generateIdempotencyToken(): string;
513
515
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
514
516
  createOrder(params: CommitOrderParams['query']): {
515
- type: "virtual" | "appointment_booking";
517
+ type: "appointment_booking" | "virtual";
516
518
  platform: string;
517
519
  sales_channel: string;
518
520
  order_sales_channel: string;
@@ -1534,21 +1534,32 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1534
1534
  return Decimal.max(new Decimal(Number(amount) || 0), 0).toDecimalPlaces(2).toFixed(2);
1535
1535
  }
1536
1536
  }, {
1537
- key: "getLastOrderDepositSnapshot",
1538
- value: function getLastOrderDepositSnapshot() {
1539
- var _lastOrderInfo$deposi, _lastOrderInfo$summar;
1540
- var lastOrderInfo = this.store.lastOrderInfo;
1541
- if (!lastOrderInfo || _typeof(lastOrderInfo) !== 'object') return null;
1542
- var rawDepositAmount = (_lastOrderInfo$deposi = lastOrderInfo.deposit_amount) !== null && _lastOrderInfo$deposi !== void 0 ? _lastOrderInfo$deposi : (_lastOrderInfo$summar = lastOrderInfo.summary) === null || _lastOrderInfo$summar === void 0 ? void 0 : _lastOrderInfo$summar.deposit_amount;
1537
+ key: "normalizeDepositFlag",
1538
+ value: function normalizeDepositFlag(value) {
1539
+ if (value === 0 || value === '0') return 0;
1540
+ if (value === 1 || value === '1') return 1;
1541
+ return null;
1542
+ }
1543
+ }, {
1544
+ key: "getHistoricalDepositSnapshot",
1545
+ value: function getHistoricalDepositSnapshot(source) {
1546
+ var _record$deposit_amoun, _record$summary, _this$normalizeDeposi;
1547
+ if (!source || _typeof(source) !== 'object') return null;
1548
+ var record = source;
1549
+ var rawDepositAmount = (_record$deposit_amoun = record.deposit_amount) !== null && _record$deposit_amoun !== void 0 ? _record$deposit_amoun : (_record$summary = record.summary) === null || _record$summary === void 0 ? void 0 : _record$summary.deposit_amount;
1543
1550
  var depositAmount = this.normalizeDepositAmount(rawDepositAmount !== null && rawDepositAmount !== void 0 ? rawDepositAmount : 0);
1544
- var hasDepositAmount = new Decimal(depositAmount).gt(0);
1545
- var isDeposit = Number(lastOrderInfo.is_deposit) === 1 || hasDepositAmount;
1546
- if (!isDeposit || !hasDepositAmount) return null;
1551
+ if (!new Decimal(depositAmount).gt(0)) return null;
1547
1552
  return {
1548
- isDeposit: 1,
1553
+ // 兼容历史数据:旧快照缺少 is_deposit 时,沿用正定金金额的推导规则。
1554
+ isDeposit: (_this$normalizeDeposi = this.normalizeDepositFlag(record.is_deposit)) !== null && _this$normalizeDeposi !== void 0 ? _this$normalizeDeposi : 1,
1549
1555
  depositAmount: depositAmount
1550
1556
  };
1551
1557
  }
1558
+ }, {
1559
+ key: "getLastOrderDepositSnapshot",
1560
+ value: function getLastOrderDepositSnapshot() {
1561
+ return this.getHistoricalDepositSnapshot(this.store.lastOrderInfo);
1562
+ }
1552
1563
  }, {
1553
1564
  key: "getLastOrderSubmitSnapshot",
1554
1565
  value: function getLastOrderSubmitSnapshot() {
@@ -1595,7 +1606,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1595
1606
  })
1596
1607
  });
1597
1608
  tempOrder.deposit_amount = snapshot.depositAmount;
1598
- tempOrder.is_deposit = tempOrder.is_deposit === 0 && new Decimal(tempOrder.deposit_amount || 0).gt(0) ? 0 : snapshot.isDeposit;
1609
+ tempOrder.is_deposit = snapshot.isDeposit;
1599
1610
  return nextSummary;
1600
1611
  }
1601
1612
  }, {
@@ -2305,6 +2316,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2305
2316
  }, {
2306
2317
  key: "restoreOriginalSnapshotIfProductsUnchanged",
2307
2318
  value: function restoreOriginalSnapshotIfProductsUnchanged(tempOrder, snapshot) {
2319
+ var _historicalDepositSna;
2308
2320
  // merge hydrate 的商品集合包含本地未提交行,但 summary 仍来自远端旧订单,不能复用。
2309
2321
  if (snapshot.requiresFullSummaryRecalculation === true) return null;
2310
2322
  var currentFingerprint = this.buildOrderProductsFingerprint(tempOrder.products);
@@ -2316,10 +2328,17 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2316
2328
  }
2317
2329
  var summary = _objectSpread(_objectSpread({}, createEmptySummary()), cloneDeep(snapshot.summary || {}));
2318
2330
  var shouldUseManualDepositOverride = Boolean(manualDepositOverride && manualDepositOverride.productStructuralFingerprint === this.buildOrderProductsStructuralFingerprint(tempOrder.products));
2331
+ var historicalDepositSnapshot = this.getHistoricalDepositSnapshot(snapshot);
2319
2332
  if (shouldUseManualDepositOverride) {
2320
2333
  summary = this.applyDepositAmountToSummary(tempOrder, summary, manualDepositOverride.amount);
2321
- } else if (manualDepositOverride) {
2322
- this.clearManualDepositOverride(tempOrder);
2334
+ } else {
2335
+ if (manualDepositOverride) {
2336
+ this.clearManualDepositOverride(tempOrder);
2337
+ }
2338
+ if (historicalDepositSnapshot) {
2339
+ summary = this.applyDepositAmountToSummary(tempOrder, summary, historicalDepositSnapshot.depositAmount);
2340
+ tempOrder.is_deposit = historicalDepositSnapshot.isDeposit;
2341
+ }
2323
2342
  }
2324
2343
  var isPayableAmountUnchanged = this.isSnapshotPayableAmountUnchanged(tempOrder, snapshot, summary);
2325
2344
  if (!isPayableAmountUnchanged) return null;
@@ -2336,8 +2355,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2336
2355
  tempOrder.surcharges = cloneDeep(snapshot.surcharges);
2337
2356
  }
2338
2357
  tempOrder.surcharge_fee = summary.surcharge_fee || tempOrder.surcharge_fee;
2339
- tempOrder.deposit_amount = summary.deposit_amount || '0.00';
2340
- tempOrder.is_deposit = summary.deposit_amount !== '0.00' ? 1 : 0;
2358
+ tempOrder.deposit_amount = this.normalizeDepositAmount(summary.deposit_amount || 0);
2359
+ tempOrder.is_deposit = shouldUseManualDepositOverride ? new Decimal(tempOrder.deposit_amount).gt(0) ? 1 : 0 : (_historicalDepositSna = historicalDepositSnapshot === null || historicalDepositSnapshot === void 0 ? void 0 : historicalDepositSnapshot.isDeposit) !== null && _historicalDepositSna !== void 0 ? _historicalDepositSna : new Decimal(tempOrder.deposit_amount).gt(0) ? 1 : 0;
2341
2360
  var previousSummary = this.store.summary;
2342
2361
  this.store.summary = summary;
2343
2362
  this.updateTempOrderPaymentStatus(tempOrder, {
@@ -2998,7 +3017,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2998
3017
  var isExistingDepositDisabled = tempOrder.is_deposit === 0 && new Decimal(tempOrder.deposit_amount || 0).gt(0);
2999
3018
  tempOrder.deposit_amount = depositAmount;
3000
3019
  tempOrder.is_deposit = hasDepositAmount && !isExistingDepositDisabled ? 1 : 0;
3001
- return this.applyLastOrderDepositSnapshot(tempOrder, nextSummary);
3020
+ return shouldUseManualDepositOverride ? nextSummary : this.applyLastOrderDepositSnapshot(tempOrder, nextSummary);
3002
3021
  }
3003
3022
  }, {
3004
3023
  key: "recalculateSummary",
@@ -6022,7 +6041,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
6022
6041
  value: (function () {
6023
6042
  var _hydrateTempOrderFromRecord = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee42(record, options) {
6024
6043
  var _sourceRaw$_extend, _this$store$discount22;
6025
- var sourceRaw, duplicateProductIdentityRepair, duplicateIdentityReadySource, identityReadySource, normalizedCollections, raw, hasIdentityChanges, identityLogMetadata, hasIdentityWarnings, isSessionStorageHydrate, isMergedSalesDetailHydrate, nextTempOrder, _this$store$discount20, _this$store$discount21, restoredSessionDiscounts, nextExtend, sourceLastOrderInfo, isDraftOrder, syntheticIdentityOptions, rawSummary, summarySurcharges, hadSyntheticDraftOrderId, hydratedEditDiscounts, currentDiscounts, currentScanDiscounts, hydratedDiscountIds, retainedScanDiscounts, nextDiscounts, shouldSkipEmptyDiscountSync, _this$store$discount23, _this$store$discount24;
6044
+ var sourceRaw, duplicateProductIdentityRepair, duplicateIdentityReadySource, identityReadySource, normalizedCollections, raw, hasIdentityChanges, identityLogMetadata, hasIdentityWarnings, isSessionStorageHydrate, isMergedSalesDetailHydrate, nextTempOrder, _this$store$discount20, _this$store$discount21, restoredSessionDiscounts, nextExtend, sourceLastOrderInfo, isDraftOrder, syntheticIdentityOptions, rawSummary, historicalDepositSnapshot, summarySurcharges, hadSyntheticDraftOrderId, hydratedEditDiscounts, currentDiscounts, currentScanDiscounts, hydratedDiscountIds, retainedScanDiscounts, nextDiscounts, shouldSkipEmptyDiscountSync, _this$store$discount23, _this$store$discount24;
6026
6045
  return _regeneratorRuntime().wrap(function _callee42$(_context45) {
6027
6046
  while (1) switch (_context45.prev = _context45.next) {
6028
6047
  case 0:
@@ -6106,6 +6125,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
6106
6125
  externalSaleNumber: nextTempOrder.external_sale_number
6107
6126
  };
6108
6127
  rawSummary = raw.summary && _typeof(raw.summary) === 'object' ? raw.summary : {};
6128
+ historicalDepositSnapshot = this.getHistoricalDepositSnapshot(sourceLastOrderInfo);
6109
6129
  summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map(function (s) {
6110
6130
  return _objectSpread({}, s || {});
6111
6131
  }) : cloneDeep(nextTempOrder.surcharges || []);
@@ -6113,7 +6133,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
6113
6133
  surcharges: summarySurcharges
6114
6134
  });
6115
6135
  nextTempOrder._extend = _objectSpread(_objectSpread({}, nextTempOrder._extend || {}), {}, {
6116
- originalSalesSnapshot: _objectSpread({
6136
+ originalSalesSnapshot: _objectSpread(_objectSpread({
6117
6137
  summary: cloneDeep(this.store.summary),
6118
6138
  products: cloneDeep(nextTempOrder.products || []),
6119
6139
  bookings: cloneDeep(nextTempOrder.bookings || []),
@@ -6121,7 +6141,10 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
6121
6141
  surcharges: cloneDeep(nextTempOrder.surcharges || []),
6122
6142
  shop_discount: nextTempOrder.shop_discount || '0.00',
6123
6143
  productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || [])
6124
- }, isMergedSalesDetailHydrate ? {
6144
+ }, historicalDepositSnapshot ? {
6145
+ is_deposit: historicalDepositSnapshot.isDeposit,
6146
+ deposit_amount: historicalDepositSnapshot.depositAmount
6147
+ } : {}), isMergedSalesDetailHydrate ? {
6125
6148
  requiresFullSummaryRecalculation: true
6126
6149
  } : {})
6127
6150
  });
@@ -6144,28 +6167,28 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
6144
6167
  nextDiscounts = [].concat(_toConsumableArray(hydratedEditDiscounts), _toConsumableArray(retainedScanDiscounts));
6145
6168
  shouldSkipEmptyDiscountSync = nextDiscounts.length === 0 && currentDiscounts.length === 0;
6146
6169
  if (shouldSkipEmptyDiscountSync) {
6147
- _context45.next = 53;
6170
+ _context45.next = 54;
6148
6171
  break;
6149
6172
  }
6150
6173
  OrderModule.populateSavedAmounts(nextTempOrder.products, nextDiscounts);
6151
- _context45.next = 51;
6174
+ _context45.next = 52;
6152
6175
  return (_this$store$discount23 = this.store.discount) === null || _this$store$discount23 === void 0 ? void 0 : _this$store$discount23.setOriginalDiscountList(nextDiscounts);
6153
- case 51:
6154
- _context45.next = 53;
6176
+ case 52:
6177
+ _context45.next = 54;
6155
6178
  return (_this$store$discount24 = this.store.discount) === null || _this$store$discount24 === void 0 ? void 0 : _this$store$discount24.setDiscountList(nextDiscounts);
6156
- case 53:
6179
+ case 54:
6157
6180
  if (!(options !== null && options !== void 0 && options.recalcOnHydrate)) {
6158
- _context45.next = 56;
6181
+ _context45.next = 57;
6159
6182
  break;
6160
6183
  }
6161
- _context45.next = 56;
6184
+ _context45.next = 57;
6162
6185
  return this.recalculateSummary({
6163
6186
  createIfMissing: false
6164
6187
  });
6165
- case 56:
6188
+ case 57:
6166
6189
  this.persistTempOrder();
6167
6190
  return _context45.abrupt("return", nextTempOrder);
6168
- case 58:
6191
+ case 59:
6169
6192
  case "end":
6170
6193
  return _context45.stop();
6171
6194
  }
@@ -30,6 +30,8 @@ var LABELS = {
30
30
  pickUpTime: 'Pick-up time',
31
31
  asap: 'ASAP',
32
32
  cash: 'Cash',
33
+ cashReceived: 'Cash received',
34
+ changeDue: 'Change due',
33
35
  eftpos: 'Eftpos',
34
36
  wallet: 'Wallet',
35
37
  giftCard: 'Gift card',
@@ -56,6 +58,8 @@ var LABELS = {
56
58
  pickUpTime: '取餐时间',
57
59
  asap: '尽快',
58
60
  cash: '现金支付',
61
+ cashReceived: '收取现金',
62
+ changeDue: '找零',
59
63
  eftpos: '刷卡支付',
60
64
  wallet: '钱包支付',
61
65
  giftCard: '礼品卡',
@@ -82,6 +86,8 @@ var LABELS = {
82
86
  pickUpTime: '取餐時間',
83
87
  asap: '盡快',
84
88
  cash: '現金支付',
89
+ cashReceived: '收取現金',
90
+ changeDue: '找零',
85
91
  eftpos: '刷卡支付',
86
92
  wallet: '錢包支付',
87
93
  giftCard: '禮品卡',
@@ -95,6 +101,14 @@ var LABELS = {
95
101
  rounding: '抹零',
96
102
  gross: '重量',
97
103
  tare: '去皮'
104
+ },
105
+ ja: {
106
+ cashReceived: 'お預かり',
107
+ changeDue: 'お釣り'
108
+ },
109
+ pt: {
110
+ cashReceived: 'Dinheiro recebido',
111
+ changeDue: 'Troco'
98
112
  }
99
113
  };
100
114
  export function buildSmallTicketData(params) {
@@ -166,7 +180,7 @@ function buildBaseData(params) {
166
180
  order_number: orderNumber,
167
181
  shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
168
182
  shop_phone: stringify(shopInfo.phone || order.shop_phone),
169
- shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
183
+ shop_address: stringify(shopInfo.receipt_address || shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
170
184
  original_payment_status: stringify(order.payment_status),
171
185
  is_repeat: 0,
172
186
  buzzer: stringify(order.buzzer || order.pickup_number || ((_order$metadata = order.metadata) === null || _order$metadata === void 0 ? void 0 : _order$metadata.buzzer)),
@@ -765,6 +779,11 @@ function buildPaymentData(params) {
765
779
  item: paymentMethodName(payment, params.locale),
766
780
  value: formatMoney((_payment$amount = payment.amount) !== null && _payment$amount !== void 0 ? _payment$amount : payment.origin_amount, params.currencySymbol)
767
781
  }];
782
+ items.push.apply(items, _toConsumableArray(buildCashChangePaymentItems({
783
+ payment: payment,
784
+ locale: params.locale,
785
+ currencySymbol: params.currencySymbol
786
+ })));
768
787
  var fundRecord = getFundRecord(payment);
769
788
  if (fundRecord) {
770
789
  items.push.apply(items, _toConsumableArray(buildFundRecordPaymentItems({
@@ -790,6 +809,35 @@ function buildPaymentData(params) {
790
809
  return items;
791
810
  });
792
811
  }
812
+ function buildCashChangePaymentItems(params) {
813
+ var payment = params.payment,
814
+ locale = params.locale,
815
+ currencySymbol = params.currencySymbol;
816
+ if (!shouldDisplayCashChange(payment)) return [];
817
+ return [{
818
+ item: label(locale, 'cashReceived'),
819
+ value: formatMoney(payment.metadata.actual_paid_amount, currencySymbol)
820
+ }, {
821
+ item: label(locale, 'changeDue'),
822
+ value: formatMoney(payment.metadata.change_given_amount, currencySymbol)
823
+ }];
824
+ }
825
+ function shouldDisplayCashChange(payment) {
826
+ var _payment$code, _payment$metadata2, _payment$metadata3;
827
+ if (stringify(payment.status).toLowerCase() !== 'paid') return false;
828
+ var paymentMethod = stringify((_payment$code = payment.code) !== null && _payment$code !== void 0 ? _payment$code : payment.payment_method).toUpperCase();
829
+ if (paymentMethod !== 'CASHMANUAL') return false;
830
+ var actualPaidAmount = (_payment$metadata2 = payment.metadata) === null || _payment$metadata2 === void 0 ? void 0 : _payment$metadata2.actual_paid_amount;
831
+ var changeGivenAmount = (_payment$metadata3 = payment.metadata) === null || _payment$metadata3 === void 0 ? void 0 : _payment$metadata3.change_given_amount;
832
+ if (!isNumericAmount(actualPaidAmount) || !isNumericAmount(changeGivenAmount)) return false;
833
+ return new Decimal(changeGivenAmount).toDecimalPlaces(2).gt(0);
834
+ }
835
+ function isNumericAmount(value) {
836
+ if (typeof value === 'number') return Number.isFinite(value);
837
+ if (typeof value !== 'string') return false;
838
+ var normalized = value.trim();
839
+ return normalized !== '' && /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i.test(normalized);
840
+ }
793
841
  function buildFundRecordPaymentItems(params) {
794
842
  var payment = params.payment,
795
843
  fundRecord = params.fundRecord,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
329
+ weekNum: 0 | 1 | 2 | 5 | 4 | 3 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -334,7 +334,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
334
334
  * 获取当前的客户搜索条件
335
335
  * @returns 当前搜索条件
336
336
  */
337
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
337
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
338
338
  /**
339
339
  * 获取客户列表状态(包含滚动加载相关状态)
340
340
  * @returns 客户状态
@@ -90,6 +90,13 @@ export declare class SalesImpl extends BaseModule implements Module, SalesModule
90
90
  private groupBookingsByResource;
91
91
  private isBookingMatchedResource;
92
92
  private sortMatchedBookings;
93
+ /** Unpaid:与 Current 重合的订单沿用 Current 顺序,其余欠款订单按开始时间降序追加。 */
94
+ private sortUnpaidBookings;
95
+ /**
96
+ * 构造资源详情的 Unpaid 列表:复用旧版当前/未来订单的展示计算,再补齐被预约状态/时间漏掉的欠款订单。
97
+ * Unpaid 的成员资格由调用方按付款状态筛好;这里仅负责展示字段与顺序。
98
+ */
99
+ private buildUnpaidBookings;
93
100
  /**
94
101
  * 资源下 bookings 的返回裁剪策略:
95
102
  * 1) 优先返回当前时刻正在进行中的预约(允许并发返回多条)
@@ -485,6 +485,64 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
485
485
  });
486
486
  }
487
487
 
488
+ /** Unpaid:与 Current 重合的订单沿用 Current 顺序,其余欠款订单按开始时间降序追加。 */
489
+ }, {
490
+ key: "sortUnpaidBookings",
491
+ value: function sortUnpaidBookings(bookings, currentBookings) {
492
+ var _this4 = this;
493
+ var currentOrderIndexes = new Map(currentBookings.map(function (booking, index) {
494
+ return [String(booking.order.order_id), index];
495
+ }));
496
+ return _toConsumableArray(bookings).sort(function (left, right) {
497
+ var leftIndex = currentOrderIndexes.get(String(left.order.order_id));
498
+ var rightIndex = currentOrderIndexes.get(String(right.order.order_id));
499
+ if (leftIndex !== undefined || rightIndex !== undefined) {
500
+ if (leftIndex === undefined) return 1;
501
+ if (rightIndex === undefined) return -1;
502
+ return leftIndex - rightIndex;
503
+ }
504
+ var leftStartAt = _this4.toBookingDateTime(left.start_date, left.start_time).valueOf();
505
+ var rightStartAt = _this4.toBookingDateTime(right.start_date, right.start_time).valueOf();
506
+ return rightStartAt - leftStartAt;
507
+ });
508
+ }
509
+
510
+ /**
511
+ * 构造资源详情的 Unpaid 列表:复用旧版当前/未来订单的展示计算,再补齐被预约状态/时间漏掉的欠款订单。
512
+ * Unpaid 的成员资格由调用方按付款状态筛好;这里仅负责展示字段与顺序。
513
+ */
514
+ }, {
515
+ key: "buildUnpaidBookings",
516
+ value: function buildUnpaidBookings(current, deviceCurrent, unpaidBookingList, currentBookings) {
517
+ var _this5 = this;
518
+ var legacyPrioritizedBookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, unpaidBookingList), {
519
+ includeAllFuture: true
520
+ });
521
+ var allBookings = this.sortMatchedBookings(unpaidBookingList.map(function (booking) {
522
+ var normalized = _this5.normalizeMatchedBooking(current, deviceCurrent, booking, {
523
+ includeCompleted: true
524
+ });
525
+ if (normalized) return normalized;
526
+ var appointmentStatus = _this5.getBookingAppointmentStatus(booking);
527
+ var status = appointmentStatus === 'started' ? 'occupied' : appointmentStatus === 'completed' ? 'completed' : 'reserved';
528
+ return _objectSpread(_objectSpread({}, booking), {}, {
529
+ status: status,
530
+ isTimeout: false,
531
+ timeoutTime: undefined,
532
+ progressPercent: undefined,
533
+ lateTime: undefined,
534
+ reserved_status: undefined,
535
+ remainingReserveTime: undefined
536
+ });
537
+ }));
538
+ var legacyOrderIds = new Set(legacyPrioritizedBookings.map(function (booking) {
539
+ return String(booking.order.order_id);
540
+ }));
541
+ return this.sortUnpaidBookings([].concat(_toConsumableArray(legacyPrioritizedBookings), _toConsumableArray(allBookings.filter(function (booking) {
542
+ return !legacyOrderIds.has(String(booking.order.order_id));
543
+ }))), currentBookings);
544
+ }
545
+
488
546
  /**
489
547
  * 资源下 bookings 的返回裁剪策略:
490
548
  * 1) 优先返回当前时刻正在进行中的预约(允许并发返回多条)
@@ -496,7 +554,7 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
496
554
  }, {
497
555
  key: "pickBookingsForCurrentPoint",
498
556
  value: function pickBookingsForCurrentPoint(current, bookings) {
499
- var _this4 = this;
557
+ var _this6 = this;
500
558
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
501
559
  if (bookings.length === 0) return [];
502
560
  var _this$getOperatingDay = this.getOperatingDayRange(current),
@@ -505,17 +563,17 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
505
563
 
506
564
  // 仅保留与 current 所属营业日窗口有时间交集的预约,避免跨营业日误命中
507
565
  var dayScopedBookings = bookings.filter(function (booking) {
508
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
509
- var endAt = _this4.toBookingDateTime(booking.end_date, booking.end_time);
566
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
567
+ var endAt = _this6.toBookingDateTime(booking.end_date, booking.end_time);
510
568
  if (!startAt.isValid() || !endAt.isValid()) return false;
511
- return startAt.isBefore(operatingDayEndExclusive) && _this4.isSameOrAfter(endAt, operatingDayStart);
569
+ return startAt.isBefore(operatingDayEndExclusive) && _this6.isSameOrAfter(endAt, operatingDayStart);
512
570
  });
513
571
  if (dayScopedBookings.length === 0) return [];
514
572
  var appendNextStartGroupIfNeeded = function appendNextStartGroupIfNeeded(selectedBookings) {
515
573
  if (selectedBookings.length === 0) return selectedBookings;
516
574
  if (options.includeAllFuture) {
517
575
  var allFutureBookings = dayScopedBookings.filter(function (booking) {
518
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
576
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
519
577
  return startAt.isValid() && startAt.isAfter(current);
520
578
  });
521
579
  return [].concat(_toConsumableArray(selectedBookings), _toConsumableArray(allFutureBookings));
@@ -525,21 +583,21 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
525
583
  });
526
584
  if (!shouldAppendNextGroup) return selectedBookings;
527
585
  var selectedStartValues = new Set(selectedBookings.map(function (booking) {
528
- return _this4.toBookingDateTime(booking.start_date, booking.start_time);
586
+ return _this6.toBookingDateTime(booking.start_date, booking.start_time);
529
587
  }).filter(function (startAt) {
530
588
  return startAt.isValid();
531
589
  }).map(function (startAt) {
532
590
  return startAt.valueOf();
533
591
  }));
534
592
  var futureCandidates = dayScopedBookings.filter(function (booking) {
535
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
593
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
536
594
  if (!startAt.isValid()) return false;
537
595
  return startAt.isAfter(current) && !selectedStartValues.has(startAt.valueOf());
538
596
  });
539
597
  if (futureCandidates.length === 0) return selectedBookings;
540
- var nextStartAt = _this4.toBookingDateTime(futureCandidates[0].start_date, futureCandidates[0].start_time).valueOf();
598
+ var nextStartAt = _this6.toBookingDateTime(futureCandidates[0].start_date, futureCandidates[0].start_time).valueOf();
541
599
  var nextStartGroup = futureCandidates.filter(function (booking) {
542
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
600
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
543
601
  return startAt.isValid() && startAt.valueOf() === nextStartAt;
544
602
  });
545
603
  if (nextStartGroup.length === 0) return selectedBookings;
@@ -551,10 +609,10 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
551
609
 
552
610
  // active: current 处于 [startAt, endAt] 区间
553
611
  var activeBookings = dayScopedBookings.filter(function (booking) {
554
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
555
- var endAt = _this4.toBookingDateTime(booking.end_date, booking.end_time);
612
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
613
+ var endAt = _this6.toBookingDateTime(booking.end_date, booking.end_time);
556
614
  if (!startAt.isValid() || !endAt.isValid()) return false;
557
- return _this4.isSameOrAfter(current, startAt) && _this4.isSameOrBefore(current, endAt);
615
+ return _this6.isSameOrAfter(current, startAt) && _this6.isSameOrBefore(current, endAt);
558
616
  });
559
617
  if (activeBookings.length > 0) return appendNextStartGroupIfNeeded(activeBookings);
560
618
 
@@ -566,14 +624,14 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
566
624
 
567
625
  // upcoming: 从未来预约里只取最早那一组(同 start_time)
568
626
  var upcoming = dayScopedBookings.filter(function (booking) {
569
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
627
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
570
628
  return startAt.isValid() && startAt.isAfter(current);
571
629
  });
572
630
  if (upcoming.length > 0) {
573
631
  if (options.includeAllFuture) return upcoming;
574
632
  var firstStartAt = this.toBookingDateTime(upcoming[0].start_date, upcoming[0].start_time).valueOf();
575
633
  var upcomingStartGroup = upcoming.filter(function (booking) {
576
- var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
634
+ var startAt = _this6.toBookingDateTime(booking.start_date, booking.start_time);
577
635
  return startAt.valueOf() === firstStartAt;
578
636
  });
579
637
  return appendNextStartGroupIfNeeded(upcomingStartGroup);
@@ -626,10 +684,10 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
626
684
  }, {
627
685
  key: "normalizeResourceBookings",
628
686
  value: function normalizeResourceBookings(current, deviceCurrent, bookingList) {
629
- var _this5 = this;
687
+ var _this7 = this;
630
688
  var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
631
689
  var normalizedBookings = bookingList.map(function (booking) {
632
- return _this5.normalizeMatchedBooking(current, deviceCurrent, booking, options);
690
+ return _this7.normalizeMatchedBooking(current, deviceCurrent, booking, options);
633
691
  }).filter(function (booking) {
634
692
  return Boolean(booking);
635
693
  }).filter(function (booking) {
@@ -759,7 +817,7 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
759
817
  var _getResourceBookingList = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(currentTime) {
760
818
  var _resourceResponse$dat,
761
819
  _resourceResponse$dat2,
762
- _this6 = this;
820
+ _this8 = this;
763
821
  var bookingList,
764
822
  deviceTime,
765
823
  current,
@@ -815,16 +873,16 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
815
873
  rawBookingMap = this.groupBookingsByResource(bookingList);
816
874
  bookingMap = this.groupBookingsByResource(normalizedBookings); // 输出:每个资源都返回;bookings 可能是 0 / 1 / 多条(并发场景)
817
875
  list = resourceList.map(function (resource) {
818
- var resourceId = _this6.getResourceId(resource);
876
+ var resourceId = _this8.getResourceId(resource);
819
877
  var rawMatchedBookings = rawBookingMap.get(String(resourceId)) || [];
820
878
  var matchedBookings = bookingMap.get(String(resourceId)) || [];
821
879
  var statsBookings = rawMatchedBookings.filter(function (booking) {
822
- return _this6.isBookingIncludedInStats(booking);
880
+ return _this8.isBookingIncludedInStats(booking);
823
881
  });
824
- var orderCount = _this6.countBookingOrders(statsBookings);
882
+ var orderCount = _this8.countBookingOrders(statsBookings);
825
883
  var bookingCount = statsBookings.length;
826
- var compeleteBookingCount = _this6.countCompletedBookings(statsBookings);
827
- var bookings = _this6.pickBookingsForCurrentPoint(current, matchedBookings);
884
+ var compeleteBookingCount = _this8.countCompletedBookings(statsBookings);
885
+ var bookings = _this8.pickBookingsForCurrentPoint(current, matchedBookings);
828
886
  return _objectSpread(_objectSpread({}, resource), {}, {
829
887
  resource_id: resourceId,
830
888
  orderCount: orderCount,
@@ -861,7 +919,7 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
861
919
  var _getResourceBookingItem = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(params) {
862
920
  var _resourceResponse$dat3,
863
921
  _resourceResponse$dat4,
864
- _this7 = this,
922
+ _this9 = this,
865
923
  _params$bookingList;
866
924
  var current, deviceCurrent, resourceResponse, resourceList, targetResource, resourceId, matchedBookingList, statsBookingList, completedBookingList, unpaidBookingList, bookings, completedBookings, unpaidBookings, orderCount, bookingCount, compeleteBookingCount;
867
925
  return _regeneratorRuntime().wrap(function _callee6$(_context6) {
@@ -901,7 +959,7 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
901
959
  return _context6.abrupt("return", null);
902
960
  case 12:
903
961
  targetResource = resourceList.find(function (resource) {
904
- return String(_this7.getResourceId(resource)) === String(params.resourceId);
962
+ return String(_this9.getResourceId(resource)) === String(params.resourceId);
905
963
  });
906
964
  if (targetResource) {
907
965
  _context6.next = 15;
@@ -911,18 +969,18 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
911
969
  case 15:
912
970
  resourceId = this.getResourceId(targetResource);
913
971
  matchedBookingList = params.bookingList.filter(function (booking) {
914
- return _this7.isBookingMatchedResource(booking, resourceId);
972
+ return _this9.isBookingMatchedResource(booking, resourceId);
915
973
  });
916
974
  statsBookingList = matchedBookingList.filter(function (booking) {
917
- return _this7.isBookingIncludedInStats(booking);
975
+ return _this9.isBookingIncludedInStats(booking);
918
976
  });
919
977
  completedBookingList = matchedBookingList.filter(function (booking) {
920
- return _this7.getBookingAppointmentStatus(booking) === 'completed';
978
+ return _this9.getBookingAppointmentStatus(booking) === 'completed';
921
979
  }); // const unpaidBookingList = matchedBookingList.filter(
922
980
  // (booking) => this.getBookingOrderPaymentStatus(booking) === 'unpaid' || this.getBookingOrderPaymentStatus(booking) === 'payment_processing',
923
981
  // );
924
982
  unpaidBookingList = matchedBookingList.filter(function (booking) {
925
- return _this7.isUnpaidBooking(booking);
983
+ return _this9.isUnpaidBooking(booking);
926
984
  });
927
985
  bookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, matchedBookingList), {
928
986
  includeAllFuture: true
@@ -938,9 +996,7 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
938
996
  remainingReserveTime: undefined
939
997
  });
940
998
  });
941
- unpaidBookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, unpaidBookingList), {
942
- includeAllFuture: true
943
- });
999
+ unpaidBookings = this.buildUnpaidBookings(current, deviceCurrent, unpaidBookingList, bookings);
944
1000
  orderCount = this.countBookingOrders(statsBookingList);
945
1001
  bookingCount = statsBookingList.length;
946
1002
  compeleteBookingCount = this.countCompletedBookings(statsBookingList);
@@ -234,15 +234,25 @@ class DataVariantEvaluator {
234
234
  if (!appliedInfo?.appliedFields?.length) {
235
235
  return originalItem;
236
236
  }
237
+
238
+ // 套餐加价/减价使用配置价;仅商品原价模式跟随子商品的 Data Variant 价格。
239
+ const isOriginalPriceBundleItem = originalItem.price_type === 'markup' && originalItem.price_type_ext === 'product_price';
240
+ const appliedFields = appliedInfo.appliedFields.filter(field => field !== 'price' || isOriginalPriceBundleItem);
241
+ if (!appliedFields.length) {
242
+ return originalItem;
243
+ }
237
244
  const result = {
238
245
  ...originalItem
239
246
  };
240
- for (const field of appliedInfo.appliedFields) {
247
+ for (const field of appliedFields) {
241
248
  if (resolvedItem[field] !== undefined) {
242
249
  result[field] = resolvedItem[field];
243
250
  }
244
251
  }
245
- result._dataVariant = appliedInfo;
252
+ result._dataVariant = {
253
+ ...appliedInfo,
254
+ appliedFields
255
+ };
246
256
  return result;
247
257
  }
248
258
  evaluateProductRules(rule, product, businessData, menuScopeMap) {
@@ -179,6 +179,8 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
179
179
  private calculateOrderPaidPaymentTotal;
180
180
  private getDepositAmount;
181
181
  private normalizeDepositAmount;
182
+ private normalizeDepositFlag;
183
+ private getHistoricalDepositSnapshot;
182
184
  private getLastOrderDepositSnapshot;
183
185
  private getLastOrderSubmitSnapshot;
184
186
  private applyDepositAmountToSummary;
@@ -512,7 +514,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
512
514
  generateIdempotencyToken(): string;
513
515
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
514
516
  createOrder(params: CommitOrderParams['query']): {
515
- type: "virtual" | "appointment_booking";
517
+ type: "appointment_booking" | "virtual";
516
518
  platform: string;
517
519
  sales_channel: string;
518
520
  order_sales_channel: string;
@@ -1006,19 +1006,26 @@ class OrderModule extends _BaseModule.BaseModule {
1006
1006
  normalizeDepositAmount(amount) {
1007
1007
  return _decimal.default.max(new _decimal.default(Number(amount) || 0), 0).toDecimalPlaces(2).toFixed(2);
1008
1008
  }
1009
- getLastOrderDepositSnapshot() {
1010
- const lastOrderInfo = this.store.lastOrderInfo;
1011
- if (!lastOrderInfo || typeof lastOrderInfo !== 'object') return null;
1012
- const rawDepositAmount = lastOrderInfo.deposit_amount ?? lastOrderInfo.summary?.deposit_amount;
1009
+ normalizeDepositFlag(value) {
1010
+ if (value === 0 || value === '0') return 0;
1011
+ if (value === 1 || value === '1') return 1;
1012
+ return null;
1013
+ }
1014
+ getHistoricalDepositSnapshot(source) {
1015
+ if (!source || typeof source !== 'object') return null;
1016
+ const record = source;
1017
+ const rawDepositAmount = record.deposit_amount ?? record.summary?.deposit_amount;
1013
1018
  const depositAmount = this.normalizeDepositAmount(rawDepositAmount ?? 0);
1014
- const hasDepositAmount = new _decimal.default(depositAmount).gt(0);
1015
- const isDeposit = Number(lastOrderInfo.is_deposit) === 1 || hasDepositAmount;
1016
- if (!isDeposit || !hasDepositAmount) return null;
1019
+ if (!new _decimal.default(depositAmount).gt(0)) return null;
1017
1020
  return {
1018
- isDeposit: 1,
1021
+ // 兼容历史数据:旧快照缺少 is_deposit 时,沿用正定金金额的推导规则。
1022
+ isDeposit: this.normalizeDepositFlag(record.is_deposit) ?? 1,
1019
1023
  depositAmount
1020
1024
  };
1021
1025
  }
1026
+ getLastOrderDepositSnapshot() {
1027
+ return this.getHistoricalDepositSnapshot(this.store.lastOrderInfo);
1028
+ }
1022
1029
  getLastOrderSubmitSnapshot() {
1023
1030
  const lastOrderInfo = this.store.lastOrderInfo;
1024
1031
  if (!lastOrderInfo || typeof lastOrderInfo !== 'object') return {};
@@ -1066,7 +1073,7 @@ class OrderModule extends _BaseModule.BaseModule {
1066
1073
  }
1067
1074
  };
1068
1075
  tempOrder.deposit_amount = snapshot.depositAmount;
1069
- tempOrder.is_deposit = tempOrder.is_deposit === 0 && new _decimal.default(tempOrder.deposit_amount || 0).gt(0) ? 0 : snapshot.isDeposit;
1076
+ tempOrder.is_deposit = snapshot.isDeposit;
1070
1077
  return nextSummary;
1071
1078
  }
1072
1079
  isDepositOrder(tempOrder, depositAmount) {
@@ -1603,10 +1610,17 @@ class OrderModule extends _BaseModule.BaseModule {
1603
1610
  ...(0, _lodashEs.cloneDeep)(snapshot.summary || {})
1604
1611
  };
1605
1612
  const shouldUseManualDepositOverride = Boolean(manualDepositOverride && manualDepositOverride.productStructuralFingerprint === this.buildOrderProductsStructuralFingerprint(tempOrder.products));
1613
+ const historicalDepositSnapshot = this.getHistoricalDepositSnapshot(snapshot);
1606
1614
  if (shouldUseManualDepositOverride) {
1607
1615
  summary = this.applyDepositAmountToSummary(tempOrder, summary, manualDepositOverride.amount);
1608
- } else if (manualDepositOverride) {
1609
- this.clearManualDepositOverride(tempOrder);
1616
+ } else {
1617
+ if (manualDepositOverride) {
1618
+ this.clearManualDepositOverride(tempOrder);
1619
+ }
1620
+ if (historicalDepositSnapshot) {
1621
+ summary = this.applyDepositAmountToSummary(tempOrder, summary, historicalDepositSnapshot.depositAmount);
1622
+ tempOrder.is_deposit = historicalDepositSnapshot.isDeposit;
1623
+ }
1610
1624
  }
1611
1625
  const isPayableAmountUnchanged = this.isSnapshotPayableAmountUnchanged(tempOrder, snapshot, summary);
1612
1626
  if (!isPayableAmountUnchanged) return null;
@@ -1623,8 +1637,8 @@ class OrderModule extends _BaseModule.BaseModule {
1623
1637
  tempOrder.surcharges = (0, _lodashEs.cloneDeep)(snapshot.surcharges);
1624
1638
  }
1625
1639
  tempOrder.surcharge_fee = summary.surcharge_fee || tempOrder.surcharge_fee;
1626
- tempOrder.deposit_amount = summary.deposit_amount || '0.00';
1627
- tempOrder.is_deposit = summary.deposit_amount !== '0.00' ? 1 : 0;
1640
+ tempOrder.deposit_amount = this.normalizeDepositAmount(summary.deposit_amount || 0);
1641
+ tempOrder.is_deposit = shouldUseManualDepositOverride ? new _decimal.default(tempOrder.deposit_amount).gt(0) ? 1 : 0 : historicalDepositSnapshot?.isDeposit ?? (new _decimal.default(tempOrder.deposit_amount).gt(0) ? 1 : 0);
1628
1642
  const previousSummary = this.store.summary;
1629
1643
  this.store.summary = summary;
1630
1644
  this.updateTempOrderPaymentStatus(tempOrder, {
@@ -2081,7 +2095,7 @@ class OrderModule extends _BaseModule.BaseModule {
2081
2095
  const isExistingDepositDisabled = tempOrder.is_deposit === 0 && new _decimal.default(tempOrder.deposit_amount || 0).gt(0);
2082
2096
  tempOrder.deposit_amount = depositAmount;
2083
2097
  tempOrder.is_deposit = hasDepositAmount && !isExistingDepositDisabled ? 1 : 0;
2084
- return this.applyLastOrderDepositSnapshot(tempOrder, nextSummary);
2098
+ return shouldUseManualDepositOverride ? nextSummary : this.applyLastOrderDepositSnapshot(tempOrder, nextSummary);
2085
2099
  }
2086
2100
  async recalculateSummary(options) {
2087
2101
  const tempOrder = options?.createIfMissing ? this.ensureTempOrder() : this.store.tempOrder;
@@ -4187,6 +4201,7 @@ class OrderModule extends _BaseModule.BaseModule {
4187
4201
  externalSaleNumber: nextTempOrder.external_sale_number
4188
4202
  };
4189
4203
  const rawSummary = raw.summary && typeof raw.summary === 'object' ? raw.summary : {};
4204
+ const historicalDepositSnapshot = this.getHistoricalDepositSnapshot(sourceLastOrderInfo);
4190
4205
  const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map(s => ({
4191
4206
  ...(s || {})
4192
4207
  })) : (0, _lodashEs.cloneDeep)(nextTempOrder.surcharges || []);
@@ -4205,6 +4220,10 @@ class OrderModule extends _BaseModule.BaseModule {
4205
4220
  surcharges: (0, _lodashEs.cloneDeep)(nextTempOrder.surcharges || []),
4206
4221
  shop_discount: nextTempOrder.shop_discount || '0.00',
4207
4222
  productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || []),
4223
+ ...(historicalDepositSnapshot ? {
4224
+ is_deposit: historicalDepositSnapshot.isDeposit,
4225
+ deposit_amount: historicalDepositSnapshot.depositAmount
4226
+ } : {}),
4208
4227
  // merged record 的 summary 仍是远端旧值,保留快照仅用于完整重算的价格清理基线。
4209
4228
  ...(isMergedSalesDetailHydrate ? {
4210
4229
  requiresFullSummaryRecalculation: true
@@ -22,6 +22,8 @@ const LABELS = {
22
22
  pickUpTime: 'Pick-up time',
23
23
  asap: 'ASAP',
24
24
  cash: 'Cash',
25
+ cashReceived: 'Cash received',
26
+ changeDue: 'Change due',
25
27
  eftpos: 'Eftpos',
26
28
  wallet: 'Wallet',
27
29
  giftCard: 'Gift card',
@@ -48,6 +50,8 @@ const LABELS = {
48
50
  pickUpTime: '取餐时间',
49
51
  asap: '尽快',
50
52
  cash: '现金支付',
53
+ cashReceived: '收取现金',
54
+ changeDue: '找零',
51
55
  eftpos: '刷卡支付',
52
56
  wallet: '钱包支付',
53
57
  giftCard: '礼品卡',
@@ -74,6 +78,8 @@ const LABELS = {
74
78
  pickUpTime: '取餐時間',
75
79
  asap: '盡快',
76
80
  cash: '現金支付',
81
+ cashReceived: '收取現金',
82
+ changeDue: '找零',
77
83
  eftpos: '刷卡支付',
78
84
  wallet: '錢包支付',
79
85
  giftCard: '禮品卡',
@@ -87,6 +93,14 @@ const LABELS = {
87
93
  rounding: '抹零',
88
94
  gross: '重量',
89
95
  tare: '去皮'
96
+ },
97
+ ja: {
98
+ cashReceived: 'お預かり',
99
+ changeDue: 'お釣り'
100
+ },
101
+ pt: {
102
+ cashReceived: 'Dinheiro recebido',
103
+ changeDue: 'Troco'
90
104
  }
91
105
  };
92
106
  function buildSmallTicketData(params) {
@@ -161,7 +175,7 @@ function buildBaseData(params) {
161
175
  order_number: orderNumber,
162
176
  shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
163
177
  shop_phone: stringify(shopInfo.phone || order.shop_phone),
164
- shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
178
+ shop_address: stringify(shopInfo.receipt_address || shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
165
179
  original_payment_status: stringify(order.payment_status),
166
180
  is_repeat: 0,
167
181
  buzzer: stringify(order.buzzer || order.pickup_number || order.metadata?.buzzer),
@@ -734,6 +748,11 @@ function buildPaymentData(params) {
734
748
  item: paymentMethodName(payment, params.locale),
735
749
  value: formatMoney(payment.amount ?? payment.origin_amount, params.currencySymbol)
736
750
  }];
751
+ items.push(...buildCashChangePaymentItems({
752
+ payment,
753
+ locale: params.locale,
754
+ currencySymbol: params.currencySymbol
755
+ }));
737
756
  const fundRecord = getFundRecord(payment);
738
757
  if (fundRecord) {
739
758
  items.push(...buildFundRecordPaymentItems({
@@ -758,6 +777,36 @@ function buildPaymentData(params) {
758
777
  return items;
759
778
  });
760
779
  }
780
+ function buildCashChangePaymentItems(params) {
781
+ const {
782
+ payment,
783
+ locale,
784
+ currencySymbol
785
+ } = params;
786
+ if (!shouldDisplayCashChange(payment)) return [];
787
+ return [{
788
+ item: label(locale, 'cashReceived'),
789
+ value: formatMoney(payment.metadata.actual_paid_amount, currencySymbol)
790
+ }, {
791
+ item: label(locale, 'changeDue'),
792
+ value: formatMoney(payment.metadata.change_given_amount, currencySymbol)
793
+ }];
794
+ }
795
+ function shouldDisplayCashChange(payment) {
796
+ if (stringify(payment.status).toLowerCase() !== 'paid') return false;
797
+ const paymentMethod = stringify(payment.code ?? payment.payment_method).toUpperCase();
798
+ if (paymentMethod !== 'CASHMANUAL') return false;
799
+ const actualPaidAmount = payment.metadata?.actual_paid_amount;
800
+ const changeGivenAmount = payment.metadata?.change_given_amount;
801
+ if (!isNumericAmount(actualPaidAmount) || !isNumericAmount(changeGivenAmount)) return false;
802
+ return new _decimal.default(changeGivenAmount).toDecimalPlaces(2).gt(0);
803
+ }
804
+ function isNumericAmount(value) {
805
+ if (typeof value === 'number') return Number.isFinite(value);
806
+ if (typeof value !== 'string') return false;
807
+ const normalized = value.trim();
808
+ return normalized !== '' && /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i.test(normalized);
809
+ }
761
810
  function buildFundRecordPaymentItems(params) {
762
811
  const {
763
812
  payment,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
329
+ weekNum: 0 | 1 | 2 | 5 | 4 | 3 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -334,7 +334,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
334
334
  * 获取当前的客户搜索条件
335
335
  * @returns 当前搜索条件
336
336
  */
337
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
337
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
338
338
  /**
339
339
  * 获取客户列表状态(包含滚动加载相关状态)
340
340
  * @returns 客户状态
@@ -90,6 +90,13 @@ export declare class SalesImpl extends BaseModule implements Module, SalesModule
90
90
  private groupBookingsByResource;
91
91
  private isBookingMatchedResource;
92
92
  private sortMatchedBookings;
93
+ /** Unpaid:与 Current 重合的订单沿用 Current 顺序,其余欠款订单按开始时间降序追加。 */
94
+ private sortUnpaidBookings;
95
+ /**
96
+ * 构造资源详情的 Unpaid 列表:复用旧版当前/未来订单的展示计算,再补齐被预约状态/时间漏掉的欠款订单。
97
+ * Unpaid 的成员资格由调用方按付款状态筛好;这里仅负责展示字段与顺序。
98
+ */
99
+ private buildUnpaidBookings;
93
100
  /**
94
101
  * 资源下 bookings 的返回裁剪策略:
95
102
  * 1) 优先返回当前时刻正在进行中的预约(允许并发返回多条)
@@ -340,6 +340,53 @@ class SalesImpl extends _BaseModule.BaseModule {
340
340
  });
341
341
  }
342
342
 
343
+ /** Unpaid:与 Current 重合的订单沿用 Current 顺序,其余欠款订单按开始时间降序追加。 */
344
+ sortUnpaidBookings(bookings, currentBookings) {
345
+ const currentOrderIndexes = new Map(currentBookings.map((booking, index) => [String(booking.order.order_id), index]));
346
+ return [...bookings].sort((left, right) => {
347
+ const leftIndex = currentOrderIndexes.get(String(left.order.order_id));
348
+ const rightIndex = currentOrderIndexes.get(String(right.order.order_id));
349
+ if (leftIndex !== undefined || rightIndex !== undefined) {
350
+ if (leftIndex === undefined) return 1;
351
+ if (rightIndex === undefined) return -1;
352
+ return leftIndex - rightIndex;
353
+ }
354
+ const leftStartAt = this.toBookingDateTime(left.start_date, left.start_time).valueOf();
355
+ const rightStartAt = this.toBookingDateTime(right.start_date, right.start_time).valueOf();
356
+ return rightStartAt - leftStartAt;
357
+ });
358
+ }
359
+
360
+ /**
361
+ * 构造资源详情的 Unpaid 列表:复用旧版当前/未来订单的展示计算,再补齐被预约状态/时间漏掉的欠款订单。
362
+ * Unpaid 的成员资格由调用方按付款状态筛好;这里仅负责展示字段与顺序。
363
+ */
364
+ buildUnpaidBookings(current, deviceCurrent, unpaidBookingList, currentBookings) {
365
+ const legacyPrioritizedBookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, unpaidBookingList), {
366
+ includeAllFuture: true
367
+ });
368
+ const allBookings = this.sortMatchedBookings(unpaidBookingList.map(booking => {
369
+ const normalized = this.normalizeMatchedBooking(current, deviceCurrent, booking, {
370
+ includeCompleted: true
371
+ });
372
+ if (normalized) return normalized;
373
+ const appointmentStatus = this.getBookingAppointmentStatus(booking);
374
+ const status = appointmentStatus === 'started' ? 'occupied' : appointmentStatus === 'completed' ? 'completed' : 'reserved';
375
+ return {
376
+ ...booking,
377
+ status,
378
+ isTimeout: false,
379
+ timeoutTime: undefined,
380
+ progressPercent: undefined,
381
+ lateTime: undefined,
382
+ reserved_status: undefined,
383
+ remainingReserveTime: undefined
384
+ };
385
+ }));
386
+ const legacyOrderIds = new Set(legacyPrioritizedBookings.map(booking => String(booking.order.order_id)));
387
+ return this.sortUnpaidBookings([...legacyPrioritizedBookings, ...allBookings.filter(booking => !legacyOrderIds.has(String(booking.order.order_id)))], currentBookings);
388
+ }
389
+
343
390
  /**
344
391
  * 资源下 bookings 的返回裁剪策略:
345
392
  * 1) 优先返回当前时刻正在进行中的预约(允许并发返回多条)
@@ -679,9 +726,7 @@ class SalesImpl extends _BaseModule.BaseModule {
679
726
  remainingReserveTime: undefined
680
727
  };
681
728
  });
682
- const unpaidBookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, unpaidBookingList), {
683
- includeAllFuture: true
684
- });
729
+ const unpaidBookings = this.buildUnpaidBookings(current, deviceCurrent, unpaidBookingList, bookings);
685
730
  const orderCount = this.countBookingOrders(statsBookingList);
686
731
  const bookingCount = statsBookingList.length;
687
732
  const compeleteBookingCount = this.countCompletedBookings(statsBookingList);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.290",
4
+ "version": "2.2.291",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",