@pisell/pisellos 0.0.500 → 0.0.502
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 +8 -0
- package/dist/model/strategy/adapter/itemRule/adapter.js +52 -8
- package/dist/model/strategy/adapter/itemRule/examples.d.ts +15 -0
- package/dist/model/strategy/adapter/itemRule/examples.js +68 -1
- package/dist/model/strategy/adapter/itemRule/index.d.ts +1 -1
- package/dist/model/strategy/adapter/itemRule/index.js +1 -1
- package/dist/model/strategy/adapter/itemRule/type.d.ts +20 -1
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Order/index.d.ts +10 -0
- package/dist/modules/Order/index.js +64 -40
- package/dist/modules/Order/types.d.ts +13 -1
- package/dist/modules/Order/utils.d.ts +36 -1
- package/dist/modules/Order/utils.js +120 -24
- package/dist/modules/ProductList/index.js +2 -2
- package/dist/modules/Quotation/index.js +6 -3
- package/dist/modules/SalesSummary/types.d.ts +2 -1
- package/dist/modules/SalesSummary/utils.js +10 -10
- package/dist/modules/Schedule/utils.d.ts +1 -1
- package/dist/solution/ScanOrder/index.d.ts +22 -0
- package/dist/solution/ScanOrder/index.js +863 -369
- package/dist/solution/ScanOrder/types.d.ts +31 -8
- package/dist/solution/ScanOrder/utils.d.ts +26 -0
- package/dist/solution/ScanOrder/utils.js +191 -44
- package/dist/solution/VenueBooking/index.d.ts +42 -5
- package/dist/solution/VenueBooking/index.js +692 -280
- package/dist/solution/VenueBooking/types.d.ts +23 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +2 -1
- package/dist/solution/VenueBooking/utils/dateSummary.js +7 -5
- package/dist/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/dist/solution/VenueBooking/utils/resource.js +57 -21
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +33 -12
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/dist/solution/VenueBooking/utils/timeSlot.js +259 -62
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +8 -0
- package/lib/model/strategy/adapter/itemRule/adapter.js +41 -2
- package/lib/model/strategy/adapter/itemRule/examples.d.ts +15 -0
- package/lib/model/strategy/adapter/itemRule/examples.js +47 -0
- package/lib/model/strategy/adapter/itemRule/index.d.ts +1 -1
- package/lib/model/strategy/adapter/itemRule/index.js +2 -0
- package/lib/model/strategy/adapter/itemRule/type.d.ts +20 -1
- package/lib/modules/Order/index.d.ts +10 -0
- package/lib/modules/Order/index.js +40 -43
- package/lib/modules/Order/types.d.ts +13 -1
- package/lib/modules/Order/utils.d.ts +36 -1
- package/lib/modules/Order/utils.js +100 -21
- package/lib/modules/ProductList/index.js +3 -2
- package/lib/modules/Quotation/index.js +3 -0
- package/lib/modules/SalesSummary/types.d.ts +2 -1
- package/lib/modules/SalesSummary/utils.js +2 -2
- package/lib/modules/Schedule/utils.d.ts +1 -1
- package/lib/solution/ScanOrder/index.d.ts +22 -0
- package/lib/solution/ScanOrder/index.js +376 -21
- package/lib/solution/ScanOrder/types.d.ts +31 -8
- package/lib/solution/ScanOrder/utils.d.ts +26 -0
- package/lib/solution/ScanOrder/utils.js +128 -19
- package/lib/solution/VenueBooking/index.d.ts +42 -5
- package/lib/solution/VenueBooking/index.js +356 -84
- package/lib/solution/VenueBooking/types.d.ts +23 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +2 -1
- package/lib/solution/VenueBooking/utils/dateSummary.js +14 -5
- package/lib/solution/VenueBooking/utils/resource.d.ts +11 -1
- package/lib/solution/VenueBooking/utils/resource.js +15 -4
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +5 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +29 -12
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -1
- package/lib/solution/VenueBooking/utils/timeSlot.js +182 -43
- package/package.json +1 -1
|
@@ -50,6 +50,14 @@ export declare class ItemRuleAdapter implements BusinessAdapter {
|
|
|
50
50
|
* 不适用或无配置时返回 null。
|
|
51
51
|
*/
|
|
52
52
|
extractQuantityLimits(action: ActionEffect, businessData: ItemRuleBusinessData): QuantityLimitResult | null;
|
|
53
|
+
/**
|
|
54
|
+
* 计算当前提交剩余可选的最大数量。
|
|
55
|
+
*
|
|
56
|
+
* 仅在 scope='cumulative' 且存在 requiredMax 时生效:
|
|
57
|
+
* 用 requiredMax 减去 historicalItems 中目标商品的累计数量,保底 0。
|
|
58
|
+
* 其余场景返回 undefined,保持向后兼容。
|
|
59
|
+
*/
|
|
60
|
+
private calculateRemainingMax;
|
|
53
61
|
private processPrefillCart;
|
|
54
62
|
/**
|
|
55
63
|
* 根据 quantityFrom 计算预填数量
|
|
@@ -327,7 +327,8 @@ export var ItemRuleAdapter = /*#__PURE__*/function () {
|
|
|
327
327
|
var scope = config.scope,
|
|
328
328
|
quantityRules = config.quantityRules,
|
|
329
329
|
targetType = config.targetType,
|
|
330
|
-
targets = config.targets
|
|
330
|
+
targets = config.targets,
|
|
331
|
+
validationMessage = config.validationMessage;
|
|
331
332
|
if (!this.shouldEvaluateForScope(scope, (_businessData$submiss2 = businessData.submissionIndex) !== null && _businessData$submiss2 !== void 0 ? _businessData$submiss2 : 0)) {
|
|
332
333
|
return null;
|
|
333
334
|
}
|
|
@@ -373,18 +374,61 @@ export var ItemRuleAdapter = /*#__PURE__*/function () {
|
|
|
373
374
|
} finally {
|
|
374
375
|
_iterator4.f();
|
|
375
376
|
}
|
|
377
|
+
var remainingMax = this.calculateRemainingMax(scope, requiredMax, targets, businessData);
|
|
378
|
+
var formattedValidationMessage = this.formatValidationMessage(validationMessage, requiredMin, requiredMax, requiredExact);
|
|
376
379
|
return {
|
|
377
380
|
ruleId: action.id,
|
|
378
381
|
targetType: targetType,
|
|
379
382
|
targets: targets,
|
|
380
383
|
requiredMin: requiredMin,
|
|
381
384
|
requiredMax: requiredMax,
|
|
385
|
+
remainingMax: remainingMax,
|
|
382
386
|
requiredExact: requiredExact,
|
|
383
387
|
mustInclude: mustInclude,
|
|
384
|
-
scope: scope
|
|
388
|
+
scope: scope,
|
|
389
|
+
validationMessage: formattedValidationMessage,
|
|
390
|
+
rawValidationMessage: validationMessage
|
|
385
391
|
};
|
|
386
392
|
}
|
|
387
393
|
|
|
394
|
+
/**
|
|
395
|
+
* 计算当前提交剩余可选的最大数量。
|
|
396
|
+
*
|
|
397
|
+
* 仅在 scope='cumulative' 且存在 requiredMax 时生效:
|
|
398
|
+
* 用 requiredMax 减去 historicalItems 中目标商品的累计数量,保底 0。
|
|
399
|
+
* 其余场景返回 undefined,保持向后兼容。
|
|
400
|
+
*/
|
|
401
|
+
}, {
|
|
402
|
+
key: "calculateRemainingMax",
|
|
403
|
+
value: function calculateRemainingMax(scope, requiredMax, targets, businessData) {
|
|
404
|
+
if (scope !== 'cumulative' || typeof requiredMax !== 'number') {
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
var historicalItems = businessData.historicalItems;
|
|
408
|
+
if (!(historicalItems !== null && historicalItems !== void 0 && historicalItems.length)) {
|
|
409
|
+
return Math.max(0, requiredMax);
|
|
410
|
+
}
|
|
411
|
+
var targetIds = new Set(targets.map(function (t) {
|
|
412
|
+
return t.product_id;
|
|
413
|
+
}));
|
|
414
|
+
var historicalQty = 0;
|
|
415
|
+
var _iterator5 = _createForOfIteratorHelper(historicalItems),
|
|
416
|
+
_step5;
|
|
417
|
+
try {
|
|
418
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
419
|
+
var item = _step5.value;
|
|
420
|
+
if (targetIds.has(item.product_id)) {
|
|
421
|
+
historicalQty += item.quantity;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
} catch (err) {
|
|
425
|
+
_iterator5.e(err);
|
|
426
|
+
} finally {
|
|
427
|
+
_iterator5.f();
|
|
428
|
+
}
|
|
429
|
+
return Math.max(0, requiredMax - historicalQty);
|
|
430
|
+
}
|
|
431
|
+
|
|
388
432
|
// ============================================
|
|
389
433
|
// Prefill Cart 处理
|
|
390
434
|
// ============================================
|
|
@@ -394,11 +438,11 @@ export var ItemRuleAdapter = /*#__PURE__*/function () {
|
|
|
394
438
|
var config = action.config;
|
|
395
439
|
if (!(config !== null && config !== void 0 && config.products)) return [];
|
|
396
440
|
var results = [];
|
|
397
|
-
var
|
|
398
|
-
|
|
441
|
+
var _iterator6 = _createForOfIteratorHelper(config.products),
|
|
442
|
+
_step6;
|
|
399
443
|
try {
|
|
400
|
-
for (
|
|
401
|
-
var prefillProduct =
|
|
444
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
445
|
+
var prefillProduct = _step6.value;
|
|
402
446
|
var quantity = this.resolvePrefillQuantity(prefillProduct.quantityFrom, prefillProduct.quantity, businessData);
|
|
403
447
|
if (quantity <= 0) continue;
|
|
404
448
|
results.push({
|
|
@@ -409,9 +453,9 @@ export var ItemRuleAdapter = /*#__PURE__*/function () {
|
|
|
409
453
|
});
|
|
410
454
|
}
|
|
411
455
|
} catch (err) {
|
|
412
|
-
|
|
456
|
+
_iterator6.e(err);
|
|
413
457
|
} finally {
|
|
414
|
-
|
|
458
|
+
_iterator6.f();
|
|
415
459
|
}
|
|
416
460
|
return results;
|
|
417
461
|
}
|
|
@@ -25,6 +25,21 @@ export declare const MAX_BUNS_PER_TABLE_STRATEGY: StrategyConfig;
|
|
|
25
25
|
* - Prefill Cart: 自动添加默认锅底 x 1
|
|
26
26
|
*/
|
|
27
27
|
export declare const HOTPOT_BASE_REQUIRED_STRATEGY: StrategyConfig;
|
|
28
|
+
/**
|
|
29
|
+
* 场景:4 款锅底里任选至少 1 款,不自动预填,不限制多选上限
|
|
30
|
+
*
|
|
31
|
+
* WHEN: Always active
|
|
32
|
+
* THEN:
|
|
33
|
+
* - Quantity Check: 4 个锅底商品合计数量 >= 1 (OR 组语义)
|
|
34
|
+
*
|
|
35
|
+
* 说明:
|
|
36
|
+
* - targets 里放多个 product_id 时,ItemRuleAdapter 会把它们视为 OR 组,
|
|
37
|
+
* 仅校验「合计数量」,不会要求每款各自满足 min。
|
|
38
|
+
* - ScanOrder 工具层 buildQuantityLimitIndex 会跳过多目标规则的
|
|
39
|
+
* 单品索引,避免 UI 把组级 min 误当作每张商品卡的减号下限,
|
|
40
|
+
* 锁死用户切换锅底的操作。
|
|
41
|
+
*/
|
|
42
|
+
export declare const HOTPOT_BASE_PICK_ONE_STRATEGY: StrategyConfig;
|
|
28
43
|
/**
|
|
29
44
|
* ItemRuleEvaluator 简洁调用示例
|
|
30
45
|
*
|
|
@@ -205,7 +205,74 @@ export var HOTPOT_BASE_REQUIRED_STRATEGY = {
|
|
|
205
205
|
};
|
|
206
206
|
|
|
207
207
|
// ============================================
|
|
208
|
-
// 示例 4
|
|
208
|
+
// 示例 4:锅底四选一(Multi-target OR 组至少 1 份)
|
|
209
|
+
// ============================================
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 场景:4 款锅底里任选至少 1 款,不自动预填,不限制多选上限
|
|
213
|
+
*
|
|
214
|
+
* WHEN: Always active
|
|
215
|
+
* THEN:
|
|
216
|
+
* - Quantity Check: 4 个锅底商品合计数量 >= 1 (OR 组语义)
|
|
217
|
+
*
|
|
218
|
+
* 说明:
|
|
219
|
+
* - targets 里放多个 product_id 时,ItemRuleAdapter 会把它们视为 OR 组,
|
|
220
|
+
* 仅校验「合计数量」,不会要求每款各自满足 min。
|
|
221
|
+
* - ScanOrder 工具层 buildQuantityLimitIndex 会跳过多目标规则的
|
|
222
|
+
* 单品索引,避免 UI 把组级 min 误当作每张商品卡的减号下限,
|
|
223
|
+
* 锁死用户切换锅底的操作。
|
|
224
|
+
*/
|
|
225
|
+
export var HOTPOT_BASE_PICK_ONE_STRATEGY = {
|
|
226
|
+
metadata: {
|
|
227
|
+
id: 'RULE_HOTPOT_BASE_PICK_ONE',
|
|
228
|
+
name: {
|
|
229
|
+
'zh-CN': '锅底必选(四选一)',
|
|
230
|
+
en: 'Hotpot base required (pick any)'
|
|
231
|
+
},
|
|
232
|
+
type: 'item_rule',
|
|
233
|
+
description: {
|
|
234
|
+
'zh-CN': '4 款锅底任选至少 1 份',
|
|
235
|
+
en: 'Pick at least 1 hotpot base from the available options'
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
conditions: {
|
|
239
|
+
operator: 'and',
|
|
240
|
+
rules: [],
|
|
241
|
+
actionIds: ['quantity_check_hotpot_base_group']
|
|
242
|
+
},
|
|
243
|
+
actions: [{
|
|
244
|
+
id: 'quantity_check_hotpot_base_group',
|
|
245
|
+
type: ITEM_RULE_ACTION_TYPES.QUANTITY_CHECK,
|
|
246
|
+
value: null,
|
|
247
|
+
target: 'cart',
|
|
248
|
+
priority: 10,
|
|
249
|
+
config: {
|
|
250
|
+
targetType: 'product',
|
|
251
|
+
targets: [{
|
|
252
|
+
product_id: 30001
|
|
253
|
+
}, {
|
|
254
|
+
product_id: 30002
|
|
255
|
+
}, {
|
|
256
|
+
product_id: 30003
|
|
257
|
+
}, {
|
|
258
|
+
product_id: 30004
|
|
259
|
+
}],
|
|
260
|
+
quantityRules: [{
|
|
261
|
+
comparison: 'minimum',
|
|
262
|
+
source: 'fixed',
|
|
263
|
+
value: 1
|
|
264
|
+
}],
|
|
265
|
+
scope: 'first_submission_only',
|
|
266
|
+
validationMessage: {
|
|
267
|
+
'zh-CN': '请至少选择 {min} 款锅底',
|
|
268
|
+
en: 'Please select at least {min} hotpot base'
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}]
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// ============================================
|
|
275
|
+
// 示例 5:ItemRuleEvaluator 用法(简洁调用 + 完整 Demo)
|
|
209
276
|
// ============================================
|
|
210
277
|
|
|
211
278
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ItemRuleEvaluator } from './evaluator';
|
|
2
2
|
export { ItemRuleAdapter } from './adapter';
|
|
3
3
|
export { default } from './adapter';
|
|
4
|
-
export { MIN_CONDIMENT_PER_PERSON_STRATEGY, MAX_BUNS_PER_TABLE_STRATEGY, HOTPOT_BASE_REQUIRED_STRATEGY, quickUseItemRuleEvaluator, runItemRuleEvaluatorDemo, } from './examples';
|
|
4
|
+
export { MIN_CONDIMENT_PER_PERSON_STRATEGY, MAX_BUNS_PER_TABLE_STRATEGY, HOTPOT_BASE_REQUIRED_STRATEGY, HOTPOT_BASE_PICK_ONE_STRATEGY, quickUseItemRuleEvaluator, runItemRuleEvaluatorDemo, } from './examples';
|
|
5
5
|
export * from './type';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ItemRuleEvaluator } from "./evaluator";
|
|
2
2
|
export { ItemRuleAdapter } from "./adapter";
|
|
3
3
|
export { default } from "./adapter";
|
|
4
|
-
export { MIN_CONDIMENT_PER_PERSON_STRATEGY, MAX_BUNS_PER_TABLE_STRATEGY, HOTPOT_BASE_REQUIRED_STRATEGY, quickUseItemRuleEvaluator, runItemRuleEvaluatorDemo } from "./examples";
|
|
4
|
+
export { MIN_CONDIMENT_PER_PERSON_STRATEGY, MAX_BUNS_PER_TABLE_STRATEGY, HOTPOT_BASE_REQUIRED_STRATEGY, HOTPOT_BASE_PICK_ONE_STRATEGY, quickUseItemRuleEvaluator, runItemRuleEvaluatorDemo } from "./examples";
|
|
5
5
|
export * from "./type";
|
|
@@ -180,14 +180,33 @@ export interface QuantityLimitResult {
|
|
|
180
180
|
targets: TargetItem[];
|
|
181
181
|
/** 要求的最小数量 */
|
|
182
182
|
requiredMin?: number;
|
|
183
|
-
/**
|
|
183
|
+
/** 要求的最大数量(规则配置的原始上限,用于 UI 文案展示) */
|
|
184
184
|
requiredMax?: number;
|
|
185
|
+
/**
|
|
186
|
+
* 当前提交剩余可选的最大数量。
|
|
187
|
+
*
|
|
188
|
+
* 仅在 scope='cumulative' 且存在 requiredMax 时计算:
|
|
189
|
+
* remainingMax = max(0, requiredMax - historicalItems 中目标商品累计数量)
|
|
190
|
+
*
|
|
191
|
+
* 非 cumulative 场景不设置此字段;调用方用于限制加购上限时,
|
|
192
|
+
* 应优先读取本字段,未定义时回退到 requiredMax。
|
|
193
|
+
*/
|
|
194
|
+
remainingMax?: number;
|
|
185
195
|
/** 要求的精确数量 */
|
|
186
196
|
requiredExact?: number;
|
|
187
197
|
/** 是否必须包含 */
|
|
188
198
|
mustInclude?: boolean;
|
|
189
199
|
/** 作用范围 */
|
|
190
200
|
scope: RuleScope;
|
|
201
|
+
/**
|
|
202
|
+
* 校验失败时的提示语(已做 {min}/{max}/{exact} 占位符替换)。
|
|
203
|
+
* 当 rawValidationMessage 为多语言对象时,后端不做 locale 选择,
|
|
204
|
+
* 默认按 en → Object.values()[0] 的顺序兜底,前端可再根据自身 locale
|
|
205
|
+
* 读取 rawValidationMessage 做精确匹配。
|
|
206
|
+
*/
|
|
207
|
+
validationMessage?: string;
|
|
208
|
+
/** 原始多语言模板,前端可根据自身 locale 做二次选择 */
|
|
209
|
+
rawValidationMessage?: string | Record<string, string>;
|
|
191
210
|
}
|
|
192
211
|
/**
|
|
193
212
|
* ItemRule 评估器的完整输出结果
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// 导出评估器
|
|
2
|
+
export { PromotionEvaluator } from "./evaluator";
|
|
3
|
+
|
|
4
|
+
// 导出适配器
|
|
5
|
+
export { PromotionAdapter } from "./adapter";
|
|
6
|
+
export { default } from "./adapter";
|
|
7
|
+
|
|
8
|
+
// 导出策略配置示例常量
|
|
9
|
+
export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY } from "./examples";
|
|
@@ -2,6 +2,7 @@ import { Module, PisellCore, ModuleOptions } from '../../types';
|
|
|
2
2
|
import { BaseModule } from '../BaseModule';
|
|
3
3
|
import { OrderModuleAPI, CommitOrderParams, SubmitScanOrderParams, ScanOrderMoreParams, CheckoutOrderParams } from './types';
|
|
4
4
|
import { CartItem } from '../Cart/types';
|
|
5
|
+
import { type SubmitPayloadEnhancer } from './utils';
|
|
5
6
|
import type { ScanOrderOrderProduct, ScanOrderOrderProductIdentity, ScanOrderSummary, ScanOrderTempOrder } from '../../solution/ScanOrder/types';
|
|
6
7
|
import type { Discount } from '../Discount/types';
|
|
7
8
|
import { UnavailableReason } from '../Rules/types';
|
|
@@ -57,6 +58,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
57
58
|
persistTempOrder(): void;
|
|
58
59
|
private createDefaultTempOrderInstance;
|
|
59
60
|
ensureTempOrder(): ScanOrderTempOrder;
|
|
61
|
+
restoreOrder(): ScanOrderTempOrder;
|
|
60
62
|
getTempOrder(): ScanOrderTempOrder | null;
|
|
61
63
|
addNewOrder(): Promise<ScanOrderTempOrder>;
|
|
62
64
|
getOrderProducts(): ScanOrderOrderProduct[];
|
|
@@ -66,6 +68,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
66
68
|
}): Promise<ScanOrderSummary | null>;
|
|
67
69
|
getScanOrderSummary(): Promise<ScanOrderSummary>;
|
|
68
70
|
updateTempOrderNote(note: string): string;
|
|
71
|
+
updateTempOrderBuzzer(buzzer: string): string;
|
|
69
72
|
updateTempOrderContactsInfo(contactsInfo: any[]): any[];
|
|
70
73
|
addProductToOrder(product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity): Promise<ScanOrderOrderProduct[]>;
|
|
71
74
|
updateProductInOrder(params: {
|
|
@@ -76,6 +79,11 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
76
79
|
removeProductFromOrder(identity: ScanOrderOrderProductIdentity): Promise<ScanOrderOrderProduct[]>;
|
|
77
80
|
submitTempOrder<T = any>(params?: {
|
|
78
81
|
cacheId?: string;
|
|
82
|
+
platform?: string;
|
|
83
|
+
businessCode?: string;
|
|
84
|
+
channel?: string;
|
|
85
|
+
type?: string;
|
|
86
|
+
enhancePayload?: SubmitPayloadEnhancer;
|
|
79
87
|
}): Promise<T>;
|
|
80
88
|
createOrder(params: CommitOrderParams['query']): {
|
|
81
89
|
type: "virtual" | "appointment_booking";
|
|
@@ -108,4 +116,6 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
108
116
|
createOrderByCheckout(params: CheckoutOrderParams): Promise<any>;
|
|
109
117
|
submitScanOrder<T = any>(params: SubmitScanOrderParams): Promise<T>;
|
|
110
118
|
scanOrderMore<T = any>(params: ScanOrderMoreParams): Promise<T>;
|
|
119
|
+
getOrderInfoByRemote(order_id: number): Promise<any>;
|
|
120
|
+
getLastOrderInfo(): Record<string, any> | undefined;
|
|
111
121
|
}
|
|
@@ -25,7 +25,7 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
|
|
|
25
25
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
26
26
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
27
27
|
import { BaseModule } from "../BaseModule";
|
|
28
|
-
import { generateDuration, getAllDiscountList, mergeRelationForms, buildSubmitPayload, createDefaultTempOrder, createEmptySummary, formatDateTime, formatV1Product, isTempOrder } from "./utils";
|
|
28
|
+
import { generateDuration, getAllDiscountList, mergeRelationForms, buildSubmitPayload, createDefaultTempOrder, createDefaultOrderRulesHooks, createEmptySummary, formatDateTime, formatV1Product, isTempOrder } from "./utils";
|
|
29
29
|
import { isNormalProduct } from "../Product/utils";
|
|
30
30
|
import dayjs from 'dayjs';
|
|
31
31
|
import { getProductIdentityIndex, getSafeProductNum, isIdentityMatch, normalizeOrderProduct } from "../../solution/ScanOrder/utils";
|
|
@@ -173,42 +173,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
173
173
|
}, {
|
|
174
174
|
key: "createDefaultRulesHooks",
|
|
175
175
|
value: function createDefaultRulesHooks() {
|
|
176
|
-
return
|
|
177
|
-
getProduct: function getProduct(product) {
|
|
178
|
-
var _product$_origin, _product$_origin2, _product$_origin3, _product$_origin4;
|
|
179
|
-
return {
|
|
180
|
-
id: product.product_id,
|
|
181
|
-
_id: product.identity_key ? "".concat(product.product_id, "_").concat(product.product_variant_id, "_").concat(product.identity_key) : "".concat(product.product_id, "_").concat(product.product_variant_id),
|
|
182
|
-
price: product.selling_price,
|
|
183
|
-
total: new Decimal(product.payment_price || product.selling_price || 0).times(product.num || 1).toNumber(),
|
|
184
|
-
origin_total: new Decimal(product.original_price || product.selling_price || 0).times(product.num || 1).toNumber(),
|
|
185
|
-
original_price: product.original_price,
|
|
186
|
-
quantity: product.num || 1,
|
|
187
|
-
num: product.num || 1,
|
|
188
|
-
discount_list: product.discount_list || [],
|
|
189
|
-
bundle: product.product_bundle || [],
|
|
190
|
-
booking_id: ((_product$_origin = product._origin) === null || _product$_origin === void 0 ? void 0 : _product$_origin.booking_id) || null,
|
|
191
|
-
isClient: false,
|
|
192
|
-
isManualDiscount: ((_product$_origin2 = product._origin) === null || _product$_origin2 === void 0 ? void 0 : _product$_origin2.isManualDiscount) || false,
|
|
193
|
-
holder_id: (_product$_origin3 = product._origin) === null || _product$_origin3 === void 0 ? void 0 : _product$_origin3.holder_id,
|
|
194
|
-
startDate: (_product$_origin4 = product._origin) === null || _product$_origin4 === void 0 ? void 0 : _product$_origin4.startDate
|
|
195
|
-
};
|
|
196
|
-
},
|
|
197
|
-
setProduct: function setProduct(product, values) {
|
|
198
|
-
var _values$discount_list, _values$quantity, _values$bundle;
|
|
199
|
-
return _objectSpread(_objectSpread({}, product), {}, {
|
|
200
|
-
selling_price: values.price !== undefined ? String(values.price) : product.selling_price,
|
|
201
|
-
payment_price: values.total !== undefined ? String(values.total) : product.payment_price,
|
|
202
|
-
original_price: values.original_price !== undefined ? String(values.original_price) : product.original_price,
|
|
203
|
-
discount_list: (_values$discount_list = values.discount_list) !== null && _values$discount_list !== void 0 ? _values$discount_list : product.discount_list,
|
|
204
|
-
num: (_values$quantity = values.quantity) !== null && _values$quantity !== void 0 ? _values$quantity : product.num,
|
|
205
|
-
product_bundle: (_values$bundle = values.bundle) !== null && _values$bundle !== void 0 ? _values$bundle : product.product_bundle,
|
|
206
|
-
metadata: _objectSpread(_objectSpread({}, product.metadata || {}), values.main_product_selling_price !== undefined ? {
|
|
207
|
-
main_product_selling_price: String(values.main_product_selling_price)
|
|
208
|
-
} : {})
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
};
|
|
176
|
+
return createDefaultOrderRulesHooks();
|
|
212
177
|
}
|
|
213
178
|
|
|
214
179
|
// ─── Discount: 公共 API ───
|
|
@@ -360,9 +325,12 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
360
325
|
}, {
|
|
361
326
|
key: "applyDiscount",
|
|
362
327
|
value: function applyDiscount() {
|
|
363
|
-
var
|
|
328
|
+
var _this$store$discount6, _tempOrder$holder3, _tempOrder$holder4, _tempOrder$summary2;
|
|
364
329
|
var tempOrder = this.store.tempOrder;
|
|
365
|
-
|
|
330
|
+
// 任意 products CRUD 后都应当重算 discount 状态;即使 products 为空,
|
|
331
|
+
// 也需要让 Rules.calcDiscount 把 DiscountModule 的 isSelected / isAvailable /
|
|
332
|
+
// appliedProductDetails / savedAmount 以及 tempOrder.discount_list 复位。
|
|
333
|
+
if (!tempOrder) return;
|
|
366
334
|
var rulesModule = this.store.rules;
|
|
367
335
|
if (!rulesModule) return;
|
|
368
336
|
var discountList = ((_this$store$discount6 = this.store.discount) === null || _this$store$discount6 === void 0 ? void 0 : _this$store$discount6.getDiscountList()) || [];
|
|
@@ -452,6 +420,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
452
420
|
this.persistTempOrder();
|
|
453
421
|
return newOrder;
|
|
454
422
|
}
|
|
423
|
+
}, {
|
|
424
|
+
key: "restoreOrder",
|
|
425
|
+
value: function restoreOrder() {
|
|
426
|
+
var freshTempOrder = this.createDefaultTempOrderInstance();
|
|
427
|
+
this.store.tempOrder = freshTempOrder;
|
|
428
|
+
this.persistTempOrder();
|
|
429
|
+
return freshTempOrder;
|
|
430
|
+
}
|
|
455
431
|
}, {
|
|
456
432
|
key: "getTempOrder",
|
|
457
433
|
value: function getTempOrder() {
|
|
@@ -593,6 +569,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
593
569
|
this.persistTempOrder();
|
|
594
570
|
return tempOrder.note;
|
|
595
571
|
}
|
|
572
|
+
}, {
|
|
573
|
+
key: "updateTempOrderBuzzer",
|
|
574
|
+
value: function updateTempOrderBuzzer(buzzer) {
|
|
575
|
+
var tempOrder = this.ensureTempOrder();
|
|
576
|
+
tempOrder.buzzer = String(buzzer || '');
|
|
577
|
+
this.persistTempOrder();
|
|
578
|
+
return tempOrder.buzzer;
|
|
579
|
+
}
|
|
596
580
|
}, {
|
|
597
581
|
key: "updateTempOrderContactsInfo",
|
|
598
582
|
value: function updateTempOrderContactsInfo(contactsInfo) {
|
|
@@ -742,7 +726,12 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
742
726
|
effectiveCacheId = (_params$cacheId = params === null || params === void 0 ? void 0 : params.cacheId) !== null && _params$cacheId !== void 0 ? _params$cacheId : this.cacheId;
|
|
743
727
|
payload = buildSubmitPayload({
|
|
744
728
|
tempOrder: tempOrder,
|
|
745
|
-
cacheId: effectiveCacheId
|
|
729
|
+
cacheId: effectiveCacheId,
|
|
730
|
+
platform: params === null || params === void 0 ? void 0 : params.platform,
|
|
731
|
+
businessCode: params === null || params === void 0 ? void 0 : params.businessCode,
|
|
732
|
+
channel: params === null || params === void 0 ? void 0 : params.channel,
|
|
733
|
+
type: params === null || params === void 0 ? void 0 : params.type,
|
|
734
|
+
enhance: params === null || params === void 0 ? void 0 : params.enhancePayload
|
|
746
735
|
});
|
|
747
736
|
if (!tempOrder.order_id) {
|
|
748
737
|
_context10.next = 12;
|
|
@@ -1101,7 +1090,42 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
|
|
|
1101
1090
|
return _scanOrderMore.apply(this, arguments);
|
|
1102
1091
|
}
|
|
1103
1092
|
return scanOrderMore;
|
|
1093
|
+
}() // TODO 获取详情的接口
|
|
1094
|
+
}, {
|
|
1095
|
+
key: "getOrderInfoByRemote",
|
|
1096
|
+
value: function () {
|
|
1097
|
+
var _getOrderInfoByRemote = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15(order_id) {
|
|
1098
|
+
var res;
|
|
1099
|
+
return _regeneratorRuntime().wrap(function _callee15$(_context15) {
|
|
1100
|
+
while (1) switch (_context15.prev = _context15.next) {
|
|
1101
|
+
case 0:
|
|
1102
|
+
_context15.next = 2;
|
|
1103
|
+
return this.request.get("/order/sales/".concat(order_id), {
|
|
1104
|
+
with: ['products', 'scheduleEvents']
|
|
1105
|
+
});
|
|
1106
|
+
case 2:
|
|
1107
|
+
res = _context15.sent;
|
|
1108
|
+
if (res.code === 200 && this.store.tempOrder) {
|
|
1109
|
+
this.store.tempOrder.lastOrderInfo = res.data;
|
|
1110
|
+
}
|
|
1111
|
+
return _context15.abrupt("return", res);
|
|
1112
|
+
case 5:
|
|
1113
|
+
case "end":
|
|
1114
|
+
return _context15.stop();
|
|
1115
|
+
}
|
|
1116
|
+
}, _callee15, this);
|
|
1117
|
+
}));
|
|
1118
|
+
function getOrderInfoByRemote(_x15) {
|
|
1119
|
+
return _getOrderInfoByRemote.apply(this, arguments);
|
|
1120
|
+
}
|
|
1121
|
+
return getOrderInfoByRemote;
|
|
1104
1122
|
}()
|
|
1123
|
+
}, {
|
|
1124
|
+
key: "getLastOrderInfo",
|
|
1125
|
+
value: function getLastOrderInfo() {
|
|
1126
|
+
var _this$store;
|
|
1127
|
+
return (_this$store = this.store) === null || _this$store === void 0 || (_this$store = _this$store.tempOrder) === null || _this$store === void 0 ? void 0 : _this$store.lastOrderInfo;
|
|
1128
|
+
}
|
|
1105
1129
|
}], [{
|
|
1106
1130
|
key: "populateSavedAmounts",
|
|
1107
1131
|
value:
|
|
@@ -3,6 +3,7 @@ import type { ScanOrderTempOrder, ScanOrderOrderProduct, ScanOrderOrderProductId
|
|
|
3
3
|
import type { DiscountModule } from '../Discount';
|
|
4
4
|
import type { RulesModule } from '../Rules';
|
|
5
5
|
import type { Discount } from '../Discount/types';
|
|
6
|
+
import type { SubmitPayloadEnhancer } from './utils';
|
|
6
7
|
export declare enum OrderHooks {
|
|
7
8
|
OnOrderCreate = "order:onOrderCreate",
|
|
8
9
|
OnOrderUpdate = "order:onOrderUpdate",
|
|
@@ -68,10 +69,12 @@ export interface SubmitScanOrderBooking {
|
|
|
68
69
|
start_time?: string;
|
|
69
70
|
end_time?: string;
|
|
70
71
|
metadata?: Record<string, any>;
|
|
72
|
+
resources?: Array<Record<string, any>>;
|
|
73
|
+
product_uid?: string;
|
|
71
74
|
}
|
|
72
75
|
export interface SubmitScanOrderFormRecord {
|
|
73
76
|
form_id: number | string;
|
|
74
|
-
|
|
77
|
+
form_record_id: number | string;
|
|
75
78
|
}
|
|
76
79
|
export interface SubmitScanOrderParams {
|
|
77
80
|
url?: string;
|
|
@@ -107,6 +110,8 @@ export interface SubmitScanOrderParams {
|
|
|
107
110
|
shop_discount: string;
|
|
108
111
|
surcharge_fee: string;
|
|
109
112
|
note: string;
|
|
113
|
+
delivery_type?: string;
|
|
114
|
+
table_number?: Record<string, any>;
|
|
110
115
|
schedule_date: string;
|
|
111
116
|
created_at?: string;
|
|
112
117
|
products: SubmitScanOrderProduct[];
|
|
@@ -195,12 +200,14 @@ export interface OrderModuleAPI {
|
|
|
195
200
|
getTempOrder: () => ScanOrderTempOrder | null;
|
|
196
201
|
ensureTempOrder: () => ScanOrderTempOrder;
|
|
197
202
|
addNewOrder: () => Promise<ScanOrderTempOrder>;
|
|
203
|
+
restoreOrder: () => ScanOrderTempOrder;
|
|
198
204
|
getOrderProducts: () => ScanOrderOrderProduct[];
|
|
199
205
|
getScanOrderSummary: () => Promise<ScanOrderSummary>;
|
|
200
206
|
recalculateSummary: (options?: {
|
|
201
207
|
createIfMissing?: boolean;
|
|
202
208
|
}) => Promise<ScanOrderSummary | null>;
|
|
203
209
|
updateTempOrderNote: (note: string) => string;
|
|
210
|
+
updateTempOrderBuzzer: (buzzer: string) => string;
|
|
204
211
|
updateTempOrderContactsInfo: (contactsInfo: any[]) => any[];
|
|
205
212
|
addProductToOrder: (product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity) => Promise<ScanOrderOrderProduct[]>;
|
|
206
213
|
updateProductInOrder: (params: {
|
|
@@ -212,6 +219,11 @@ export interface OrderModuleAPI {
|
|
|
212
219
|
persistTempOrder: () => void;
|
|
213
220
|
submitTempOrder: <T = any>(params?: {
|
|
214
221
|
cacheId?: string;
|
|
222
|
+
platform?: string;
|
|
223
|
+
businessCode?: string;
|
|
224
|
+
channel?: string;
|
|
225
|
+
type?: string;
|
|
226
|
+
enhancePayload?: SubmitPayloadEnhancer;
|
|
215
227
|
}) => Promise<T>;
|
|
216
228
|
loadDiscountConfig: (params: {
|
|
217
229
|
customerId: number;
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import { CartItem } from "../Cart";
|
|
2
2
|
import type { ScanOrderSubmitPayload, ScanOrderSubmitProduct, ScanOrderSummary, ScanOrderTempOrder } from '../../solution/ScanOrder/types';
|
|
3
|
+
import type { RulesParamsHooks } from '../Rules/types';
|
|
4
|
+
/**
|
|
5
|
+
* OrderModule 默认 Rules 钩子工厂。
|
|
6
|
+
*
|
|
7
|
+
* 价格语义约定(订单域):
|
|
8
|
+
* - `selling_price`:券后单品单价(实际成交单价)。初次加购 = `original_price`;券应用后由 Rules 引擎更新。
|
|
9
|
+
* - `original_price`:券前单品单价(店铺售价)。不承载后台划线价语义。
|
|
10
|
+
* - `payment_price`:已从内部字段移除;只在出站 payload 中由 `selling_price` 派生以兼容后端。
|
|
11
|
+
*
|
|
12
|
+
* Rules 钩子契约:
|
|
13
|
+
* - `getProduct.total` = `selling_price × num`(当前成交总价)
|
|
14
|
+
* - `getProduct.origin_total` = `original_price × num`(券前总价)
|
|
15
|
+
* - `setProduct` 写回 `selling_price` 的优先级:
|
|
16
|
+
* 1. `values.main_product_selling_price`(券应用分支,per-unit 券后主价)
|
|
17
|
+
* 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
|
|
18
|
+
* 3. `values.total / num`(仅当 Rules 只给出总价时的兜底)
|
|
19
|
+
*
|
|
20
|
+
* 导出为纯函数方便单测直接驱动钩子,不依赖 OrderModule 实例。
|
|
21
|
+
*/
|
|
22
|
+
export declare function createDefaultOrderRulesHooks(): RulesParamsHooks;
|
|
3
23
|
/**
|
|
4
24
|
* 通过 session 类商品的开始时间结束时间生成商品的时长
|
|
5
25
|
* @param {CartItem} cartItem
|
|
@@ -28,14 +48,29 @@ export declare function formatDateTime(date: Date): string;
|
|
|
28
48
|
export declare function normalizeSubmitBooking<T extends {
|
|
29
49
|
metadata?: Record<string, any>;
|
|
30
50
|
}>(booking: T): T;
|
|
51
|
+
/** 提交用人数:有限且为正则向下取整,否则为 1 */
|
|
52
|
+
export declare function normalizeSubmitCollectPaxValue(value: unknown): number;
|
|
53
|
+
/** 从临时订单 metadata 解析合成 booking 的 collect_pax */
|
|
54
|
+
export declare function resolveSubmitCollectPax(tempOrder: ScanOrderTempOrder): number;
|
|
31
55
|
export declare function createDefaultTempOrder(params: {
|
|
32
56
|
now: string;
|
|
33
57
|
summary?: ScanOrderSummary;
|
|
34
58
|
}): ScanOrderTempOrder;
|
|
59
|
+
export interface SubmitPayloadEnhancerContext {
|
|
60
|
+
tempOrder: ScanOrderTempOrder;
|
|
61
|
+
bookingUuid: string;
|
|
62
|
+
now: Date;
|
|
63
|
+
}
|
|
64
|
+
export type SubmitPayloadEnhancer = (payload: ScanOrderSubmitPayload, ctx: SubmitPayloadEnhancerContext) => ScanOrderSubmitPayload;
|
|
35
65
|
export declare function buildSubmitPayload(params: {
|
|
36
66
|
tempOrder: ScanOrderTempOrder;
|
|
37
67
|
cacheId?: string;
|
|
38
68
|
now?: Date;
|
|
69
|
+
platform?: string;
|
|
70
|
+
businessCode?: string;
|
|
71
|
+
channel?: string;
|
|
72
|
+
type?: string;
|
|
73
|
+
enhance?: SubmitPayloadEnhancer;
|
|
39
74
|
}): ScanOrderSubmitPayload;
|
|
40
75
|
export declare function formatV1Product(products: ScanOrderSubmitProduct[]): {
|
|
41
76
|
bundle: any[];
|
|
@@ -43,7 +78,7 @@ export declare function formatV1Product(products: ScanOrderSubmitProduct[]): {
|
|
|
43
78
|
option: any[];
|
|
44
79
|
product_id: number | null;
|
|
45
80
|
product_variant_id: number;
|
|
46
|
-
|
|
81
|
+
num: number;
|
|
47
82
|
rowKey: number | null;
|
|
48
83
|
session: null;
|
|
49
84
|
unique: string;
|