@pisell/pisellos 2.2.176 → 2.2.178

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.
@@ -127,6 +127,9 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
127
127
  private calculatePaymentTotal;
128
128
  private calculatePaidPaymentSummary;
129
129
  private calculatePaymentServiceFee;
130
+ private formatSummaryMetadataMoney;
131
+ private syncSummaryProductMetadata;
132
+ private calculateSummaryPaymentBalance;
130
133
  private getPaymentTargetAmount;
131
134
  ensureTempOrder(): OrderTempOrder;
132
135
  restoreOrder(): OrderTempOrder;
@@ -1134,6 +1134,91 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1134
1134
  var fixedAmount = new Decimal(serviceCharge.amount || 0);
1135
1135
  return new Decimal(payment.amount || 0).times(percentage).plus(fixedAmount);
1136
1136
  }
1137
+ }, {
1138
+ key: "formatSummaryMetadataMoney",
1139
+ value: function formatSummaryMetadataMoney(value) {
1140
+ if (value === undefined || value === null || value === '') return undefined;
1141
+ if (value instanceof Decimal) return value.toFixed(2);
1142
+ return new Decimal(String(value || 0)).toFixed(2);
1143
+ }
1144
+ }, {
1145
+ key: "syncSummaryProductMetadata",
1146
+ value: function syncSummaryProductMetadata(products) {
1147
+ var moneyKeys = ['main_product_attached_bundle_surcharge_fee', 'main_product_attached_bundle_tax_fee', 'surcharge_rounding_remainder', 'tax_fee_rounding_remainder'];
1148
+ var _iterator5 = _createForOfIteratorHelper(products || []),
1149
+ _step5;
1150
+ try {
1151
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
1152
+ var product = _step5.value;
1153
+ var productRecord = product;
1154
+ var metadata = productRecord.metadata && _typeof(productRecord.metadata) === 'object' ? _objectSpread({}, productRecord.metadata) : {};
1155
+ var hasMetadataPatch = false;
1156
+ var _iterator6 = _createForOfIteratorHelper(moneyKeys),
1157
+ _step6;
1158
+ try {
1159
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1160
+ var key = _step6.value;
1161
+ var value = this.formatSummaryMetadataMoney(productRecord[key]);
1162
+ if (value === undefined) continue;
1163
+ metadata[key] = value;
1164
+ hasMetadataPatch = true;
1165
+ }
1166
+ } catch (err) {
1167
+ _iterator6.e(err);
1168
+ } finally {
1169
+ _iterator6.f();
1170
+ }
1171
+ if (Array.isArray(productRecord.relation_surcharge_ids)) {
1172
+ metadata.relation_surcharge_ids = productRecord.relation_surcharge_ids;
1173
+ hasMetadataPatch = true;
1174
+ }
1175
+ if (hasMetadataPatch) productRecord.metadata = metadata;
1176
+ if (!Array.isArray(productRecord.product_bundle)) continue;
1177
+ var _iterator7 = _createForOfIteratorHelper(productRecord.product_bundle),
1178
+ _step7;
1179
+ try {
1180
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
1181
+ var bundle = _step7.value;
1182
+ var bundleRecord = bundle;
1183
+ var bundleMetadata = bundleRecord.metadata && _typeof(bundleRecord.metadata) === 'object' ? _objectSpread({}, bundleRecord.metadata) : {};
1184
+ var hasBundleMetadataPatch = false;
1185
+ var bundleSurchargeFee = this.formatSummaryMetadataMoney(bundleRecord.surcharge_fee);
1186
+ if (bundleSurchargeFee !== undefined) {
1187
+ bundleMetadata.surcharge_fee = bundleSurchargeFee;
1188
+ hasBundleMetadataPatch = true;
1189
+ }
1190
+ if (Array.isArray(bundleRecord.relation_surcharge_ids)) {
1191
+ bundleMetadata.relation_surcharge_ids = bundleRecord.relation_surcharge_ids;
1192
+ hasBundleMetadataPatch = true;
1193
+ }
1194
+ if (hasBundleMetadataPatch) bundleRecord.metadata = bundleMetadata;
1195
+ }
1196
+ } catch (err) {
1197
+ _iterator7.e(err);
1198
+ } finally {
1199
+ _iterator7.f();
1200
+ }
1201
+ }
1202
+ } catch (err) {
1203
+ _iterator5.e(err);
1204
+ } finally {
1205
+ _iterator5.f();
1206
+ }
1207
+ }
1208
+ }, {
1209
+ key: "calculateSummaryPaymentBalance",
1210
+ value: function calculateSummaryPaymentBalance(params) {
1211
+ var tempOrder = params.tempOrder,
1212
+ summary = params.summary,
1213
+ orderPaidAmount = params.orderPaidAmount;
1214
+ var depositAmount = summary.deposit_amount || tempOrder.deposit_amount || '0.00';
1215
+ var isDeposit = tempOrder.is_deposit === 1 || new Decimal(depositAmount || 0).gt(0);
1216
+ var targetAmount = isDeposit ? new Decimal(depositAmount || 0) : new Decimal(summary.total_amount || summary.expect_amount || 0);
1217
+ return {
1218
+ amountGap: Decimal.max(0, targetAmount.minus(orderPaidAmount)).toFixed(2),
1219
+ totalRefundAmount: Decimal.max(0, orderPaidAmount.minus(targetAmount)).toFixed(2)
1220
+ };
1221
+ }
1137
1222
  }, {
1138
1223
  key: "getPaymentTargetAmount",
1139
1224
  value: function getPaymentTargetAmount() {
@@ -1450,7 +1535,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1450
1535
  key: "recalculateSummary",
1451
1536
  value: function () {
1452
1537
  var _recalculateSummary = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12(options) {
1453
- var tempOrder, salesSummary, existedSummary, paidPaymentSummary, emptySummary, salesSummaryResult, summary;
1538
+ var tempOrder, salesSummary, paidPaymentSummary, _paymentBalance, emptySummary, salesSummaryResult, paymentBalance, summary;
1454
1539
  return _regeneratorRuntime().wrap(function _callee12$(_context14) {
1455
1540
  while (1) switch (_context14.prev = _context14.next) {
1456
1541
  case 0:
@@ -1462,16 +1547,21 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1462
1547
  return _context14.abrupt("return", null);
1463
1548
  case 3:
1464
1549
  salesSummary = this.getSalesSummary();
1465
- existedSummary = this.store.summary || createEmptySummary();
1466
1550
  paidPaymentSummary = this.calculatePaidPaymentSummary(tempOrder.payments || []);
1467
1551
  if (salesSummary) {
1468
1552
  _context14.next = 11;
1469
1553
  break;
1470
1554
  }
1555
+ _paymentBalance = this.calculateSummaryPaymentBalance({
1556
+ tempOrder: tempOrder,
1557
+ summary: createEmptySummary(),
1558
+ orderPaidAmount: paidPaymentSummary.orderPaidAmount
1559
+ });
1471
1560
  emptySummary = _objectSpread(_objectSpread({}, createEmptySummary()), {}, {
1472
- total_refund_amount: existedSummary.total_refund_amount || '0.00',
1561
+ total_refund_amount: _paymentBalance.totalRefundAmount,
1473
1562
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
1474
1563
  order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
1564
+ amount_gap: _paymentBalance.amountGap,
1475
1565
  pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
1476
1566
  });
1477
1567
  this.store.summary = emptySummary;
@@ -1486,10 +1576,17 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1486
1576
  });
1487
1577
  case 13:
1488
1578
  salesSummaryResult = _context14.sent;
1579
+ this.syncSummaryProductMetadata(tempOrder.products || []);
1580
+ paymentBalance = this.calculateSummaryPaymentBalance({
1581
+ tempOrder: tempOrder,
1582
+ summary: salesSummaryResult,
1583
+ orderPaidAmount: paidPaymentSummary.orderPaidAmount
1584
+ });
1489
1585
  summary = _objectSpread(_objectSpread({}, salesSummaryResult), {}, {
1490
- total_refund_amount: existedSummary.total_refund_amount || '0.00',
1586
+ total_refund_amount: paymentBalance.totalRefundAmount,
1491
1587
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
1492
1588
  order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
1589
+ amount_gap: paymentBalance.amountGap,
1493
1590
  pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
1494
1591
  });
1495
1592
  this.store.summary = summary;
@@ -1504,7 +1601,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1504
1601
  tempOrder.deposit_amount = summary.deposit_amount || '0.00';
1505
1602
  tempOrder.is_deposit = summary.deposit_amount !== '0.00' ? 1 : 0;
1506
1603
  return _context14.abrupt("return", this.store.summary);
1507
- case 23:
1604
+ case 25:
1508
1605
  case "end":
1509
1606
  return _context14.stop();
1510
1607
  }
@@ -1791,13 +1888,28 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1791
1888
  }, {
1792
1889
  key: "addOrderPayment",
1793
1890
  value: function addOrderPayment(payment) {
1891
+ var _paymentRecord$status,
1892
+ _ref21,
1893
+ _paymentRecord$origin,
1894
+ _this6 = this;
1794
1895
  this.logInfo('addOrderPayment', {
1795
1896
  payment: payment
1796
1897
  });
1797
1898
  var tempOrder = this.ensureTempOrder();
1798
- var mapped = mapPaymentItemsToOrderPayments([payment]);
1899
+ var paymentRecord = payment;
1900
+ var mapped = mapPaymentItemsToOrderPayments([_objectSpread(_objectSpread({}, paymentRecord), {}, {
1901
+ status: (_paymentRecord$status = paymentRecord.status) !== null && _paymentRecord$status !== void 0 ? _paymentRecord$status : 'paid',
1902
+ origin_amount: (_ref21 = (_paymentRecord$origin = paymentRecord.origin_amount) !== null && _paymentRecord$origin !== void 0 ? _paymentRecord$origin : paymentRecord.amount) !== null && _ref21 !== void 0 ? _ref21 : '0.00'
1903
+ })]);
1799
1904
  tempOrder.payments = [].concat(_toConsumableArray(tempOrder.payments || []), _toConsumableArray(mapped));
1800
1905
  this.persistTempOrder();
1906
+ void this.recalculateSummary({
1907
+ createIfMissing: true
1908
+ }).catch(function (error) {
1909
+ _this6.logError('recalculate summary after addOrderPayment failed', {
1910
+ error: error instanceof Error ? error.message : String(error)
1911
+ });
1912
+ });
1801
1913
  return tempOrder.payments;
1802
1914
  }
1803
1915
 
@@ -1920,7 +2032,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1920
2032
  key: "addProductToOrder",
1921
2033
  value: function () {
1922
2034
  var _addProductToOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16(product, booking) {
1923
- var _this6 = this;
2035
+ var _this7 = this;
1924
2036
  var tempOrder, linked, productToAdd, incomingFingerprint, normalizedIncoming, hasIncomingGoodPass, shouldForceNewLine, matchedIndex, matchedProduct, existedFingerprint, shouldMerge, _targetProduct$metada, targetProduct, targetUid, normalizedProduct;
1925
2037
  return _regeneratorRuntime().wrap(function _callee16$(_context18) {
1926
2038
  while (1) switch (_context18.prev = _context18.next) {
@@ -1937,7 +2049,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1937
2049
  hasIncomingGoodPass = this.hasGoodPassDiscount(normalizedIncoming);
1938
2050
  shouldForceNewLine = !!booking;
1939
2051
  matchedIndex = hasIncomingGoodPass || shouldForceNewLine ? -1 : tempOrder.products.findIndex(function (item) {
1940
- if (_this6.hasGoodPassDiscount(item)) return false;
2052
+ if (_this7.hasGoodPassDiscount(item)) return false;
1941
2053
  if (item.product_id !== productToAdd.product_id) return false;
1942
2054
  if (item.product_variant_id !== productToAdd.product_variant_id) return false;
1943
2055
  var existedFingerprint = buildProductLineFingerprint(item.product_option_item, item.product_bundle);
@@ -2494,10 +2606,10 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2494
2606
  value: function extractSubmitErrorResponse(error) {
2495
2607
  var _error$response,
2496
2608
  _error$response2,
2497
- _this7 = this;
2609
+ _this8 = this;
2498
2610
  var candidates = [error === null || error === void 0 || (_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.data, error === null || error === void 0 ? void 0 : error.data, error === null || error === void 0 || (_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.body, error === null || error === void 0 ? void 0 : error.body];
2499
2611
  return candidates.find(function (candidate) {
2500
- return _this7.isSubmitErrorResponse(candidate);
2612
+ return _this8.isSubmitErrorResponse(candidate);
2501
2613
  }) || null;
2502
2614
  }
2503
2615
  }, {
@@ -3075,7 +3187,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3075
3187
  }, {
3076
3188
  key: "normalizeTempOrderForRuntime",
3077
3189
  value: function normalizeTempOrderForRuntime(raw, options) {
3078
- var _this8 = this;
3190
+ var _this9 = this;
3079
3191
  var nextTempOrder = _objectSpread(_objectSpread({}, this.createDefaultTempOrderInstance()), raw || {});
3080
3192
  delete nextTempOrder.summary;
3081
3193
  delete nextTempOrder.lastOrderInfo;
@@ -3093,7 +3205,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3093
3205
  nextTempOrder.metadata = raw.metadata && _typeof(raw.metadata) === 'object' ? _objectSpread({}, raw.metadata) : {};
3094
3206
  nextTempOrder.holder = raw.holder && _typeof(raw.holder) === 'object' ? _objectSpread({}, raw.holder) : null;
3095
3207
  nextTempOrder.products = Array.isArray(raw.products) ? raw.products.map(function (p) {
3096
- return _this8.normalizeHydratedOrderProduct(p);
3208
+ return _this9.normalizeHydratedOrderProduct(p);
3097
3209
  }) : [];
3098
3210
  nextTempOrder.bookings = Array.isArray(raw.bookings) ? raw.bookings.map(function (b) {
3099
3211
  return _objectSpread(_objectSpread({}, b || {}), {}, {
@@ -3187,46 +3299,46 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3187
3299
  */
3188
3300
  function populateSavedAmounts(productList, discountList) {
3189
3301
  var savedMap = new Map();
3190
- var _iterator5 = _createForOfIteratorHelper(productList),
3191
- _step5;
3302
+ var _iterator8 = _createForOfIteratorHelper(productList),
3303
+ _step8;
3192
3304
  try {
3193
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
3194
- var product = _step5.value;
3305
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
3306
+ var product = _step8.value;
3195
3307
  var qty = product.num || 1;
3196
- var _iterator7 = _createForOfIteratorHelper(product.discount_list || []),
3197
- _step7;
3308
+ var _iterator10 = _createForOfIteratorHelper(product.discount_list || []),
3309
+ _step10;
3198
3310
  try {
3199
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
3311
+ for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
3200
3312
  var _pd$discount, _pd$metadata;
3201
- var pd = _step7.value;
3313
+ var pd = _step10.value;
3202
3314
  var discountKey = ((_pd$discount = pd.discount) === null || _pd$discount === void 0 ? void 0 : _pd$discount.resource_id) || pd.id;
3203
3315
  if (discountKey == null) continue;
3204
3316
  var amount = new Decimal(pd.amount || 0).times(qty).plus(((_pd$metadata = pd.metadata) === null || _pd$metadata === void 0 ? void 0 : _pd$metadata.product_discount_difference) || 0);
3205
3317
  savedMap.set(discountKey, (savedMap.get(discountKey) || new Decimal(0)).plus(amount));
3206
3318
  }
3207
3319
  } catch (err) {
3208
- _iterator7.e(err);
3320
+ _iterator10.e(err);
3209
3321
  } finally {
3210
- _iterator7.f();
3322
+ _iterator10.f();
3211
3323
  }
3212
3324
  }
3213
3325
  } catch (err) {
3214
- _iterator5.e(err);
3326
+ _iterator8.e(err);
3215
3327
  } finally {
3216
- _iterator5.f();
3328
+ _iterator8.f();
3217
3329
  }
3218
- var _iterator6 = _createForOfIteratorHelper(discountList),
3219
- _step6;
3330
+ var _iterator9 = _createForOfIteratorHelper(discountList),
3331
+ _step9;
3220
3332
  try {
3221
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
3222
- var d = _step6.value;
3333
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
3334
+ var d = _step9.value;
3223
3335
  var key = d.id;
3224
3336
  d.savedAmount = d.isSelected && key != null && savedMap.has(key) ? savedMap.get(key).toNumber() : 0;
3225
3337
  }
3226
3338
  } catch (err) {
3227
- _iterator6.e(err);
3339
+ _iterator9.e(err);
3228
3340
  } finally {
3229
- _iterator6.f();
3341
+ _iterator9.f();
3230
3342
  }
3231
3343
  }
3232
3344
  }]);
@@ -280,6 +280,7 @@ function calculateProductsTax(products, taxRate, isPriceIncludeTax) {
280
280
  isChargeTax: (_product$is_charge_ta2 = product.is_charge_tax) !== null && _product$is_charge_ta2 !== void 0 ? _product$is_charge_ta2 : 0
281
281
  });
282
282
  var mainTaxRounded = mainTaxPrecise.toDecimalPlaces(2, Decimal.ROUND_HALF_UP);
283
+ product.main_product_attached_bundle_tax_fee = mainTaxRounded.toFixed(2);
283
284
  if (mainTaxPrecise.gt(0)) {
284
285
  lastTaxableItem = {
285
286
  type: 'main',
@@ -313,15 +314,16 @@ function calculateProductsTax(products, taxRate, isPriceIncludeTax) {
313
314
  var bundleQuantity = new Decimal(getSafeNum((_bundleItem$num2 = bundleItem.num) !== null && _bundleItem$num2 !== void 0 ? _bundleItem$num2 : bundleItem.quantity));
314
315
  var bundlePrice = toDecimal((_ref4 = (_bundleItem$bundle_se2 = bundleItem.bundle_selling_price) !== null && _bundleItem$bundle_se2 !== void 0 ? _bundleItem$bundle_se2 : bundleItem.price) !== null && _ref4 !== void 0 ? _ref4 : 0);
315
316
  var bundleOriginalPrice = toDecimal((_ref5 = (_ref6 = (_bundleItem$original_ = bundleItem.original_price) !== null && _bundleItem$original_ !== void 0 ? _bundleItem$original_ : bundleItem.product_price) !== null && _ref6 !== void 0 ? _ref6 : bundleItem.price) !== null && _ref5 !== void 0 ? _ref5 : 0);
317
+ var bundleSurchargeFee = toDecimal(bundleItem.surcharge_fee);
316
318
  var bundleTaxPrecise = calculateSingleItemTax({
317
- price: bundlePrice,
319
+ price: bundlePrice.plus(bundleSurchargeFee),
318
320
  taxRate: rate,
319
321
  isPriceIncludeTax: isPriceIncludeTax,
320
322
  isChargeTax: (_ref7 = (_bundleItem$is_charge = bundleItem.is_charge_tax) !== null && _bundleItem$is_charge !== void 0 ? _bundleItem$is_charge : product.is_charge_tax) !== null && _ref7 !== void 0 ? _ref7 : 0
321
323
  });
322
324
  var bundleTaxRounded = bundleTaxPrecise.toDecimalPlaces(2, Decimal.ROUND_HALF_UP);
323
325
  var bundleOrigTaxPrecise = calculateSingleItemTax({
324
- price: bundleOriginalPrice,
326
+ price: bundleOriginalPrice.plus(bundleSurchargeFee),
325
327
  taxRate: rate,
326
328
  isPriceIncludeTax: isPriceIncludeTax,
327
329
  isChargeTax: (_ref8 = (_bundleItem$is_charge2 = bundleItem.is_charge_tax) !== null && _bundleItem$is_charge2 !== void 0 ? _bundleItem$is_charge2 : product.is_charge_tax) !== null && _ref8 !== void 0 ? _ref8 : 0
@@ -444,8 +446,20 @@ export function calculateSalesSummary(params) {
444
446
  isEdit: false
445
447
  }) || 0);
446
448
  for (var i = 0; i < products.length; i++) {
447
- var _surchargeServiceItem;
448
- products[i].surcharge_fee = ((_surchargeServiceItem = surchargeServiceItems[i]) === null || _surchargeServiceItem === void 0 ? void 0 : _surchargeServiceItem.surcharge_fee) || 0;
449
+ var sourceItem = surchargeServiceItems[i] || {};
450
+ var product = products[i];
451
+ product.surcharge_fee = sourceItem.surcharge_fee || 0;
452
+ var relationSurchargeIds = Array.isArray(sourceItem.relation_surcharge_ids) ? sourceItem.relation_surcharge_ids : [];
453
+ var hasSurcharge = new Decimal(product.surcharge_fee || 0).gt(0) || relationSurchargeIds.length > 0;
454
+ if (hasSurcharge) {
455
+ product.main_product_attached_bundle_surcharge_fee = toFixed2(product.surcharge_fee);
456
+ }
457
+ if (relationSurchargeIds.length > 0) {
458
+ product.relation_surcharge_ids = sourceItem.relation_surcharge_ids;
459
+ }
460
+ if (hasSurcharge && sourceItem.surcharge_rounding_remainder !== undefined) {
461
+ product.surcharge_rounding_remainder = sourceItem.surcharge_rounding_remainder;
462
+ }
449
463
  }
450
464
  var hasTaxRate = taxRate !== undefined && taxRate !== null && taxRate > 0;
451
465
  var productTaxFee;
@@ -18,6 +18,7 @@ export declare class OrderModule extends BaseModule implements Module {
18
18
  private resourceIdIndex;
19
19
  private logger;
20
20
  private storage;
21
+ private orderSQLiteSaveQueue;
21
22
  constructor(name?: string, version?: string);
22
23
  initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
23
24
  /**
@@ -130,6 +131,28 @@ export declare class OrderModule extends BaseModule implements Module {
130
131
  private getStorageItem;
131
132
  private setStorageItem;
132
133
  private loadOrdersFromSQLite;
134
+ /**
135
+ * 串行执行订单 SQLite 保存任务,保证 clear + bulkAdd 组合不会被其它订单保存插入。
136
+ *
137
+ * @example
138
+ * await this.runInOrderSQLiteSaveQueue(async () => {
139
+ * await this.dbManager.clear(INDEXDB_STORE_NAME)
140
+ * await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orders)
141
+ * })
142
+ */
143
+ private runInOrderSQLiteSaveQueue;
144
+ /**
145
+ * 保存订单列表到 SQLite,内部会先清空 orders 表再批量写入当前快照。
146
+ *
147
+ * @example
148
+ * await this.saveOrdersToSQLite(this.store.list)
149
+ */
133
150
  private saveOrdersToSQLite;
151
+ /**
152
+ * 清空订单模块的内存数据和本地 SQLite 订单表。
153
+ *
154
+ * @example
155
+ * await orderModule.clear()
156
+ */
134
157
  clear(): Promise<void>;
135
158
  }
@@ -63,6 +63,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
63
63
  _defineProperty(_assertThisInitialized(_this), "logger", void 0);
64
64
  // LoggerManager 实例
65
65
  _defineProperty(_assertThisInitialized(_this), "storage", void 0);
66
+ _defineProperty(_assertThisInitialized(_this), "orderSQLiteSaveQueue", Promise.resolve());
66
67
  return _this;
67
68
  }
68
69
  _createClass(OrderModule, [{
@@ -1276,92 +1277,168 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1276
1277
  }
1277
1278
  return loadOrdersFromSQLite;
1278
1279
  }()
1280
+ /**
1281
+ * 串行执行订单 SQLite 保存任务,保证 clear + bulkAdd 组合不会被其它订单保存插入。
1282
+ *
1283
+ * @example
1284
+ * await this.runInOrderSQLiteSaveQueue(async () => {
1285
+ * await this.dbManager.clear(INDEXDB_STORE_NAME)
1286
+ * await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orders)
1287
+ * })
1288
+ */
1279
1289
  }, {
1280
- key: "saveOrdersToSQLite",
1281
- value: function () {
1282
- var _saveOrdersToSQLite = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15(orderList) {
1290
+ key: "runInOrderSQLiteSaveQueue",
1291
+ value: (function () {
1292
+ var _runInOrderSQLiteSaveQueue = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15(task) {
1293
+ var queuedTask;
1283
1294
  return _regeneratorRuntime().wrap(function _callee15$(_context15) {
1284
1295
  while (1) switch (_context15.prev = _context15.next) {
1296
+ case 0:
1297
+ queuedTask = this.orderSQLiteSaveQueue.then(task, task);
1298
+ this.orderSQLiteSaveQueue = queuedTask.then(function () {
1299
+ return undefined;
1300
+ }, function () {
1301
+ return undefined;
1302
+ });
1303
+ return _context15.abrupt("return", queuedTask);
1304
+ case 3:
1305
+ case "end":
1306
+ return _context15.stop();
1307
+ }
1308
+ }, _callee15, this);
1309
+ }));
1310
+ function runInOrderSQLiteSaveQueue(_x8) {
1311
+ return _runInOrderSQLiteSaveQueue.apply(this, arguments);
1312
+ }
1313
+ return runInOrderSQLiteSaveQueue;
1314
+ }()
1315
+ /**
1316
+ * 保存订单列表到 SQLite,内部会先清空 orders 表再批量写入当前快照。
1317
+ *
1318
+ * @example
1319
+ * await this.saveOrdersToSQLite(this.store.list)
1320
+ */
1321
+ )
1322
+ }, {
1323
+ key: "saveOrdersToSQLite",
1324
+ value: (function () {
1325
+ var _saveOrdersToSQLite = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee17(orderList) {
1326
+ var _this10 = this;
1327
+ var orderListSnapshot;
1328
+ return _regeneratorRuntime().wrap(function _callee17$(_context17) {
1329
+ while (1) switch (_context17.prev = _context17.next) {
1285
1330
  case 0:
1286
1331
  if (this.dbManager) {
1287
- _context15.next = 2;
1332
+ _context17.next = 2;
1288
1333
  break;
1289
1334
  }
1290
- return _context15.abrupt("return");
1335
+ return _context17.abrupt("return");
1291
1336
  case 2:
1292
- _context15.prev = 2;
1293
- this.logInfo('saveOrdersToSQLite-开始', {
1294
- count: orderList.length
1295
- });
1296
- _context15.next = 6;
1297
- return this.dbManager.clear(INDEXDB_STORE_NAME);
1337
+ orderListSnapshot = cloneDeep(orderList);
1338
+ _context17.prev = 3;
1339
+ _context17.next = 6;
1340
+ return this.runInOrderSQLiteSaveQueue( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {
1341
+ return _regeneratorRuntime().wrap(function _callee16$(_context16) {
1342
+ while (1) switch (_context16.prev = _context16.next) {
1343
+ case 0:
1344
+ _this10.logInfo('saveOrdersToSQLite-开始', {
1345
+ count: orderListSnapshot.length
1346
+ });
1347
+ _context16.next = 3;
1348
+ return _this10.dbManager.clear(INDEXDB_STORE_NAME);
1349
+ case 3:
1350
+ _this10.logInfo('saveOrdersToSQLite-clear完成', {
1351
+ count: orderListSnapshot.length
1352
+ });
1353
+ if (!(orderListSnapshot.length === 0)) {
1354
+ _context16.next = 6;
1355
+ break;
1356
+ }
1357
+ return _context16.abrupt("return");
1358
+ case 6:
1359
+ _context16.next = 8;
1360
+ return _this10.dbManager.bulkAdd(INDEXDB_STORE_NAME, orderListSnapshot);
1361
+ case 8:
1362
+ _this10.logInfo('saveOrdersToSQLite-bulkAdd完成', {
1363
+ count: orderListSnapshot.length
1364
+ });
1365
+ case 9:
1366
+ case "end":
1367
+ return _context16.stop();
1368
+ }
1369
+ }, _callee16);
1370
+ })));
1298
1371
  case 6:
1299
- this.logInfo('saveOrdersToSQLite-clear完成', {
1300
- count: orderList.length
1301
- });
1302
- if (!(orderList.length === 0)) {
1303
- _context15.next = 9;
1304
- break;
1305
- }
1306
- return _context15.abrupt("return");
1307
- case 9:
1308
- _context15.next = 11;
1309
- return this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orderList);
1310
- case 11:
1311
- this.logInfo('saveOrdersToSQLite-bulkAdd完成', {
1312
- count: orderList.length
1313
- });
1314
- _context15.next = 17;
1372
+ _context17.next = 11;
1315
1373
  break;
1316
- case 14:
1317
- _context15.prev = 14;
1318
- _context15.t0 = _context15["catch"](2);
1374
+ case 8:
1375
+ _context17.prev = 8;
1376
+ _context17.t0 = _context17["catch"](3);
1319
1377
  // SQLite 异常,避免影响主流程
1320
1378
  this.logError('保存订单到 SQLite 失败', {
1321
- error: _context15.t0 instanceof Error ? _context15.t0.message : String(_context15.t0),
1322
- orderList: orderList.length
1379
+ error: _context17.t0 instanceof Error ? _context17.t0.message : String(_context17.t0),
1380
+ orderList: orderListSnapshot.length
1323
1381
  });
1324
- case 17:
1382
+ case 11:
1325
1383
  case "end":
1326
- return _context15.stop();
1384
+ return _context17.stop();
1327
1385
  }
1328
- }, _callee15, this, [[2, 14]]);
1386
+ }, _callee17, this, [[3, 8]]);
1329
1387
  }));
1330
- function saveOrdersToSQLite(_x8) {
1388
+ function saveOrdersToSQLite(_x9) {
1331
1389
  return _saveOrdersToSQLite.apply(this, arguments);
1332
1390
  }
1333
1391
  return saveOrdersToSQLite;
1334
1392
  }()
1393
+ /**
1394
+ * 清空订单模块的内存数据和本地 SQLite 订单表。
1395
+ *
1396
+ * @example
1397
+ * await orderModule.clear()
1398
+ */
1399
+ )
1335
1400
  }, {
1336
1401
  key: "clear",
1337
- value: function () {
1338
- var _clear = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {
1339
- return _regeneratorRuntime().wrap(function _callee16$(_context16) {
1340
- while (1) switch (_context16.prev = _context16.next) {
1402
+ value: (function () {
1403
+ var _clear = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {
1404
+ var _this11 = this;
1405
+ return _regeneratorRuntime().wrap(function _callee19$(_context19) {
1406
+ while (1) switch (_context19.prev = _context19.next) {
1341
1407
  case 0:
1342
1408
  this.store.list = [];
1343
1409
  this.store.map = new Map();
1344
1410
  this.resourceIdIndex.clear();
1345
1411
  if (!this.dbManager) {
1346
- _context16.next = 6;
1412
+ _context19.next = 6;
1347
1413
  break;
1348
1414
  }
1349
- _context16.next = 6;
1350
- return this.dbManager.clear(INDEXDB_STORE_NAME);
1415
+ _context19.next = 6;
1416
+ return this.runInOrderSQLiteSaveQueue( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {
1417
+ return _regeneratorRuntime().wrap(function _callee18$(_context18) {
1418
+ while (1) switch (_context18.prev = _context18.next) {
1419
+ case 0:
1420
+ _context18.next = 2;
1421
+ return _this11.dbManager.clear(INDEXDB_STORE_NAME);
1422
+ case 2:
1423
+ case "end":
1424
+ return _context18.stop();
1425
+ }
1426
+ }, _callee18);
1427
+ })));
1351
1428
  case 6:
1352
1429
  this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, '');
1353
1430
  this.core.effects.emit(OrderHooks.onOrdersChanged, this.store.list);
1354
1431
  case 8:
1355
1432
  case "end":
1356
- return _context16.stop();
1433
+ return _context19.stop();
1357
1434
  }
1358
- }, _callee16, this);
1435
+ }, _callee19, this);
1359
1436
  }));
1360
1437
  function clear() {
1361
1438
  return _clear.apply(this, arguments);
1362
1439
  }
1363
1440
  return clear;
1364
- }()
1441
+ }())
1365
1442
  }]);
1366
1443
  return OrderModule;
1367
1444
  }(BaseModule);
@@ -0,0 +1,49 @@
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
+ });
@@ -127,6 +127,9 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
127
127
  private calculatePaymentTotal;
