@pisell/pisellos 0.10.43 → 0.10.45
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/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +135 -35
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +25 -1
- package/dist/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/dist/model/strategy/adapter/itemRule/type.js +19 -1
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
- package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
- package/dist/modules/Customer/index.js +2 -1
- package/dist/modules/Discount/availability.d.ts +7 -0
- package/dist/modules/Discount/availability.js +49 -0
- package/dist/modules/Discount/index.d.ts +1 -3
- package/dist/modules/Discount/index.js +12 -151
- package/dist/modules/Discount/types.d.ts +6 -0
- package/dist/modules/Order/index.d.ts +41 -9
- package/dist/modules/Order/index.js +1457 -872
- package/dist/modules/Order/salesNotes.d.ts +31 -0
- package/dist/modules/Order/salesNotes.js +492 -0
- package/dist/modules/Order/types.d.ts +105 -8
- package/dist/modules/Order/types.js +6 -1
- package/dist/modules/Order/utils.d.ts +4 -2
- package/dist/modules/Order/utils.js +224 -79
- package/dist/modules/Payment/cashRecommendationAlgorithm.d.ts +4 -5
- package/dist/modules/Payment/cashRecommendationAlgorithm.js +17 -367
- package/dist/modules/Product/index.d.ts +1 -1
- package/dist/modules/ProductList/index.d.ts +2 -1
- package/dist/modules/ProductList/index.js +100 -20
- package/dist/modules/ProductList/types.d.ts +10 -0
- package/dist/modules/Rules/index.js +50 -16
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +45 -3
- package/dist/server/modules/order/index.js +6 -0
- package/dist/server/modules/order/types.d.ts +9 -0
- package/dist/server/utils/small-ticket.d.ts +1 -0
- package/dist/server/utils/small-ticket.js +142 -14
- package/dist/solution/BaseSales/index.d.ts +15 -1
- package/dist/solution/BaseSales/index.js +1240 -877
- package/dist/solution/BaseSales/types.d.ts +2 -2
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -0
- package/dist/solution/BookingTicket/index.js +37 -16
- package/dist/solution/BookingTicket/utils/orderCustomer.js +3 -2
- package/dist/solution/RegisterAndLogin/config.d.ts +9 -3
- package/dist/solution/RegisterAndLogin/config.js +95 -40
- package/dist/solution/RegisterAndLogin/index.js +4 -1
- package/dist/solution/ScanOrder/index.d.ts +1 -0
- package/dist/solution/ScanOrder/index.js +31 -27
- package/dist/solution/ScanOrder/utils.d.ts +1 -0
- package/dist/solution/ScanOrder/utils.js +2 -0
- package/dist/solution/ShopDiscount/index.d.ts +1 -0
- package/dist/solution/ShopDiscount/index.js +59 -22
- package/dist/solution/ShopDiscount/utils.d.ts +4 -2
- package/dist/solution/ShopDiscount/utils.js +40 -21
- package/dist/solution/UnifiedBookingSales/index.d.ts +15 -2
- package/dist/solution/UnifiedBookingSales/index.js +777 -510
- package/dist/solution/UnifiedBookingSales/types.d.ts +14 -1
- package/dist/solution/VenueBooking/index.d.ts +1 -0
- package/dist/solution/VenueBooking/index.js +8 -4
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +73 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +23 -1
- package/lib/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/lib/model/strategy/adapter/itemRule/type.js +19 -1
- package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
- package/lib/model/strategy/adapter/walletPass/evaluator.js +2 -0
- package/lib/modules/Customer/index.js +1 -0
- package/lib/modules/Discount/availability.d.ts +7 -0
- package/lib/modules/Discount/availability.js +43 -0
- package/lib/modules/Discount/index.d.ts +1 -3
- package/lib/modules/Discount/index.js +10 -131
- package/lib/modules/Discount/types.d.ts +6 -0
- package/lib/modules/Order/index.d.ts +41 -9
- package/lib/modules/Order/index.js +456 -69
- package/lib/modules/Order/salesNotes.d.ts +31 -0
- package/lib/modules/Order/salesNotes.js +382 -0
- package/lib/modules/Order/types.d.ts +105 -8
- package/lib/modules/Order/types.js +5 -1
- package/lib/modules/Order/utils.d.ts +4 -2
- package/lib/modules/Order/utils.js +134 -3
- package/lib/modules/Payment/cashRecommendationAlgorithm.d.ts +4 -5
- package/lib/modules/Payment/cashRecommendationAlgorithm.js +9 -354
- package/lib/modules/Product/index.d.ts +1 -1
- package/lib/modules/ProductList/index.d.ts +2 -1
- package/lib/modules/ProductList/index.js +47 -2
- package/lib/modules/ProductList/types.d.ts +10 -0
- package/lib/modules/Rules/index.js +42 -5
- package/lib/server/index.d.ts +7 -0
- package/lib/server/index.js +39 -3
- package/lib/server/modules/order/index.js +6 -0
- package/lib/server/modules/order/types.d.ts +9 -0
- package/lib/server/utils/small-ticket.d.ts +1 -0
- package/lib/server/utils/small-ticket.js +136 -12
- package/lib/solution/BaseSales/index.d.ts +15 -1
- package/lib/solution/BaseSales/index.js +192 -22
- package/lib/solution/BaseSales/types.d.ts +2 -2
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -0
- package/lib/solution/BookingTicket/index.js +23 -5
- package/lib/solution/BookingTicket/utils/orderCustomer.js +2 -1
- package/lib/solution/RegisterAndLogin/config.d.ts +9 -3
- package/lib/solution/RegisterAndLogin/config.js +49 -8
- package/lib/solution/RegisterAndLogin/index.js +4 -1
- package/lib/solution/ScanOrder/index.d.ts +1 -0
- package/lib/solution/ScanOrder/index.js +5 -1
- package/lib/solution/ScanOrder/utils.d.ts +1 -0
- package/lib/solution/ScanOrder/utils.js +1 -0
- package/lib/solution/ShopDiscount/index.d.ts +1 -0
- package/lib/solution/ShopDiscount/index.js +29 -3
- package/lib/solution/ShopDiscount/utils.d.ts +4 -2
- package/lib/solution/ShopDiscount/utils.js +39 -23
- package/lib/solution/UnifiedBookingSales/index.d.ts +15 -2
- package/lib/solution/UnifiedBookingSales/index.js +125 -1
- package/lib/solution/UnifiedBookingSales/types.d.ts +14 -1
- package/lib/solution/VenueBooking/index.d.ts +1 -0
- package/lib/solution/VenueBooking/index.js +5 -1
- package/package.json +1 -1
|
@@ -25,6 +25,15 @@ Object.keys(_types).forEach(function (key) {
|
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
28
|
+
function normalizeQuerySet(values) {
|
|
29
|
+
if (!Array.isArray(values) || values.length === 0) return null;
|
|
30
|
+
const normalized = values.map(value => String(value ?? '').trim()).filter(Boolean);
|
|
31
|
+
return normalized.length ? new Set(normalized) : null;
|
|
32
|
+
}
|
|
33
|
+
function matchesAny(values, querySet) {
|
|
34
|
+
if (!querySet) return true;
|
|
35
|
+
return values.some(value => querySet.has(String(value ?? '').trim()));
|
|
36
|
+
}
|
|
28
37
|
class ProductList extends _BaseModule.BaseModule {
|
|
29
38
|
defaultName = 'productList';
|
|
30
39
|
defaultVersion = '1.0.0';
|
|
@@ -281,10 +290,46 @@ class ProductList extends _BaseModule.BaseModule {
|
|
|
281
290
|
const product = this.store.list.find(product => product.id === id);
|
|
282
291
|
return product ? (0, _lodashEs.cloneDeep)(product) : undefined;
|
|
283
292
|
}
|
|
293
|
+
async queryProducts(params = {}) {
|
|
294
|
+
const includeIds = normalizeQuerySet(params.includeIds);
|
|
295
|
+
const excludeIds = normalizeQuerySet(params.excludeIds);
|
|
296
|
+
const categoryIds = normalizeQuerySet(params.categoryIds);
|
|
297
|
+
const collectionIds = normalizeQuerySet(params.collectionIds);
|
|
298
|
+
const extensionTypes = normalizeQuerySet(params.extensionTypes);
|
|
299
|
+
const statuses = normalizeQuerySet(params.statuses);
|
|
300
|
+
const channelApplications = normalizeQuerySet(params.channelApplications);
|
|
301
|
+
const codeOrBarcode = typeof params.codeOrBarcode === 'string' ? params.codeOrBarcode.trim() : '';
|
|
302
|
+
const products = (this.store.list || []).filter(product => {
|
|
303
|
+
const productId = String(product.id ?? '').trim();
|
|
304
|
+
if (includeIds && !includeIds.has(productId)) return false;
|
|
305
|
+
if (excludeIds && excludeIds.has(productId)) return false;
|
|
306
|
+
if (categoryIds) {
|
|
307
|
+
const productCategoryIds = (product.categories || []).flatMap(category => [category?.id, category?.pivot?.product_category_id]);
|
|
308
|
+
if (!matchesAny(productCategoryIds, categoryIds)) return false;
|
|
309
|
+
}
|
|
310
|
+
if (collectionIds) {
|
|
311
|
+
const productCollectionIds = (product.collection || []).map(collection => collection?.id);
|
|
312
|
+
if (!matchesAny(productCollectionIds, collectionIds)) return false;
|
|
313
|
+
}
|
|
314
|
+
if (extensionTypes && !extensionTypes.has(String(product.extension_type ?? '').trim())) return false;
|
|
315
|
+
if (statuses && !statuses.has(String(product.status ?? '').trim())) return false;
|
|
316
|
+
if (channelApplications) {
|
|
317
|
+
if (!matchesAny(product.channel_application || [], channelApplications)) return false;
|
|
318
|
+
}
|
|
319
|
+
if (codeOrBarcode) {
|
|
320
|
+
const code = typeof product.code === 'string' ? product.code.trim() : '';
|
|
321
|
+
const barcode = typeof product.barcode === 'string' ? product.barcode.trim() : '';
|
|
322
|
+
if (code !== codeOrBarcode && barcode !== codeOrBarcode) return false;
|
|
323
|
+
}
|
|
324
|
+
return true;
|
|
325
|
+
});
|
|
326
|
+
return (0, _lodashEs.cloneDeep)(products);
|
|
327
|
+
}
|
|
284
328
|
async getProductByIds(ids) {
|
|
285
329
|
await this.core.effects.emit(`${this.name}:onGetProductByIds`, this.store.list);
|
|
286
|
-
|
|
287
|
-
|
|
330
|
+
return this.queryProducts({
|
|
331
|
+
includeIds: ids
|
|
332
|
+
});
|
|
288
333
|
}
|
|
289
334
|
async addProduct(products) {
|
|
290
335
|
// list 需要根据 id 去重
|
|
@@ -15,6 +15,16 @@ export interface ProductListLoadProductsParams {
|
|
|
15
15
|
/** 智能定价条件上下文,仅影响策略命中,不参与商品集合筛选 */
|
|
16
16
|
strategy_context?: Record<string, any>;
|
|
17
17
|
}
|
|
18
|
+
export interface ProductListStoreQueryParams {
|
|
19
|
+
includeIds?: Array<number | string>;
|
|
20
|
+
excludeIds?: Array<number | string>;
|
|
21
|
+
categoryIds?: Array<number | string>;
|
|
22
|
+
collectionIds?: Array<number | string>;
|
|
23
|
+
extensionTypes?: string[];
|
|
24
|
+
statuses?: ProductData['status'][];
|
|
25
|
+
channelApplications?: string[];
|
|
26
|
+
codeOrBarcode?: string;
|
|
27
|
+
}
|
|
18
28
|
export interface ProductListData {
|
|
19
29
|
list: ProductData[];
|
|
20
30
|
selectProducts: ProductData[];
|
|
@@ -12,6 +12,7 @@ var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
|
12
12
|
var _lodashEs = require("lodash-es");
|
|
13
13
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
14
14
|
var _entitlementPass = require("../Discount/entitlementPass");
|
|
15
|
+
var _availability = require("../Discount/availability");
|
|
15
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
17
|
class RulesModule extends _BaseModule.BaseModule {
|
|
17
18
|
defaultName = 'rules';
|
|
@@ -240,7 +241,13 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
240
241
|
if (discount.isEditMode) {
|
|
241
242
|
editModeDiscount.push(discount);
|
|
242
243
|
} else {
|
|
243
|
-
|
|
244
|
+
// 试算不能把 config / 不可用原因写回原有选券;每次重新计算以清除旧原因。
|
|
245
|
+
addModeDiscount.push({
|
|
246
|
+
...discount,
|
|
247
|
+
usageLimitFailKey: (0, _availability.getDiscountUsageLimitFailKey)(discount),
|
|
248
|
+
reason: undefined,
|
|
249
|
+
reasonCode: (0, _availability.getDiscountUsageBlockReason)(discount)
|
|
250
|
+
});
|
|
244
251
|
}
|
|
245
252
|
});
|
|
246
253
|
|
|
@@ -481,8 +488,15 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
481
488
|
|
|
482
489
|
// 🔥 为每个折扣卡/商品券执行策略检查并附加config
|
|
483
490
|
const evaluator = this.getWalletPassEvaluator();
|
|
491
|
+
addModeDiscount.forEach(discount => {
|
|
492
|
+
if (discount.reasonCode) discount.config = {
|
|
493
|
+
isAvailable: false
|
|
494
|
+
};
|
|
495
|
+
});
|
|
484
496
|
if (evaluator) {
|
|
485
497
|
addModeDiscount.forEach(discount => {
|
|
498
|
+
// 即使没有匹配的动态策略,服务端状态和次数限制也不能被覆盖为可用。
|
|
499
|
+
if (discount.reasonCode) return;
|
|
486
500
|
const discountType = discount.tag || discount.type || '';
|
|
487
501
|
// 对两类全额抵扣卡和折扣卡执行附加策略检查。
|
|
488
502
|
if (['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
|
|
@@ -501,7 +515,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
501
515
|
balance: entitlementQuota?.type === 'unlimited' ? Number.MAX_SAFE_INTEGER : entitlementQuota?.type === 'limited' ? entitlementQuota.balance : Number(discount.balance || 0),
|
|
502
516
|
type: discountType,
|
|
503
517
|
product_id: discount.product_id,
|
|
504
|
-
unified_available_status: 1,
|
|
518
|
+
unified_available_status: discount.unified_available_status ?? 1,
|
|
505
519
|
available_product_type: discount.limited_relation_product_data?.type,
|
|
506
520
|
available_product_ids: discount.limited_relation_product_data?.product_ids
|
|
507
521
|
};
|
|
@@ -532,6 +546,8 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
532
546
|
discount.config = {
|
|
533
547
|
isAvailable: false
|
|
534
548
|
};
|
|
549
|
+
discount.reason = result.reason;
|
|
550
|
+
discount.reasonCode = result.reasonCode || 'not_meet_the_required_conditions';
|
|
535
551
|
}
|
|
536
552
|
}
|
|
537
553
|
});
|
|
@@ -672,6 +688,8 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
672
688
|
|
|
673
689
|
// 记录每个优惠券适用的商品详细信息
|
|
674
690
|
const discountApplicableProducts = new Map();
|
|
691
|
+
const discountTimeReasons = new Map();
|
|
692
|
+
const discountHolderMismatch = new Set();
|
|
675
693
|
|
|
676
694
|
// 初始化每个优惠券的适用性和可抵扣商品
|
|
677
695
|
addModeDiscount.forEach(discount => {
|
|
@@ -691,6 +709,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
691
709
|
|
|
692
710
|
// 辅助函数:检查商品是否对某个折扣卡可用
|
|
693
711
|
const checkItemApplicableForDiscount = (flatItem, discount) => {
|
|
712
|
+
if (discount.config?.isAvailable === false) return false;
|
|
694
713
|
let product;
|
|
695
714
|
if (flatItem.type === 'main') {
|
|
696
715
|
product = flatItem.product;
|
|
@@ -896,16 +915,23 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
896
915
|
isNeedHolder: resolveIsFormSubject(_tempVar) && !_tempVar?.isNormalProduct,
|
|
897
916
|
holder_id: _tempVar?.holder_id || product.holder_id
|
|
898
917
|
}, holders);
|
|
899
|
-
|
|
900
|
-
timeLimit =
|
|
918
|
+
const timeReason = (0, _utils.getDiscountTimeUnavailableReason)(discount, (product?.startDate || (0, _dayjs.default)()).format('YYYY-MM-DD HH:mm:ss'));
|
|
919
|
+
const timeLimit = !timeReason;
|
|
901
920
|
// 是符合折扣的商品
|
|
902
|
-
const
|
|
921
|
+
const isProductInScope = limitedData.type === 'product_all' && limitedData.filter !== 1 || limitedData.type === 'product_all' && limitedData.filter === 1 && !limitedData.exclude_product_ids.includes(product.id) || limitedData.product_ids && limitedData.product_ids.includes(product.id);
|
|
922
|
+
const isLimitedProduct = isProductInScope && isHolderMatch;
|
|
903
923
|
|
|
904
924
|
// 编辑的商品 使用了优惠券不可用
|
|
905
925
|
const isAvailableProduct = flatItem.type === 'main' ? !(product?.booking_id && product?.discount_list?.length && product?.discount_list?.every(discount => discount.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type))) : !(flatItem?.booking_id && !!flatItem?.bundleItem?.discount_list?.length && flatItem?.bundleItem?.discount_list?.every(discount => discount.id));
|
|
906
926
|
|
|
907
927
|
// 套餐是否可用判断
|
|
908
928
|
const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
|
|
929
|
+
if (isProductInScope && isBundleAvailable && !isItemRewardProductDiscount) {
|
|
930
|
+
const timeReasons = discountTimeReasons.get(discount.id) || [];
|
|
931
|
+
timeReasons.push(timeReason);
|
|
932
|
+
discountTimeReasons.set(discount.id, timeReasons);
|
|
933
|
+
if (!isHolderMatch && timeLimit) discountHolderMismatch.add(discount.id);
|
|
934
|
+
}
|
|
909
935
|
|
|
910
936
|
// 判断优惠券是否适用于该商品
|
|
911
937
|
if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && discount.config?.isAvailable && (!(0, _entitlementPass.isEntitlementPass)(discount) || (0, _entitlementPass.getRemainingEntitlementUses)(discount, 0, 1) > 0)) {
|
|
@@ -2028,11 +2054,19 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2028
2054
|
|
|
2029
2055
|
// 根据是否有适用商品决定isAvailable
|
|
2030
2056
|
const isAvailable = applicableProducts.length > 0;
|
|
2057
|
+
const timeReasons = discountTimeReasons.get(discount.id) || [];
|
|
2058
|
+
const timeReason = timeReasons.length ? timeReasons.every(Boolean) ? timeReasons[0] : undefined : (0, _utils.getDiscountTimeUnavailableReason)(discount, (0, _dayjs.default)().format('YYYY-MM-DD HH:mm:ss'));
|
|
2059
|
+
const reasonCode = isAvailable ? undefined : (0, _availability.getDiscountUsageBlockReason)(discount) || timeReason || discount.reasonCode || (discountHolderMismatch.has(discount.id) ? 'holder_not_matched' : 'product_not_applicable');
|
|
2060
|
+
const availabilityReason = {
|
|
2061
|
+
reasonCode,
|
|
2062
|
+
reason: reasonCode && reasonCode === discount.reasonCode ? discount.reason : undefined
|
|
2063
|
+
};
|
|
2031
2064
|
|
|
2032
2065
|
// 如果此优惠券被明确设置为不选中,保持其状态,但正确设置isAvailable
|
|
2033
2066
|
if (typeof discount.isSelected === 'boolean' && discount.isSelected === false && discount.isManualSelect) {
|
|
2034
2067
|
return {
|
|
2035
2068
|
...discount,
|
|
2069
|
+
...availabilityReason,
|
|
2036
2070
|
isSelected: false,
|
|
2037
2071
|
isAvailable: isAvailable,
|
|
2038
2072
|
// 正确设置可用性
|
|
@@ -2046,6 +2080,8 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2046
2080
|
if (isDiscountUsed(discount)) {
|
|
2047
2081
|
return {
|
|
2048
2082
|
...discount,
|
|
2083
|
+
reason: undefined,
|
|
2084
|
+
reasonCode: undefined,
|
|
2049
2085
|
isSelected: true,
|
|
2050
2086
|
isManualSelect: options?.scan ? false : discount.isManualSelect,
|
|
2051
2087
|
// 标记为可用,因为它已被应用
|
|
@@ -2068,6 +2104,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
2068
2104
|
}
|
|
2069
2105
|
return {
|
|
2070
2106
|
...discount,
|
|
2107
|
+
...availabilityReason,
|
|
2071
2108
|
// 如果有适用的商品,标记为可用
|
|
2072
2109
|
isAvailable: isAvailable,
|
|
2073
2110
|
isSelected,
|
package/lib/server/index.d.ts
CHANGED
|
@@ -421,6 +421,7 @@ declare class Server {
|
|
|
421
421
|
private shouldUseLocalOrderQuery;
|
|
422
422
|
/**
|
|
423
423
|
* 预约查询是否走本地:
|
|
424
|
+
* - 日历周/月/资源视图通过 compact_fields 显式标识,始终走远端;
|
|
424
425
|
* - 当 sales_time_between 的开始和结束都不是今天时,走远端;
|
|
425
426
|
* - 其余情况走本地。
|
|
426
427
|
*/
|
|
@@ -524,6 +525,12 @@ declare class Server {
|
|
|
524
525
|
private stringifyCheckoutResourceIdentifier;
|
|
525
526
|
private normalizeCheckoutSubmitData;
|
|
526
527
|
private ensureCheckoutOrderNumbers;
|
|
528
|
+
/**
|
|
529
|
+
* Notes 允许在本地草稿阶段暂存空订单目标;checkout 的统一出口负责用最终
|
|
530
|
+
* shop_order_number 完成绑定并校验,保证后端请求、pending、设备任务和打印
|
|
531
|
+
* 都使用同一份完整快照。
|
|
532
|
+
*/
|
|
533
|
+
private finalizeCheckoutSalesNotes;
|
|
527
534
|
private dispatchCheckoutSyncTask;
|
|
528
535
|
private dispatchPrintOtherReceiptTask;
|
|
529
536
|
private buildPrintOtherReceiptIdempotencyKey;
|
package/lib/server/index.js
CHANGED
|
@@ -27,6 +27,7 @@ var _filterBookings = require("./modules/order/utils/filterBookings");
|
|
|
27
27
|
var _smallTicket = require("./utils/small-ticket");
|
|
28
28
|
var _BaseSales = require("../solution/BaseSales");
|
|
29
29
|
var _paymentUtils = require("../modules/Order/payment-utils");
|
|
30
|
+
var _salesNotes = require("../modules/Order/salesNotes");
|
|
30
31
|
var _orderCollectionIdentity = require("../modules/Order/utils/orderCollectionIdentity");
|
|
31
32
|
var _osPrivatePayload = require("../utils/os-private-payload");
|
|
32
33
|
var _OpenData = require("../modules/OpenData");
|
|
@@ -2172,10 +2173,12 @@ class Server {
|
|
|
2172
2173
|
|
|
2173
2174
|
/**
|
|
2174
2175
|
* 预约查询是否走本地:
|
|
2176
|
+
* - 日历周/月/资源视图通过 compact_fields 显式标识,始终走远端;
|
|
2175
2177
|
* - 当 sales_time_between 的开始和结束都不是今天时,走远端;
|
|
2176
2178
|
* - 其余情况走本地。
|
|
2177
2179
|
*/
|
|
2178
2180
|
shouldUseLocalBookingQuery(data) {
|
|
2181
|
+
if (data?.compact_fields === true) return false;
|
|
2179
2182
|
const range = data?.sales_time_between;
|
|
2180
2183
|
if (!Array.isArray(range) || range.length < 2) return true;
|
|
2181
2184
|
return !this.isRangeBothNotToday(range[0], range[1]);
|
|
@@ -3682,14 +3685,16 @@ class Server {
|
|
|
3682
3685
|
};
|
|
3683
3686
|
const needsShopOrderNumber = next.shop_order_number === undefined || next.shop_order_number === null || next.shop_order_number === '';
|
|
3684
3687
|
const needsShopFullOrderNumber = next.shop_full_order_number === undefined || next.shop_full_order_number === null || next.shop_full_order_number === '';
|
|
3685
|
-
if (!needsShopOrderNumber && !needsShopFullOrderNumber)
|
|
3688
|
+
if (!needsShopOrderNumber && !needsShopFullOrderNumber) {
|
|
3689
|
+
return this.finalizeCheckoutSalesNotes(next, title);
|
|
3690
|
+
}
|
|
3686
3691
|
const idGenerator = this.getIdGeneratorPlugin();
|
|
3687
3692
|
if (!idGenerator) {
|
|
3688
3693
|
this.logWarning(`${title}: idGenerator 插件不可用,无法生成订单号`, {
|
|
3689
3694
|
needsShopOrderNumber,
|
|
3690
3695
|
needsShopFullOrderNumber
|
|
3691
3696
|
});
|
|
3692
|
-
return next;
|
|
3697
|
+
return this.finalizeCheckoutSalesNotes(next, title);
|
|
3693
3698
|
}
|
|
3694
3699
|
try {
|
|
3695
3700
|
if (needsShopOrderNumber && idGenerator.generateShopOrderNumber) {
|
|
@@ -3711,7 +3716,38 @@ class Server {
|
|
|
3711
3716
|
error: error instanceof Error ? error.message : String(error)
|
|
3712
3717
|
});
|
|
3713
3718
|
}
|
|
3714
|
-
return next;
|
|
3719
|
+
return this.finalizeCheckoutSalesNotes(next, title);
|
|
3720
|
+
}
|
|
3721
|
+
|
|
3722
|
+
/**
|
|
3723
|
+
* Notes 允许在本地草稿阶段暂存空订单目标;checkout 的统一出口负责用最终
|
|
3724
|
+
* shop_order_number 完成绑定并校验,保证后端请求、pending、设备任务和打印
|
|
3725
|
+
* 都使用同一份完整快照。
|
|
3726
|
+
*/
|
|
3727
|
+
finalizeCheckoutSalesNotes(data, title) {
|
|
3728
|
+
if (!data || typeof data !== 'object') return data;
|
|
3729
|
+
if (!Object.prototype.hasOwnProperty.call(data, 'notes')) return data;
|
|
3730
|
+
if (data.notes === undefined || data.notes === null) return data;
|
|
3731
|
+
if (!Array.isArray(data.notes)) {
|
|
3732
|
+
throw new Error('[Order Notes] checkout notes 必须为数组');
|
|
3733
|
+
}
|
|
3734
|
+
if (data.notes.length === 0) return data;
|
|
3735
|
+
const productTargetUuids = (Array.isArray(data.products) ? data.products : []).map(product => product?.metadata?.unique_identification_number ?? product?.unique_identification_number).filter(targetUuid => targetUuid !== undefined && targetUuid !== null && String(targetUuid).trim().length > 0).map(targetUuid => String(targetUuid));
|
|
3736
|
+
const shopOrderNumber = String(data.shop_order_number ?? '').trim();
|
|
3737
|
+
const notes = (0, _salesNotes.finalizeSalesNotesForCheckout)({
|
|
3738
|
+
notes: data.notes,
|
|
3739
|
+
shopOrderNumber,
|
|
3740
|
+
productTargetUuids
|
|
3741
|
+
});
|
|
3742
|
+
this.logInfo(`${title}: checkout Notes 已绑定订单号`, {
|
|
3743
|
+
shop_order_number: shopOrderNumber,
|
|
3744
|
+
note_count: notes.length
|
|
3745
|
+
});
|
|
3746
|
+
return {
|
|
3747
|
+
...data,
|
|
3748
|
+
shop_order_number: shopOrderNumber,
|
|
3749
|
+
notes
|
|
3750
|
+
};
|
|
3715
3751
|
}
|
|
3716
3752
|
async dispatchCheckoutSyncTask(params) {
|
|
3717
3753
|
this.registerDeviceTaskActions();
|
|
@@ -2017,6 +2017,12 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2017
2017
|
mergedRecord[field] = (0, _lodashEs.cloneDeep)(incomingRecord[field]);
|
|
2018
2018
|
}
|
|
2019
2019
|
|
|
2020
|
+
// order_meta_list 是一次性生成的完整业务快照。incoming 明确携带时
|
|
2021
|
+
// 必须整体覆盖(包括 null / 空对象 / 空数组);省略时才保留 existing。
|
|
2022
|
+
if (Object.prototype.hasOwnProperty.call(incomingRecord, 'order_meta_list')) {
|
|
2023
|
+
mergedRecord.order_meta_list = (0, _lodashEs.cloneDeep)(incomingRecord.order_meta_list);
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2020
2026
|
// 子项数组遵循完整快照语义:incoming 自有且为数组(包括 [])时权威替换;
|
|
2021
2027
|
// 字段缺席或不是数组时视为稀疏 patch,继续保留 existing。
|
|
2022
2028
|
for (const field of ORDER_AUTHORITATIVE_COLLECTION_FIELDS) {
|
|
@@ -456,6 +456,15 @@ export interface OrderData {
|
|
|
456
456
|
par_value: string;
|
|
457
457
|
used_par_value: string;
|
|
458
458
|
}>;
|
|
459
|
+
virtual_currency_snapshot?: Array<{
|
|
460
|
+
id: number | string;
|
|
461
|
+
tag: 'virtual_currency';
|
|
462
|
+
product_id?: number | string;
|
|
463
|
+
product_name: string;
|
|
464
|
+
par_value: string;
|
|
465
|
+
used_par_value: string;
|
|
466
|
+
name: Record<string, string>;
|
|
467
|
+
}>;
|
|
459
468
|
};
|
|
460
469
|
/**
|
|
461
470
|
* 金额汇总(仅输出)。
|
|
@@ -311,6 +311,7 @@ function buildBaseData(params) {
|
|
|
311
311
|
}
|
|
312
312
|
function buildProducts(order, locale, productMap) {
|
|
313
313
|
const products = Array.isArray(order.products) ? order.products : [];
|
|
314
|
+
const allergyByProductUid = buildProductAllergyMap(order, locale);
|
|
314
315
|
return products.map(rawProduct => {
|
|
315
316
|
const product = restoreReceiptDiscountHierarchy(rawProduct);
|
|
316
317
|
const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
|
|
@@ -351,6 +352,7 @@ function buildProducts(order, locale, productMap) {
|
|
|
351
352
|
originalPrice
|
|
352
353
|
});
|
|
353
354
|
const productNote = resolveProductNote(product, locale);
|
|
355
|
+
const allergy = isPresentId(productUid) ? allergyByProductUid.get(String(productUid).trim()) || '' : '';
|
|
354
356
|
const basePrice = resolveProductBasePrice(product);
|
|
355
357
|
const resolvedCombinations = Array.isArray(product.combinations) && product.combinations.length ? normalizeExistingCombinations(product.combinations, locale, currencySymbol) : combinations;
|
|
356
358
|
const shouldIncludeBasePrice = options.length > 0 || resolvedCombinations.length > 0 || hasProductDiscount(product, extensionList);
|
|
@@ -380,6 +382,9 @@ function buildProducts(order, locale, productMap) {
|
|
|
380
382
|
...(productNote ? {
|
|
381
383
|
product_note: productNote
|
|
382
384
|
} : {}),
|
|
385
|
+
...(allergy ? {
|
|
386
|
+
allergy
|
|
387
|
+
} : {}),
|
|
383
388
|
...(options.length ? {
|
|
384
389
|
options
|
|
385
390
|
} : {}),
|
|
@@ -782,6 +787,21 @@ function resolveProductNote(product, locale) {
|
|
|
782
787
|
if (productNote) return productNote;
|
|
783
788
|
return getLocalizedValue(product.note, locale).trim();
|
|
784
789
|
}
|
|
790
|
+
function buildProductAllergyMap(order, locale) {
|
|
791
|
+
const allergyByProductUid = new Map();
|
|
792
|
+
for (const note of normalizeArray(order.notes)) {
|
|
793
|
+
if (!note || typeof note !== 'object' || Array.isArray(note) || String(note.note_type || '').trim() !== 'allergy') {
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
const content = getLocalizedValue(note.content?.text, locale).trim();
|
|
797
|
+
if (!content) continue;
|
|
798
|
+
const relation = normalizeArray(note.note_relations).find(item => item && typeof item === 'object' && !Array.isArray(item) && item.relation_type === 'about' && item.target_type === 'order_detail' && Number(item.is_primary) === 1);
|
|
799
|
+
const productUid = String(relation?.target_uuid ?? '').trim();
|
|
800
|
+
if (!productUid || allergyByProductUid.has(productUid)) continue;
|
|
801
|
+
allergyByProductUid.set(productUid, content);
|
|
802
|
+
}
|
|
803
|
+
return allergyByProductUid;
|
|
804
|
+
}
|
|
785
805
|
function resolveBundleProductTitle(params) {
|
|
786
806
|
const {
|
|
787
807
|
bundle,
|
|
@@ -1358,20 +1378,30 @@ function resolveRefundPayment(refund, payments) {
|
|
|
1358
1378
|
return matchedPayment || refund;
|
|
1359
1379
|
}
|
|
1360
1380
|
function buildWallets(params) {
|
|
1381
|
+
const virtualCurrencySnapshots = collectVirtualCurrencySnapshots(params.order);
|
|
1361
1382
|
const displayedWalletPayments = normalizeArray(params.order.payments).filter(payment => isPrintablePayment(payment) && !!getFundRecord(payment));
|
|
1362
|
-
const paymentWallets = displayedWalletPayments.map(payment =>
|
|
1363
|
-
payment,
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1383
|
+
const paymentWallets = displayedWalletPayments.map(payment => {
|
|
1384
|
+
const virtualCurrencySnapshot = findVirtualCurrencySnapshotForPayment(payment, virtualCurrencySnapshots.byId);
|
|
1385
|
+
return buildPaymentItems({
|
|
1386
|
+
payment,
|
|
1387
|
+
locale: params.locale,
|
|
1388
|
+
currencySymbol: params.currencySymbol,
|
|
1389
|
+
includeFundRecordBalance: true,
|
|
1390
|
+
includeFundRecordUsage: false,
|
|
1391
|
+
includePaymentAmount: false,
|
|
1392
|
+
virtualCurrencyUnit: virtualCurrencySnapshot ? getVirtualCurrencySnapshotUnit(virtualCurrencySnapshot, params.locale) : undefined
|
|
1393
|
+
});
|
|
1394
|
+
});
|
|
1370
1395
|
const displayedWalletPassIds = collectDisplayedWalletPassIds(displayedWalletPayments);
|
|
1371
1396
|
return [...paymentWallets, ...buildVoucherAssets(params), ...buildPointCardSnapshotAssets({
|
|
1372
1397
|
order: params.order,
|
|
1373
1398
|
locale: params.locale,
|
|
1374
1399
|
displayedWalletPassIds
|
|
1400
|
+
}), ...buildVirtualCurrencySnapshotAssets({
|
|
1401
|
+
snapshots: virtualCurrencySnapshots.items,
|
|
1402
|
+
order: params.order,
|
|
1403
|
+
locale: params.locale,
|
|
1404
|
+
displayedWalletPassIds
|
|
1375
1405
|
})];
|
|
1376
1406
|
}
|
|
1377
1407
|
function collectDisplayedWalletPassIds(payments) {
|
|
@@ -1418,6 +1448,88 @@ function buildPointCardSnapshotAssets(params) {
|
|
|
1418
1448
|
return [rows];
|
|
1419
1449
|
});
|
|
1420
1450
|
}
|
|
1451
|
+
function collectVirtualCurrencySnapshots(order) {
|
|
1452
|
+
const items = [];
|
|
1453
|
+
const byId = new Map();
|
|
1454
|
+
const snapshots = order.order_meta_list?.virtual_currency_snapshot;
|
|
1455
|
+
if (!Array.isArray(snapshots)) return {
|
|
1456
|
+
items,
|
|
1457
|
+
byId
|
|
1458
|
+
};
|
|
1459
|
+
snapshots.forEach(snapshot => {
|
|
1460
|
+
if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) return;
|
|
1461
|
+
const virtualCurrency = snapshot;
|
|
1462
|
+
if (stringify(virtualCurrency.tag).trim().toLowerCase() !== 'virtual_currency') return;
|
|
1463
|
+
const id = normalizeWalletPassId(virtualCurrency.id);
|
|
1464
|
+
if (!id || byId.has(id)) return;
|
|
1465
|
+
byId.set(id, virtualCurrency);
|
|
1466
|
+
items.push(virtualCurrency);
|
|
1467
|
+
});
|
|
1468
|
+
return {
|
|
1469
|
+
items,
|
|
1470
|
+
byId
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
function findVirtualCurrencySnapshotForPayment(payment, snapshotsById) {
|
|
1474
|
+
const fundRecord = getFundRecord(payment);
|
|
1475
|
+
for (const value of [fundRecord?.voucher_id, payment.voucher_id]) {
|
|
1476
|
+
const id = normalizeWalletPassId(value);
|
|
1477
|
+
if (!id) continue;
|
|
1478
|
+
const snapshot = snapshotsById.get(id);
|
|
1479
|
+
if (snapshot) return snapshot;
|
|
1480
|
+
}
|
|
1481
|
+
return undefined;
|
|
1482
|
+
}
|
|
1483
|
+
function buildVirtualCurrencySnapshotAssets(params) {
|
|
1484
|
+
const snapshotTime = firstPresentValue(params.order.updated_at, params.order.created_at);
|
|
1485
|
+
return params.snapshots.flatMap(virtualCurrency => {
|
|
1486
|
+
const id = normalizeWalletPassId(virtualCurrency.id);
|
|
1487
|
+
if (!id || params.displayedWalletPassIds.has(id)) return [];
|
|
1488
|
+
const rows = [{
|
|
1489
|
+
item: stringify(virtualCurrency.product_name).trim(),
|
|
1490
|
+
value: ''
|
|
1491
|
+
}];
|
|
1492
|
+
const balance = getVirtualCurrencySnapshotBalance(virtualCurrency);
|
|
1493
|
+
if (balance) {
|
|
1494
|
+
rows.push({
|
|
1495
|
+
item: label(params.locale, 'balance'),
|
|
1496
|
+
value: formatVirtualCurrencyBalance(balance, getVirtualCurrencySnapshotUnit(virtualCurrency, params.locale))
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
if (isPresentId(snapshotTime)) {
|
|
1500
|
+
rows.push({
|
|
1501
|
+
item: formatDateTime(snapshotTime, params.locale),
|
|
1502
|
+
value: ''
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
return [rows];
|
|
1506
|
+
});
|
|
1507
|
+
}
|
|
1508
|
+
function getVirtualCurrencySnapshotBalance(snapshot) {
|
|
1509
|
+
if (!isNumericAmount(snapshot.par_value) || !isNumericAmount(snapshot.used_par_value)) {
|
|
1510
|
+
return null;
|
|
1511
|
+
}
|
|
1512
|
+
return _decimal.default.max(new _decimal.default(snapshot.par_value).minus(new _decimal.default(snapshot.used_par_value)), 0);
|
|
1513
|
+
}
|
|
1514
|
+
function getVirtualCurrencySnapshotUnit(snapshot, locale) {
|
|
1515
|
+
return getNonEmptyLocalizedValue(snapshot.name, locale);
|
|
1516
|
+
}
|
|
1517
|
+
function getNonEmptyLocalizedValue(value, locale) {
|
|
1518
|
+
if (value === undefined || value === null) return '';
|
|
1519
|
+
if (typeof value !== 'object' || Array.isArray(value)) return stringify(value).trim();
|
|
1520
|
+
const dashedLocale = locale.replace('_', '-');
|
|
1521
|
+
const underscoredLocale = locale.replace('-', '_');
|
|
1522
|
+
for (const candidate of [value[locale], value[dashedLocale], value[underscoredLocale], value.original, value.auto, value.default, value.en]) {
|
|
1523
|
+
const text = stringify(candidate).trim();
|
|
1524
|
+
if (text) return text;
|
|
1525
|
+
}
|
|
1526
|
+
return '';
|
|
1527
|
+
}
|
|
1528
|
+
function formatVirtualCurrencyBalance(value, unit) {
|
|
1529
|
+
const amount = trimDecimal(value);
|
|
1530
|
+
const normalizedUnit = unit.trim();
|
|
1531
|
+
return normalizedUnit ? `${amount} ${normalizedUnit}` : amount;
|
|
1532
|
+
}
|
|
1421
1533
|
function normalizeWalletPassId(value) {
|
|
1422
1534
|
if (typeof value === 'number') return Number.isFinite(value) ? String(value) : null;
|
|
1423
1535
|
if (typeof value !== 'string') return null;
|
|
@@ -1470,8 +1582,9 @@ function buildVoucherAssets(params) {
|
|
|
1470
1582
|
}, ...(timeRow ? [timeRow] : [])]];
|
|
1471
1583
|
});
|
|
1472
1584
|
}
|
|
1585
|
+
const TICKET_VOUCHER_TAGS = new Set(['ticket', 'product_package_ticket', 'appointment_ticket', 'session_ticket']);
|
|
1473
1586
|
function isTicketVoucher(voucher) {
|
|
1474
|
-
return stringify(voucher.tag).trim().toLowerCase()
|
|
1587
|
+
return TICKET_VOUCHER_TAGS.has(stringify(voucher.tag).trim().toLowerCase());
|
|
1475
1588
|
}
|
|
1476
1589
|
function getVoucherValidity(voucher, locale) {
|
|
1477
1590
|
const availableTime = firstPresentValue(voucher.available_time, voucher.avaliable_time, voucher.metadata?.available_time, voucher.metadata?.avaliable_time);
|
|
@@ -1583,7 +1696,8 @@ function buildPaymentItems(params) {
|
|
|
1583
1696
|
currencySymbol,
|
|
1584
1697
|
includeFundRecordBalance,
|
|
1585
1698
|
includeFundRecordUsage,
|
|
1586
|
-
includePaymentAmount
|
|
1699
|
+
includePaymentAmount,
|
|
1700
|
+
virtualCurrencyUnit
|
|
1587
1701
|
} = params;
|
|
1588
1702
|
const serviceFee = getPaymentServiceFee(payment);
|
|
1589
1703
|
const items = [{
|
|
@@ -1609,7 +1723,8 @@ function buildPaymentItems(params) {
|
|
|
1609
1723
|
locale,
|
|
1610
1724
|
currencySymbol,
|
|
1611
1725
|
includeBalance: includeFundRecordBalance,
|
|
1612
|
-
includeUsage: includeFundRecordUsage
|
|
1726
|
+
includeUsage: includeFundRecordUsage,
|
|
1727
|
+
virtualCurrencyUnit
|
|
1613
1728
|
}));
|
|
1614
1729
|
} else {
|
|
1615
1730
|
const remainingAmount = payment.remaining_amount ?? payment.balance ?? payment.metadata?.remaining_amount;
|
|
@@ -1674,7 +1789,8 @@ function buildFundRecordPaymentItems(params) {
|
|
|
1674
1789
|
locale,
|
|
1675
1790
|
currencySymbol,
|
|
1676
1791
|
includeBalance,
|
|
1677
|
-
includeUsage
|
|
1792
|
+
includeUsage,
|
|
1793
|
+
virtualCurrencyUnit
|
|
1678
1794
|
} = params;
|
|
1679
1795
|
const items = [];
|
|
1680
1796
|
const usingBeforeValue = fundRecord.using_before_value;
|
|
@@ -1696,6 +1812,14 @@ function buildFundRecordPaymentItems(params) {
|
|
|
1696
1812
|
return items;
|
|
1697
1813
|
}
|
|
1698
1814
|
if (includeBalance && usingAfterValue !== undefined && usingAfterValue !== null) {
|
|
1815
|
+
if (virtualCurrencyUnit !== undefined) {
|
|
1816
|
+
if (!isNumericAmount(usingAfterValue)) return items;
|
|
1817
|
+
items.push({
|
|
1818
|
+
item: label(locale, 'balance'),
|
|
1819
|
+
value: formatVirtualCurrencyBalance(new _decimal.default(usingAfterValue), virtualCurrencyUnit)
|
|
1820
|
+
});
|
|
1821
|
+
return items;
|
|
1822
|
+
}
|
|
1699
1823
|
items.push({
|
|
1700
1824
|
item: label(locale, 'balance'),
|
|
1701
1825
|
value: formatMoney(usingAfterValue, currencySymbol)
|
|
@@ -2,7 +2,7 @@ import { Module, ModuleOptions, PisellCore } from '../../types';
|
|
|
2
2
|
import { BaseModule } from '../../modules/BaseModule';
|
|
3
3
|
import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentStatus, BaseSalesUpdateOrderProductQuantityParams, BaseSalesCalculateProductBookingPriceParams, BaseSalesPriceRecalculationContextChange, BaseSalesProductBookingPriceResult, BaseSalesQuotationCustomerScopeInfo, BaseSalesScanCodeResult, BaseSalesCashPaymentConfig, BaseSalesPayCashParams, BaseSalesPayCashResult, BaseSalesCommitPaymentMethodParams, BaseSalesCommitPaymentMethodResult, BaseSalesConfirmWalletPaymentResult } from './types';
|
|
4
4
|
import { OrderModule } from '../../modules/Order';
|
|
5
|
-
import type { AddProductBookingInput, AddProductToOrderOptions, LoadSalesDetailParams, OrderPaymentData, OrderPaymentUpdateOptions, OrderPaymentUpdateResult, OrderPaymentSource, SendCustomerPayLinkParams, SyncPaymentsToOrderParams, SyncPaymentsToOrderResult, UpdateTempOrderCustomerInput, UpdateOrderBookingParams, UpdateOrderProductParams, OrderTempOrder, OrderSummary, OrderPromotionEvaluator, OrderGiftSelectResolver, OrderUnfulfilledPromotion, OrderLastGiftActions, RemoveProductsFromOrderOptions, ReplaceTempOrderOptions } from '../../modules/Order/types';
|
|
5
|
+
import type { AddProductBookingInput, AddProductToOrderOptions, LoadSalesDetailParams, OrderPaymentData, OrderPaymentUpdateOptions, OrderPaymentUpdateResult, OrderPaymentSource, SendCustomerPayLinkParams, SyncPaymentsToOrderParams, SyncPaymentsToOrderResult, UpdateTempOrderCustomerInput, UpdateOrderBookingParams, UpdateOrderProductParams, OrderTempOrder, OrderSummary, OrderPromotionEvaluator, OrderGiftSelectResolver, OrderUnfulfilledPromotion, OrderLastGiftActions, RemoveProductsFromOrderOptions, ReplaceTempOrderOptions, SalesNote, SalesNotesMutationSnapshot, SetSalesNoteInput, PickupReferenceMode, ShopServiceData, ShopServiceType } from '../../modules/Order/types';
|
|
6
6
|
import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
|
|
7
7
|
import type { Discount, VirtualCurrencyAsset } from '../../modules/Discount/types';
|
|
8
8
|
import { RequestPlugin, WindowPlugin } from '../../plugins';
|
|
@@ -232,6 +232,12 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
232
232
|
getOrderSyncState(): import("../../modules/Order/types").OrderSyncState;
|
|
233
233
|
getOrderAmountSnapshot(): import("../../modules/Order/types").OrderAmountSnapshot | null;
|
|
234
234
|
getTempOrderNote(): string;
|
|
235
|
+
getSalesNotes(): SalesNote[];
|
|
236
|
+
createSalesNotesMutationSnapshot(): SalesNotesMutationSnapshot;
|
|
237
|
+
restoreSalesNotesMutationSnapshot(snapshot: SalesNotesMutationSnapshot): void;
|
|
238
|
+
setSalesNote(input: SetSalesNoteInput): Promise<SalesNote>;
|
|
239
|
+
removeSalesNote(uuid: string): Promise<void>;
|
|
240
|
+
clearSalesNotes(): Promise<void>;
|
|
235
241
|
updateTempOrderNote(note: string): string;
|
|
236
242
|
updateTempOrderNote(note: string, sync: true): Promise<string>;
|
|
237
243
|
updateTempOrderNote(note: string, sync: boolean): string | Promise<string>;
|
|
@@ -240,6 +246,8 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
240
246
|
setPickupRef(buzzer: string): string;
|
|
241
247
|
updateTempOrderShopDiscount(amount: string | number): string;
|
|
242
248
|
updateTempOrderDepositAmount(amount: string | number): OrderSummary;
|
|
249
|
+
setPickupReferenceMode(mode: PickupReferenceMode): ShopServiceData;
|
|
250
|
+
setServiceType(serviceType: ShopServiceType): ShopServiceData;
|
|
243
251
|
updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
|
|
244
252
|
/** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化。 */
|
|
245
253
|
setEnableTempOrderPersist(enabled: boolean): void;
|
|
@@ -263,6 +271,12 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
|
|
|
263
271
|
private mergeHistoricalDiscountList;
|
|
264
272
|
private shouldSkipAutoApplyFetchedDiscountsInEditMode;
|
|
265
273
|
private mergeCurrentDiscountSelectionState;
|
|
274
|
+
private resolveDiscountConfigCustomerId;
|
|
275
|
+
/**
|
|
276
|
+
* Stable across notifyTempOrderChanged's immutable object replacement, while
|
|
277
|
+
* still distinguishing two local orders for the same customer.
|
|
278
|
+
*/
|
|
279
|
+
private getDiscountConfigOrderIdentityKey;
|
|
266
280
|
loadDiscountConfig(params?: {
|
|
267
281
|
customerId?: number;
|
|
268
282
|
action?: 'create' | 'edit';
|