@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.
- package/dist/modules/Order/index.d.ts +2 -0
- package/dist/modules/Order/index.js +88 -26
- package/dist/modules/SalesSummary/utils.js +15 -2
- package/dist/server/modules/order/index.d.ts +23 -0
- package/dist/server/modules/order/index.js +123 -46
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/lib/modules/Order/index.d.ts +2 -0
- package/lib/modules/Order/index.js +45 -1
- package/lib/modules/SalesSummary/utils.js +15 -2
- package/lib/server/modules/order/index.d.ts +23 -0
- package/lib/server/modules/order/index.js +46 -14
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
3191
|
-
|
|
3252
|
+
var _iterator7 = _createForOfIteratorHelper(productList),
|
|
3253
|
+
_step7;
|
|
3192
3254
|
try {
|
|
3193
|
-
for (
|
|
3194
|
-
var product =
|
|
3255
|
+
for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
|
|
3256
|
+
var product = _step7.value;
|
|
3195
3257
|
var qty = product.num || 1;
|
|
3196
|
-
var
|
|
3197
|
-
|
|
3258
|
+
var _iterator9 = _createForOfIteratorHelper(product.discount_list || []),
|
|
3259
|
+
_step9;
|
|
3198
3260
|
try {
|
|
3199
|
-
for (
|
|
3261
|
+
for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
|
|
3200
3262
|
var _pd$discount, _pd$metadata;
|
|
3201
|
-
var pd =
|
|
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
|
-
|
|
3270
|
+
_iterator9.e(err);
|
|
3209
3271
|
} finally {
|
|
3210
|
-
|
|
3272
|
+
_iterator9.f();
|
|
3211
3273
|
}
|
|
3212
3274
|
}
|
|
3213
3275
|
} catch (err) {
|
|
3214
|
-
|
|
3276
|
+
_iterator7.e(err);
|
|
3215
3277
|
} finally {
|
|
3216
|
-
|
|
3278
|
+
_iterator7.f();
|
|
3217
3279
|
}
|
|
3218
|
-
var
|
|
3219
|
-
|
|
3280
|
+
var _iterator8 = _createForOfIteratorHelper(discountList),
|
|
3281
|
+
_step8;
|
|
3220
3282
|
try {
|
|
3221
|
-
for (
|
|
3222
|
-
var d =
|
|
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
|
-
|
|
3289
|
+
_iterator8.e(err);
|
|
3228
3290
|
} finally {
|
|
3229
|
-
|
|
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
|
|
448
|
-
|
|
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: "
|
|
1281
|
-
value: function () {
|
|
1282
|
-
var
|
|
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
|
-
|
|
1332
|
+
_context17.next = 2;
|
|
1288
1333
|
break;
|
|
1289
1334
|
}
|
|
1290
|
-
return
|
|
1335
|
+
return _context17.abrupt("return");
|
|
1291
1336
|
case 2:
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
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
|
-
|
|
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
|
|
1317
|
-
|
|
1318
|
-
|
|
1374
|
+
case 8:
|
|
1375
|
+
_context17.prev = 8;
|
|
1376
|
+
_context17.t0 = _context17["catch"](3);
|
|
1319
1377
|
// SQLite 异常,避免影响主流程
|
|
1320
1378
|
this.logError('保存订单到 SQLite 失败', {
|
|
1321
|
-
error:
|
|
1322
|
-
orderList:
|
|
1379
|
+
error: _context17.t0 instanceof Error ? _context17.t0.message : String(_context17.t0),
|
|
1380
|
+
orderList: orderListSnapshot.length
|
|
1323
1381
|
});
|
|
1324
|
-
case
|
|
1382
|
+
case 11:
|
|
1325
1383
|
case "end":
|
|
1326
|
-
return
|
|
1384
|
+
return _context17.stop();
|
|
1327
1385
|
}
|
|
1328
|
-
},
|
|
1386
|
+
}, _callee17, this, [[3, 8]]);
|
|
1329
1387
|
}));
|
|
1330
|
-
function saveOrdersToSQLite(
|
|
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
|
|
1339
|
-
|
|
1340
|
-
|
|
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
|
-
|
|
1412
|
+
_context19.next = 6;
|
|
1347
1413
|
break;
|
|
1348
1414
|
}
|
|
1349
|
-
|
|
1350
|
-
return this.
|
|
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
|
|
1433
|
+
return _context19.stop();
|
|
1357
1434
|
}
|
|
1358
|
-
},
|
|
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 |
|
|
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
|
|
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
|
-
|
|
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.
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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:
|
|
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.
|
|
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 |
|
|
314
|
+
weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
|
|
315
315
|
}[]>;
|
|
316
316
|
submitTimeSlot(timeSlots: TimeSliceItem): void;
|
|
317
317
|
private getScheduleDataByIds;
|