128
128
  private calculatePaidPaymentSummary;
129
129
  private calculatePaymentServiceFee;
130
+ private formatSummaryMetadataMoney;
131
+ private syncSummaryProductMetadata;
132
+ private calculateSummaryPaymentBalance;
130
133
  private getPaymentTargetAmount;
131
134
  ensureTempOrder(): OrderTempOrder;
132
135
  restoreOrder(): OrderTempOrder;
@@ -696,6 +696,69 @@ var OrderModule = class extends import_BaseModule.BaseModule {
696
696
  const fixedAmount = new import_decimal.default(serviceCharge.amount || 0);
697
697
  return new import_decimal.default(payment.amount || 0).times(percentage).plus(fixedAmount);
698
698
  }
699
+ formatSummaryMetadataMoney(value) {
700
+ if (value === void 0 || value === null || value === "")
701
+ return void 0;
702
+ if (value instanceof import_decimal.default)
703
+ return value.toFixed(2);
704
+ return new import_decimal.default(String(value || 0)).toFixed(2);
705
+ }
706
+ syncSummaryProductMetadata(products) {
707
+ const moneyKeys = [
708
+ "main_product_attached_bundle_surcharge_fee",
709
+ "main_product_attached_bundle_tax_fee",
710
+ "surcharge_rounding_remainder",
711
+ "tax_fee_rounding_remainder"
712
+ ];
713
+ for (const product of products || []) {
714
+ const productRecord = product;
715
+ const metadata = productRecord.metadata && typeof productRecord.metadata === "object" ? { ...productRecord.metadata } : {};
716
+ let hasMetadataPatch = false;
717
+ for (const key of moneyKeys) {
718
+ const value = this.formatSummaryMetadataMoney(productRecord[key]);
719
+ if (value === void 0)
720
+ continue;
721
+ metadata[key] = value;
722
+ hasMetadataPatch = true;
723
+ }
724
+ if (Array.isArray(productRecord.relation_surcharge_ids)) {
725
+ metadata.relation_surcharge_ids = productRecord.relation_surcharge_ids;
726
+ hasMetadataPatch = true;
727
+ }
728
+ if (hasMetadataPatch)
729
+ productRecord.metadata = metadata;
730
+ if (!Array.isArray(productRecord.product_bundle))
731
+ continue;
732
+ for (const bundle of productRecord.product_bundle) {
733
+ const bundleRecord = bundle;
734
+ const bundleMetadata = bundleRecord.metadata && typeof bundleRecord.metadata === "object" ? { ...bundleRecord.metadata } : {};
735
+ let hasBundleMetadataPatch = false;
736
+ const bundleSurchargeFee = this.formatSummaryMetadataMoney(
737
+ bundleRecord.surcharge_fee
738
+ );
739
+ if (bundleSurchargeFee !== void 0) {
740
+ bundleMetadata.surcharge_fee = bundleSurchargeFee;
741
+ hasBundleMetadataPatch = true;
742
+ }
743
+ if (Array.isArray(bundleRecord.relation_surcharge_ids)) {
744
+ bundleMetadata.relation_surcharge_ids = bundleRecord.relation_surcharge_ids;
745
+ hasBundleMetadataPatch = true;
746
+ }
747
+ if (hasBundleMetadataPatch)
748
+ bundleRecord.metadata = bundleMetadata;
749
+ }
750
+ }
751
+ }
752
+ calculateSummaryPaymentBalance(params) {
753
+ const { tempOrder, summary, orderPaidAmount } = params;
754
+ const depositAmount = summary.deposit_amount || tempOrder.deposit_amount || "0.00";
755
+ const isDeposit = tempOrder.is_deposit === 1 || new import_decimal.default(depositAmount || 0).gt(0);
756
+ const targetAmount = isDeposit ? new import_decimal.default(depositAmount || 0) : new import_decimal.default(summary.total_amount || summary.expect_amount || 0);
757
+ return {
758
+ amountGap: import_decimal.default.max(0, targetAmount.minus(orderPaidAmount)).toFixed(2),
759
+ totalRefundAmount: import_decimal.default.max(0, orderPaidAmount.minus(targetAmount)).toFixed(2)
760
+ };
761
+ }
699
762
  getPaymentTargetAmount() {
700
763
  const tempOrder = this.ensureTempOrder();
701
764
  const summary = this.store.summary || (0, import_utils.createEmptySummary)();
@@ -941,16 +1004,21 @@ var OrderModule = class extends import_BaseModule.BaseModule {
941
1004
  if (!tempOrder)
942
1005
  return null;
943
1006
  const salesSummary = this.getSalesSummary();
944
- const existedSummary = this.store.summary || (0, import_utils.createEmptySummary)();
945
1007
  const paidPaymentSummary = this.calculatePaidPaymentSummary(
946
1008
  tempOrder.payments || []
947
1009
  );
948
1010
  if (!salesSummary) {
1011
+ const paymentBalance2 = this.calculateSummaryPaymentBalance({
1012
+ tempOrder,
1013
+ summary: (0, import_utils.createEmptySummary)(),
1014
+ orderPaidAmount: paidPaymentSummary.orderPaidAmount
1015
+ });
949
1016
  const emptySummary = {
950
1017
  ...(0, import_utils.createEmptySummary)(),
951
- total_refund_amount: existedSummary.total_refund_amount || "0.00",
1018
+ total_refund_amount: paymentBalance2.totalRefundAmount,
952
1019
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
953
1020
  order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
1021
+ amount_gap: paymentBalance2.amountGap,
954
1022
  pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
955
1023
  };
956
1024
  this.store.summary = emptySummary;
@@ -962,11 +1030,18 @@ var OrderModule = class extends import_BaseModule.BaseModule {
962
1030
  isPriceIncludeTax: tempOrder.is_price_include_tax,
963
1031
  shopDiscount: tempOrder.shop_discount
964
1032
  });
1033
+ this.syncSummaryProductMetadata(tempOrder.products || []);
1034
+ const paymentBalance = this.calculateSummaryPaymentBalance({
1035
+ tempOrder,
1036
+ summary: salesSummaryResult,
1037
+ orderPaidAmount: paidPaymentSummary.orderPaidAmount
1038
+ });
965
1039
  const summary = {
966
1040
  ...salesSummaryResult,
967
- total_refund_amount: existedSummary.total_refund_amount || "0.00",
1041
+ total_refund_amount: paymentBalance.totalRefundAmount,
968
1042
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
969
1043
  order_paid_amount: paidPaymentSummary.orderPaidAmount.toFixed(2),
1044
+ amount_gap: paymentBalance.amountGap,
970
1045
  pay_service_charge_amount: paidPaymentSummary.payServiceChargeAmount.toFixed(2)
971
1046
  };
972
1047
  this.store.summary = summary;
@@ -1189,9 +1264,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1189
1264
  payment
1190
1265
  });
