@pisell/pisellos 2.2.176 → 2.2.177

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,8 @@ 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;
130
132
  private getPaymentTargetAmount;
131
133
  ensureTempOrder(): OrderTempOrder;
132
134
  restoreOrder(): OrderTempOrder;
@@ -1134,6 +1134,52 @@ 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
+ }
1177
+ } catch (err) {
1178
+ _iterator5.e(err);
1179
+ } finally {
1180
+ _iterator5.f();
1181
+ }
1182
+ }
1137
1183
  }, {
1138
1184
  key: "getPaymentTargetAmount",
1139
1185
  value: function getPaymentTargetAmount() {
@@ -1486,6 +1532,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1486
1532
  });
1487
1533
  case 13:
1488
1534
  salesSummaryResult = _context14.sent;
1535
+ this.syncSummaryProductMetadata(tempOrder.products || []);
1489
1536
  summary = _objectSpread(_objectSpread({}, salesSummaryResult), {}, {
1490
1537
  total_refund_amount: existedSummary.total_refund_amount || '0.00',
1491
1538
  customer_paid_amount: paidPaymentSummary.customerPaidAmount.toFixed(2),
@@ -1504,7 +1551,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1504
1551
  tempOrder.deposit_amount = summary.deposit_amount || '0.00';
1505
1552
  tempOrder.is_deposit = summary.deposit_amount !== '0.00' ? 1 : 0;
1506
1553
  return _context14.abrupt("return", this.store.summary);
1507
- case 23:
1554
+ case 24:
1508
1555
  case "end":
1509
1556
  return _context14.stop();
1510
1557
  }
@@ -1791,13 +1838,28 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1791
1838
  }, {
1792
1839
  key: "addOrderPayment",
1793
1840
  value: function addOrderPayment(payment) {
1841
+ var _paymentRecord$status,
1842
+ _ref21,
1843
+ _paymentRecord$origin,
1844
+ _this6 = this;
1794
1845
  this.logInfo('addOrderPayment', {
1795
1846
  payment: payment
1796
1847
  });
1797
1848
  var tempOrder = this.ensureTempOrder();
1798
- var mapped = mapPaymentItemsToOrderPayments([payment]);
1849
+ var paymentRecord = payment;
1850
+ var mapped = mapPaymentItemsToOrderPayments([_objectSpread(_objectSpread({}, paymentRecord), {}, {
1851
+ status: (_paymentRecord$status = paymentRecord.status) !== null && _paymentRecord$status !== void 0 ? _paymentRecord$status : 'paid',
1852
+ origin_amount: (_ref21 = (_paymentRecord$origin = paymentRecord.origin_amount) !== null && _paymentRecord$origin !== void 0 ? _paymentRecord$origin : paymentRecord.amount) !== null && _ref21 !== void 0 ? _ref21 : '0.00'
1853
+ })]);
1799
1854
  tempOrder.payments = [].concat(_toConsumableArray(tempOrder.payments || []), _toConsumableArray(mapped));
1800
1855
  this.persistTempOrder();
1856
+ void this.recalculateSummary({
1857
+ createIfMissing: true
1858
+ }).catch(function (error) {
1859
+ _this6.logError('recalculate summary after addOrderPayment failed', {
1860
+ error: error instanceof Error ? error.message : String(error)
1861
+ });
1862
+ });
1801
1863
  return tempOrder.payments;
1802
1864
  }
1803
1865
 
@@ -1920,7 +1982,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1920
1982
  key: "addProductToOrder",
1921
1983
  value: function () {
1922
1984
  var _addProductToOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16(product, booking) {
1923
- var _this6 = this;
1985
+ var _this7 = this;
1924
1986
  var tempOrder, linked, productToAdd, incomingFingerprint, normalizedIncoming, hasIncomingGoodPass, shouldForceNewLine, matchedIndex, matchedProduct, existedFingerprint, shouldMerge, _targetProduct$metada, targetProduct, targetUid, normalizedProduct;
1925
1987
  return _regeneratorRuntime().wrap(function _callee16$(_context18) {
1926
1988
  while (1) switch (_context18.prev = _context18.next) {
@@ -1937,7 +1999,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1937
1999
  hasIncomingGoodPass = this.hasGoodPassDiscount(normalizedIncoming);
1938
2000
  shouldForceNewLine = !!booking;
1939
2001
  matchedIndex = hasIncomingGoodPass || shouldForceNewLine ? -1 : tempOrder.products.findIndex(function (item) {
1940
- if (_this6.hasGoodPassDiscount(item)) return false;
2002
+ if (_this7.hasGoodPassDiscount(item)) return false;
1941
2003
  if (item.product_id !== productToAdd.product_id) return false;
1942
2004
  if (item.product_variant_id !== productToAdd.product_variant_id) return false;
1943
2005
  var existedFingerprint = buildProductLineFingerprint(item.product_option_item, item.product_bundle);
@@ -2494,10 +2556,10 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
2494
2556
  value: function extractSubmitErrorResponse(error) {
2495
2557
  var _error$response,
2496
2558
  _error$response2,
2497
- _this7 = this;
2559
+ _this8 = this;
2498
2560
  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
2561
  return candidates.find(function (candidate) {
2500
- return _this7.isSubmitErrorResponse(candidate);
2562
+ return _this8.isSubmitErrorResponse(candidate);
2501
2563
  }) || null;
2502
2564
  }
2503
2565
  }, {
@@ -3075,7 +3137,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3075
3137
  }, {
3076
3138
  key: "normalizeTempOrderForRuntime",
3077
3139
  value: function normalizeTempOrderForRuntime(raw, options) {
3078
- var _this8 = this;
3140
+ var _this9 = this;
3079
3141
  var nextTempOrder = _objectSpread(_objectSpread({}, this.createDefaultTempOrderInstance()), raw || {});
3080
3142
  delete nextTempOrder.summary;
3081
3143
  delete nextTempOrder.lastOrderInfo;
@@ -3093,7 +3155,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3093
3155
  nextTempOrder.metadata = raw.metadata && _typeof(raw.metadata) === 'object' ? _objectSpread({}, raw.metadata) : {};
3094
3156
  nextTempOrder.holder = raw.holder && _typeof(raw.holder) === 'object' ? _objectSpread({}, raw.holder) : null;
3095
3157
  nextTempOrder.products = Array.isArray(raw.products) ? raw.products.map(function (p) {
3096
- return _this8.normalizeHydratedOrderProduct(p);
3158
+ return _this9.normalizeHydratedOrderProduct(p);
3097
3159
  }) : [];
3098
3160
  nextTempOrder.bookings = Array.isArray(raw.bookings) ? raw.bookings.map(function (b) {
3099
3161
  return _objectSpread(_objectSpread({}, b || {}), {}, {
@@ -3187,46 +3249,46 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3187
3249
  */
3188
3250
  function populateSavedAmounts(productList, discountList) {
3189
3251
  var savedMap = new Map();
3190
- var _iterator5 = _createForOfIteratorHelper(productList),
3191
- _step5;
3252
+ var _iterator7 = _createForOfIteratorHelper(productList),
3253
+ _step7;
3192
3254
  try {
3193
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
3194
- var product = _step5.value;
3255
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
3256
+ var product = _step7.value;
3195
3257
  var qty = product.num || 1;
3196
- var _iterator7 = _createForOfIteratorHelper(product.discount_list || []),
3197
- _step7;
3258
+ var _iterator9 = _createForOfIteratorHelper(product.discount_list || []),
3259
+ _step9;
3198
3260
  try {
3199
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
3261
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
3200
3262
  var _pd$discount, _pd$metadata;
3201
- var pd = _step7.value;
3263
+ var pd = _step9.value;
3202
3264
  var discountKey = ((_pd$discount = pd.discount) === null || _pd$discount === void 0 ? void 0 : _pd$discount.resource_id) || pd.id;
3203
3265
  if (discountKey == null) continue;
3204
3266
  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
3267
  savedMap.set(discountKey, (savedMap.get(discountKey) || new Decimal(0)).plus(amount));
3206
3268
  }
3207
3269
  } catch (err) {
3208
- _iterator7.e(err);
3270
+ _iterator9.e(err);
3209
3271
  } finally {
3210
- _iterator7.f();
3272
+ _iterator9.f();
3211
3273
  }
3212
3274
  }
3213
3275
  } catch (err) {
3214
- _iterator5.e(err);
3276
+ _iterator7.e(err);
3215
3277
  } finally {
3216
- _iterator5.f();
3278
+ _iterator7.f();
3217
3279
  }
3218
- var _iterator6 = _createForOfIteratorHelper(discountList),
3219
- _step6;
3280
+ var _iterator8 = _createForOfIteratorHelper(discountList),
3281
+ _step8;
3220
3282
  try {
3221
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
3222
- var d = _step6.value;
3283
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
3284
+ var d = _step8.value;
3223
3285
  var key = d.id;
3224
3286
  d.savedAmount = d.isSelected && key != null && savedMap.has(key) ? savedMap.get(key).toNumber() : 0;
3225
3287
  }
3226
3288
  } catch (err) {
3227
- _iterator6.e(err);
3289
+ _iterator8.e(err);
3228
3290
  } finally {
3229
- _iterator6.f();
3291
+ _iterator8.f();
3230
3292
  }
3231
3293
  }
3232
3294
  }]);
@@ -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',
@@ -444,8 +445,20 @@ export function calculateSalesSummary(params) {
444
445
  isEdit: false
445
446
  }) || 0);
446
447
  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;
448
+ var sourceItem = surchargeServiceItems[i] || {};
449
+ var product = products[i];
450
+ product.surcharge_fee = sourceItem.surcharge_fee || 0;
451
+ var relationSurchargeIds = Array.isArray(sourceItem.relation_surcharge_ids) ? sourceItem.relation_surcharge_ids : [];
452
+ var hasSurcharge = new Decimal(product.surcharge_fee || 0).gt(0) || relationSurchargeIds.length > 0;
453
+ if (hasSurcharge) {
454
+ product.main_product_attached_bundle_surcharge_fee = toFixed2(product.surcharge_fee);
455
+ }
456
+ if (relationSurchargeIds.length > 0) {
457
+ product.relation_surcharge_ids = sourceItem.relation_surcharge_ids;
458
+ }
459
+ if (hasSurcharge && sourceItem.surcharge_rounding_remainder !== undefined) {
460
+ product.surcharge_rounding_remainder = sourceItem.surcharge_rounding_remainder;
461
+ }
449
462
  }
450
463
  var hasTaxRate = taxRate !== undefined && taxRate !== null && taxRate > 0;
451
464
  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);
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 6 | 3 | 5 | 4;
314
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -127,6 +127,8 @@ 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;
130
132
  private getPaymentTargetAmount;
131
133
  ensureTempOrder(): OrderTempOrder;
132
134
  restoreOrder(): OrderTempOrder;
@@ -696,6 +696,39 @@ 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
+ }
731
+ }
699
732
  getPaymentTargetAmount() {
700
733
  const tempOrder = this.ensureTempOrder();
701
734
  const summary = this.store.summary || (0, import_utils.createEmptySummary)();
@@ -962,6 +995,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
962
995
  isPriceIncludeTax: tempOrder.is_price_include_tax,
963
996
  shopDiscount: tempOrder.shop_discount
964
997
  });