1191
1266
  const tempOrder = this.ensureTempOrder();
1192
- const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([payment]);
1267
+ const paymentRecord = payment;
1268
+ const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([{
1269
+ ...paymentRecord,
1270
+ status: paymentRecord.status ?? "paid",
1271
+ origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
1272
+ }]);
1193
1273
  tempOrder.payments = [...tempOrder.payments || [], ...mapped];
1194
1274
  this.persistTempOrder();
1275
+ void this.recalculateSummary({ createIfMissing: true }).catch((error) => {
1276
+ this.logError("recalculate summary after addOrderPayment failed", {
1277
+ error: error instanceof Error ? error.message : String(error)
1278
+ });
1279
+ });
1195
1280
  return tempOrder.payments;
1196
1281
  }
1197
1282
  /**
@@ -236,6 +236,7 @@ function calculateProductsTax(products, taxRate, isPriceIncludeTax) {
236
236
  isChargeTax: product.is_charge_tax ?? 0
237
237
  });
238
238
  const mainTaxRounded = mainTaxPrecise.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
239
+ product.main_product_attached_bundle_tax_fee = mainTaxRounded.toFixed(2);
239
240
  if (mainTaxPrecise.gt(0)) {
240
241
  lastTaxableItem = { type: "main", item: product };
241
242
  }
@@ -258,15 +259,16 @@ function calculateProductsTax(products, taxRate, isPriceIncludeTax) {
258
259
  const bundleQuantity = new import_decimal.default(getSafeNum(bundleItem.num ?? bundleItem.quantity));
259
260
  const bundlePrice = toDecimal(bundleItem.bundle_selling_price ?? bundleItem.price ?? 0);
260
261
  const bundleOriginalPrice = toDecimal(bundleItem.original_price ?? bundleItem.product_price ?? bundleItem.price ?? 0);
262
+ const bundleSurchargeFee = toDecimal(bundleItem.surcharge_fee);
261
263
  const bundleTaxPrecise = calculateSingleItemTax({
262
- price: bundlePrice,
264
+ price: bundlePrice.plus(bundleSurchargeFee),
263
265
  taxRate: rate,
264
266
  isPriceIncludeTax,
265
267
  isChargeTax: bundleItem.is_charge_tax ?? product.is_charge_tax ?? 0
266
268
  });
267
269
  const bundleTaxRounded = bundleTaxPrecise.toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP);
268
270
  const bundleOrigTaxPrecise = calculateSingleItemTax({
269
- price: bundleOriginalPrice,
271
+ price: bundleOriginalPrice.plus(bundleSurchargeFee),
270
272
  taxRate: rate,
271
273
  isPriceIncludeTax,
272
274
  isChargeTax: bundleItem.is_charge_tax ?? product.is_charge_tax ?? 0
@@ -332,7 +334,6 @@ function createEmptySalesSummary() {
332
334
  };
333
335
  }
334
336
  function calculateSalesSummary(params) {
335
- var _a;
336
337
  const {
337
338
  products,
338
339
  isPriceIncludeTax,
@@ -379,7 +380,20 @@ function calculateSalesSummary(params) {
379
380
  ) || 0
380
381
  );
381
382
  for (let i = 0; i < products.length; i++) {
382
- products[i].surcharge_fee = ((_a = surchargeServiceItems[i]) == null ? void 0 : _a.surcharge_fee) || 0;
383
+ const sourceItem = surchargeServiceItems[i] || {};
384
+ const product = products[i];
385
+ product.surcharge_fee = sourceItem.surcharge_fee || 0;
386
+ const relationSurchargeIds = Array.isArray(sourceItem.relation_surcharge_ids) ? sourceItem.relation_surcharge_ids : [];
387
+ const hasSurcharge = new import_decimal.default(product.surcharge_fee || 0).gt(0) || relationSurchargeIds.length > 0;
388
+ if (hasSurcharge) {
389
+ product.main_product_attached_bundle_surcharge_fee = toFixed2(product.surcharge_fee);
390
+ }
391
+ if (relationSurchargeIds.length > 0) {
392
+ product.relation_surcharge_ids = sourceItem.relation_surcharge_ids;
393
+ }
394
+ if (hasSurcharge && sourceItem.surcharge_rounding_remainder !== void 0) {
395
+ product.surcharge_rounding_remainder = sourceItem.surcharge_rounding_remainder;
396
+ }
383
397
  }
384
398
  const hasTaxRate = taxRate !== void 0 && taxRate !== null && taxRate > 0;
385
399
  let productTaxFee;
@@ -18,6 +18,7 @@ export declare class OrderModule extends BaseModule implements Module {
18
18
  private resourceIdIndex;
19
19
  private logger;
20
20
  private storage;
21
+ private orderSQLiteSaveQueue;
21
22
  constructor(name?: string, version?: string);
22
23
  initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
23
24
  /**
@@ -130,6 +131,28 @@ export declare class OrderModule extends BaseModule implements Module {
130
131
  private getStorageItem;
131
132
  private setStorageItem;
132
133
  private loadOrdersFromSQLite;
134
+ /**
135
+ * 串行执行订单 SQLite 保存任务,保证 clear + bulkAdd 组合不会被其它订单保存插入。
136
+ *
137
+ * @example
138
+ * await this.runInOrderSQLiteSaveQueue(async () => {
139
+ * await this.dbManager.clear(INDEXDB_STORE_NAME)
140
+ * await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orders)
141
+ * })
142
+ */
143
+ private runInOrderSQLiteSaveQueue;
144
+ /**
145
+ * 保存订单列表到 SQLite,内部会先清空 orders 表再批量写入当前快照。
146
+ *
147
+ * @example
148
+ * await this.saveOrdersToSQLite(this.store.list)
149
+ */
133
150
  private saveOrdersToSQLite;