998
+ this.syncSummaryProductMetadata(tempOrder.products || []);
965
999
  const summary = {
966
1000
  ...salesSummaryResult,
967
1001
  total_refund_amount: existedSummary.total_refund_amount || "0.00",
@@ -1189,9 +1223,19 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1189
1223
  payment
1190
1224
  });
1191
1225
  const tempOrder = this.ensureTempOrder();
1192
- const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([payment]);
1226
+ const paymentRecord = payment;
1227
+ const mapped = (0, import_utils.mapPaymentItemsToOrderPayments)([{
1228
+ ...paymentRecord,
1229
+ status: paymentRecord.status ?? "paid",
1230
+ origin_amount: paymentRecord.origin_amount ?? paymentRecord.amount ?? "0.00"
1231
+ }]);
1193
1232
  tempOrder.payments = [...tempOrder.payments || [], ...mapped];
1194
1233
  this.persistTempOrder();
1234
+ void this.recalculateSummary({ createIfMissing: true }).catch((error) => {
1235
+ this.logError("recalculate summary after addOrderPayment failed", {
1236
+ error: error instanceof Error ? error.message : String(error)
1237
+ });
1238
+ });
1195
1239
  return tempOrder.payments;
1196
1240
  }
1197
1241
  /**
@@ -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
  }
@@ -332,7 +333,6 @@ function createEmptySalesSummary() {
332
333
  };
333
334
  }
334
335
  function calculateSalesSummary(params) {
335
- var _a;
336
336
  const {
337
337
  products,
338
338
  isPriceIncludeTax,
@@ -379,7 +379,20 @@ function calculateSalesSummary(params) {
379
379
  ) || 0
380
380
  );
381
381
  for (let i = 0; i < products.length; i++) {
382
- products[i].surcharge_fee = ((_a = surchargeServiceItems[i]) == null ? void 0 : _a.surcharge_fee) || 0;
382
+ const sourceItem = surchargeServiceItems[i] || {};
383
+ const product = products[i];
384
+ product.surcharge_fee = sourceItem.surcharge_fee || 0;
385
+ const relationSurchargeIds = Array.isArray(sourceItem.relation_surcharge_ids) ? sourceItem.relation_surcharge_ids : [];
386
+ const hasSurcharge = new import_decimal.default(product.surcharge_fee || 0).gt(0) || relationSurchargeIds.length > 0;
387
+ if (hasSurcharge) {
388
+ product.main_product_attached_bundle_surcharge_fee = toFixed2(product.surcharge_fee);
389
+ }
390
+ if (relationSurchargeIds.length > 0) {
391
+ product.relation_surcharge_ids = sourceItem.relation_surcharge_ids;
392
+ }
393
+ if (hasSurcharge && sourceItem.surcharge_rounding_remainder !== void 0) {
394
+ product.surcharge_rounding_remainder = sourceItem.surcharge_rounding_remainder;
395
+ }
383
396
  }
384
397
  const hasTaxRate = taxRate !== void 0 && taxRate !== null && taxRate > 0;
385
398
  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);
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 1 | 2 | 6 | 3 | 5 | 4;
314
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
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.177",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",