151
+ /**
152
+ * 清空订单模块的内存数据和本地 SQLite 订单表。
153
+ *
154
+ * @example
155
+ * await orderModule.clear()
156
+ */
134
157
  clear(): Promise<void>;
135
158
  }
@@ -50,6 +50,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
50
50
  this.isIdlePhase = true;
51
51
  // Map<resource_id, OrderId[]> 资源到订单的倒排索引
52
52
  this.resourceIdIndex = /* @__PURE__ */ new Map();
53
+ this.orderSQLiteSaveQueue = Promise.resolve();
53
54
  }
54
55
  async initialize(core, options) {
55
56
  var _a, _b;
@@ -743,36 +744,67 @@ var OrderModule = class extends import_BaseModule.BaseModule {
743
744
  return [];
744
745
  }
745
746
  }
747
+ /**
748
+ * 串行执行订单 SQLite 保存任务,保证 clear + bulkAdd 组合不会被其它订单保存插入。
749
+ *
750
+ * @example
751
+ * await this.runInOrderSQLiteSaveQueue(async () => {
752
+ * await this.dbManager.clear(INDEXDB_STORE_NAME)
753
+ * await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orders)
754
+ * })
755
+ */
756
+ async runInOrderSQLiteSaveQueue(task) {
757
+ const queuedTask = this.orderSQLiteSaveQueue.then(task, task);
758
+ this.orderSQLiteSaveQueue = queuedTask.then(() => void 0, () => void 0);
759
+ return queuedTask;
760
+ }
761
+ /**
762
+ * 保存订单列表到 SQLite,内部会先清空 orders 表再批量写入当前快照。
763
+ *
764
+ * @example
765
+ * await this.saveOrdersToSQLite(this.store.list)
766
+ */
746
767
  async saveOrdersToSQLite(orderList) {
747
768
  if (!this.dbManager)
748
769
  return;
770
+ const orderListSnapshot = (0, import_lodash_es.cloneDeep)(orderList);
749
771
  try {
750
- this.logInfo("saveOrdersToSQLite-开始", {
751
- count: orderList.length
752
- });
753
- await this.dbManager.clear(INDEXDB_STORE_NAME);
754
- this.logInfo("saveOrdersToSQLite-clear完成", {
755
- count: orderList.length
756
- });
757
- if (orderList.length === 0)
758
- return;
759
- await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orderList);
760
- this.logInfo("saveOrdersToSQLite-bulkAdd完成", {
761
- count: orderList.length
772
+ await this.runInOrderSQLiteSaveQueue(async () => {
773
+ this.logInfo("saveOrdersToSQLite-开始", {
774
+ count: orderListSnapshot.length
775
+ });
776
+ await this.dbManager.clear(INDEXDB_STORE_NAME);
777
+ this.logInfo("saveOrdersToSQLite-clear完成", {
778
+ count: orderListSnapshot.length
779
+ });
780
+ if (orderListSnapshot.length === 0)
781
+ return;
782
+ await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, orderListSnapshot);
783
+ this.logInfo("saveOrdersToSQLite-bulkAdd完成", {
784
+ count: orderListSnapshot.length
785
+ });
762
786
  });
763
787
  } catch (error) {
764
788
  this.logError("保存订单到 SQLite 失败", {
765
789
  error: error instanceof Error ? error.message : String(error),
766
- orderList: orderList.length
790
+ orderList: orderListSnapshot.length
767
791
  });
768
792
  }
769
793
  }
794
+ /**
795
+ * 清空订单模块的内存数据和本地 SQLite 订单表。
796
+ *
797
+ * @example
798
+ * await orderModule.clear()
799
+ */
770
800
  async clear() {
771
801
  this.store.list = [];
772
802
  this.store.map = /* @__PURE__ */ new Map();
773
803
  this.resourceIdIndex.clear();
774
804
  if (this.dbManager) {
775
- await this.dbManager.clear(INDEXDB_STORE_NAME);
805
+ await this.runInOrderSQLiteSaveQueue(async () => {
806
+ await this.dbManager.clear(INDEXDB_STORE_NAME);
807
+ });
776
808
  }
777
809
  this.setStorageItem(ORDER_LAST_FULL_FETCH_AT_STORAGE_KEY, "");
778
810
  this.core.effects.emit(import_types.OrderHooks.onOrdersChanged, this.store.list);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.176",
4
+ "version": "2.2.178",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",