@pisell/pisellos 0.0.511 → 0.0.513
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/promotion/index.js +0 -9
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +79 -58
- package/dist/modules/Order/types.d.ts +11 -0
- package/dist/modules/Order/utils.d.ts +63 -11
- package/dist/modules/Order/utils.js +242 -43
- package/dist/modules/SalesSummary/utils.js +36 -69
- package/dist/modules/Summary/utils.js +6 -21
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/ScanOrder/index.d.ts +3 -0
- package/dist/solution/ScanOrder/index.js +558 -498
- package/dist/solution/ScanOrder/types.d.ts +29 -2
- package/dist/solution/ScanOrder/utils.d.ts +18 -2
- package/dist/solution/ScanOrder/utils.js +111 -29
- package/dist/solution/VenueBooking/index.js +35 -27
- package/lib/model/strategy/adapter/promotion/index.js +0 -49
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +20 -7
- package/lib/modules/Order/types.d.ts +11 -0
- package/lib/modules/Order/utils.d.ts +63 -11
- package/lib/modules/Order/utils.js +149 -17
- package/lib/modules/SalesSummary/utils.js +16 -48
- package/lib/modules/Summary/utils.js +4 -18
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/ScanOrder/index.d.ts +3 -0
- package/lib/solution/ScanOrder/index.js +30 -4
- package/lib/solution/ScanOrder/types.d.ts +29 -2
- package/lib/solution/ScanOrder/utils.d.ts +18 -2
- package/lib/solution/ScanOrder/utils.js +66 -15
- package/lib/solution/VenueBooking/index.js +13 -6
- package/package.json +1 -1
|
@@ -39,14 +39,39 @@ export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
|
|
|
39
39
|
order_detail_id: number | null;
|
|
40
40
|
num: number;
|
|
41
41
|
product_option_item: any[];
|
|
42
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* 券后 **行 composite 单价** = `metadata.main_product_selling_price`
|
|
44
|
+
* + Σ((bundle.bundle_selling_price ?? bundle.price) × (bundle.num ?? 1))
|
|
45
|
+
*
|
|
46
|
+
* 新语义 v2 下 `metadata.main_product_selling_price` 已经**含 option**、含主商品折扣,
|
|
47
|
+
* 因此本字段不再叠加 option。未应用券时等同 `original_price`。
|
|
48
|
+
* Rules 钩子、主商品计税、Summary 统一读 metadata,不以此字段反推。
|
|
49
|
+
*/
|
|
43
50
|
selling_price: string;
|
|
44
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* 券前 **行 composite 单价** = `metadata.main_product_original_price`
|
|
53
|
+
* + Σ(bundle 原价 × num)
|
|
54
|
+
*
|
|
55
|
+
* 新语义 v2 下 `metadata.main_product_original_price` 已经**含 option**、不含折扣。
|
|
56
|
+
* 不承载后台划线价语义。
|
|
57
|
+
*/
|
|
45
58
|
original_price: string;
|
|
46
59
|
tax_fee: string;
|
|
47
60
|
is_charge_tax: number;
|
|
48
61
|
discount_list: any[];
|
|
49
62
|
product_bundle: any[];
|
|
63
|
+
/**
|
|
64
|
+
* 行级扩展 metadata。价格相关的权威字段:
|
|
65
|
+
*
|
|
66
|
+
* - `source_product_price`:主商品/variant 基础价(已应用报价单),**不含 option、不含折扣**。
|
|
67
|
+
* 是派生 `main_product_*` 的唯一源。variant 分支优先读 `metadata.origin.variant[vid].price`。
|
|
68
|
+
* - `main_product_original_price` = `source_product_price + Σ(option.price × option.num)`,
|
|
69
|
+
* **含 option、不含折扣**。
|
|
70
|
+
* - `main_product_selling_price` = `main_product_original_price − 主商品券 per-unit amount`,
|
|
71
|
+
* **含 option、含主商品折扣**。Rules 钩子 / Summary / 计税均以此为主商品权威源。
|
|
72
|
+
* - `price_schema_version`(当前 = 2):schema 版本 sentinel,用于跨端协商价格口径、
|
|
73
|
+
* 区分 v1 旧缓存以便 `normalizeOrderProduct` 触发迁移。
|
|
74
|
+
*/
|
|
50
75
|
metadata: Record<string, any>;
|
|
51
76
|
/** 商品行备注(如顾客对单品的特殊要求) */
|
|
52
77
|
note?: string;
|
|
@@ -68,6 +93,8 @@ export interface ScanOrderSubmitProduct extends Omit<ScanOrderOrderProduct, '_or
|
|
|
68
93
|
/**
|
|
69
94
|
* 出站兼容字段:SDK 内部不再消费 payment_price,
|
|
70
95
|
* 仅在提交后端时由 selling_price 派生,保持原有后端契约。
|
|
96
|
+
* 新语义 v2 下 selling_price 是 composite(含 option、含 bundle、含主商品折扣),
|
|
97
|
+
* 因此 payment_price 同样是 composite。
|
|
71
98
|
*/
|
|
72
99
|
payment_price: string;
|
|
73
100
|
}
|
|
@@ -108,10 +108,26 @@ export declare function isIdentityMatch(a: ScanOrderOrderProductIdentity, b: Sca
|
|
|
108
108
|
*/
|
|
109
109
|
export declare function getProductIdentityIndex(products: ScanOrderOrderProduct[], identity: ScanOrderOrderProductIdentity): number;
|
|
110
110
|
/**
|
|
111
|
-
*
|
|
111
|
+
* 对外部传入的商品对象做归一化(v2 composite 语义):
|
|
112
112
|
* - 补全可选字段默认值(未传则使用兜底值,避免后续计算时因 undefined 导致异常)
|
|
113
113
|
* - 对 num 调用 getSafeProductNum 做安全处理
|
|
114
114
|
* - 保留 _origin 供后续业务流程(如促销规则)使用
|
|
115
|
+
*
|
|
116
|
+
* 价格字段语义(metadata 权威源 + composite 派生):
|
|
117
|
+
* - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),**不含 option**、
|
|
118
|
+
* **不含折扣**。是推导 main_product_* 的起点。variant 分支优先读 `metadata.origin.variant[vid].price`。
|
|
119
|
+
* - `metadata.main_product_original_price`:`source + Σ(option.price × option.num)`,**含 option**、
|
|
120
|
+
* **不含折扣**。
|
|
121
|
+
* - `metadata.main_product_selling_price`:`main_product_original_price - 主商品券 per-unit amount`,
|
|
122
|
+
* **含 option**、**含折扣**。
|
|
123
|
+
* - 行级 `selling_price` = `main_product_selling_price + Σ(bundle_selling_price × num)`。
|
|
124
|
+
* - 行级 `original_price` = `main_product_original_price + Σ(bundle 原价 × num)`。
|
|
125
|
+
*
|
|
126
|
+
* 迁移与幂等:
|
|
127
|
+
* - `metadata.price_schema_version === 2` → 已新语义归一化,保留 main_product_* 原值(保留折扣)。
|
|
128
|
+
* - 其它情况(v1 / 缺字段 / 无 metadata)→ 按"main_product_selling_price 曾是 main-only"的旧约定
|
|
129
|
+
* 反推 legacyDiscount,再以新 source + options 基准重算。最终统一打上 `price_schema_version: 2`。
|
|
130
|
+
* - 因此多次 normalize 不会重复叠加 option/bundle。
|
|
115
131
|
*/
|
|
116
132
|
export declare function normalizeOrderProduct(product: Partial<ScanOrderOrderProduct> & ScanOrderOrderProductIdentity): ScanOrderOrderProduct;
|
|
117
133
|
/**
|
|
@@ -127,7 +143,7 @@ export declare function hasCustomCapacityProduct(products: ProductData[]): boole
|
|
|
127
143
|
/**
|
|
128
144
|
* 根据预约规则商品的 resource.type 计算桌台是否已被"占满"。
|
|
129
145
|
* - single:只要有 `lastOrderId` 即视为占用
|
|
130
|
-
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和
|
|
146
|
+
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和 >= 总容量
|
|
131
147
|
* - 其他('capacity' / undefined):返回 false,不施加限制
|
|
132
148
|
*/
|
|
133
149
|
export declare function computeResourceIsFull(params: {
|
|
@@ -12,7 +12,8 @@ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol
|
|
|
12
12
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
13
13
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
14
14
|
import dayjs from 'dayjs';
|
|
15
|
-
import
|
|
15
|
+
import Decimal from 'decimal.js';
|
|
16
|
+
import { composeLinePrice, createUuidV4, sumOptionUnitPrice } from "../../modules/Order/utils";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* 构建金额全为 0 的空 summary。
|
|
@@ -451,13 +452,29 @@ export function getProductIdentityIndex(products, identity) {
|
|
|
451
452
|
}
|
|
452
453
|
|
|
453
454
|
/**
|
|
454
|
-
*
|
|
455
|
+
* 对外部传入的商品对象做归一化(v2 composite 语义):
|
|
455
456
|
* - 补全可选字段默认值(未传则使用兜底值,避免后续计算时因 undefined 导致异常)
|
|
456
457
|
* - 对 num 调用 getSafeProductNum 做安全处理
|
|
457
458
|
* - 保留 _origin 供后续业务流程(如促销规则)使用
|
|
459
|
+
*
|
|
460
|
+
* 价格字段语义(metadata 权威源 + composite 派生):
|
|
461
|
+
* - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),**不含 option**、
|
|
462
|
+
* **不含折扣**。是推导 main_product_* 的起点。variant 分支优先读 `metadata.origin.variant[vid].price`。
|
|
463
|
+
* - `metadata.main_product_original_price`:`source + Σ(option.price × option.num)`,**含 option**、
|
|
464
|
+
* **不含折扣**。
|
|
465
|
+
* - `metadata.main_product_selling_price`:`main_product_original_price - 主商品券 per-unit amount`,
|
|
466
|
+
* **含 option**、**含折扣**。
|
|
467
|
+
* - 行级 `selling_price` = `main_product_selling_price + Σ(bundle_selling_price × num)`。
|
|
468
|
+
* - 行级 `original_price` = `main_product_original_price + Σ(bundle 原价 × num)`。
|
|
469
|
+
*
|
|
470
|
+
* 迁移与幂等:
|
|
471
|
+
* - `metadata.price_schema_version === 2` → 已新语义归一化,保留 main_product_* 原值(保留折扣)。
|
|
472
|
+
* - 其它情况(v1 / 缺字段 / 无 metadata)→ 按"main_product_selling_price 曾是 main-only"的旧约定
|
|
473
|
+
* 反推 legacyDiscount,再以新 source + options 基准重算。最终统一打上 `price_schema_version: 2`。
|
|
474
|
+
* - 因此多次 normalize 不会重复叠加 option/bundle。
|
|
458
475
|
*/
|
|
459
476
|
export function normalizeOrderProduct(product) {
|
|
460
|
-
var _product$is_charge_ta;
|
|
477
|
+
var _metadata$origin, _variantList$find, _product$is_charge_ta;
|
|
461
478
|
var metadata = _objectSpread({}, product.metadata || {});
|
|
462
479
|
// 不透明 identity 契约:每条订单行必须带 identity_key。
|
|
463
480
|
// 调用方未传时由 SDK 自动生成 UUID,后续 update/remove 只做严格比对,避免猜测合成 key。
|
|
@@ -465,40 +482,105 @@ export function normalizeOrderProduct(product) {
|
|
|
465
482
|
if (!metadata.unique_identification_number) {
|
|
466
483
|
metadata.unique_identification_number = resolvedIdentityKey;
|
|
467
484
|
}
|
|
468
|
-
|
|
469
|
-
// selling_price:券后成交单价;original_price:券前店铺售价。
|
|
470
|
-
// 初次加购时两者相等(入口层应保证 caller 传的 original_price == selling_price);
|
|
471
|
-
// 券应用后由 Rules 引擎只改动 selling_price,保留 original_price 以便还原 / 展示划线对比。
|
|
472
|
-
// 注意:这里 caller 若显式传入了 original_price(例如 Rules 回写或单测场景),要尊重该值,
|
|
473
|
-
// 让券后状态能正确通过再次 normalize。
|
|
474
|
-
var resolvedSellingPrice = product.selling_price || '0.00';
|
|
475
|
-
var resolvedOriginalPrice = product.original_price || resolvedSellingPrice;
|
|
476
|
-
if (metadata.main_product_original_price === undefined) {
|
|
477
|
-
metadata.main_product_original_price = resolvedOriginalPrice;
|
|
478
|
-
}
|
|
479
|
-
if (metadata.main_product_selling_price === undefined) {
|
|
480
|
-
metadata.main_product_selling_price = resolvedSellingPrice;
|
|
481
|
-
}
|
|
482
|
-
if (metadata.source_product_price === undefined) {
|
|
483
|
-
var _ref2, _product$_origin$pric, _product$_origin, _product$_origin2;
|
|
484
|
-
metadata.source_product_price = (_ref2 = (_product$_origin$pric = (_product$_origin = product._origin) === null || _product$_origin === void 0 ? void 0 : _product$_origin.price) !== null && _product$_origin$pric !== void 0 ? _product$_origin$pric : (_product$_origin2 = product._origin) === null || _product$_origin2 === void 0 ? void 0 : _product$_origin2.base_price) !== null && _ref2 !== void 0 ? _ref2 : resolvedSellingPrice;
|
|
485
|
-
}
|
|
486
485
|
var normalizedBundle = (product.product_bundle || []).map(function (item) {
|
|
487
|
-
var
|
|
486
|
+
var _ref2, _item$bundle_selling_, _ref3, _ref4, _item$custom_price;
|
|
488
487
|
return _objectSpread(_objectSpread({}, item), {}, {
|
|
489
|
-
bundle_selling_price: (
|
|
490
|
-
custom_price: (
|
|
488
|
+
bundle_selling_price: (_ref2 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref2 !== void 0 ? _ref2 : '0.00',
|
|
489
|
+
custom_price: (_ref3 = (_ref4 = (_item$custom_price = item.custom_price) !== null && _item$custom_price !== void 0 ? _item$custom_price : item.bundle_selling_price) !== null && _ref4 !== void 0 ? _ref4 : item.price) !== null && _ref3 !== void 0 ? _ref3 : '0.00'
|
|
491
490
|
});
|
|
492
491
|
});
|
|
492
|
+
var normalizedOptions = product.product_option_item || [];
|
|
493
|
+
var optionSum = sumOptionUnitPrice(normalizedOptions);
|
|
494
|
+
|
|
495
|
+
// 1) 解析 source_product_price。
|
|
496
|
+
// 优先级:
|
|
497
|
+
// 1) metadata.source_product_price(v2 权威)
|
|
498
|
+
// 2) variantPrice(命中 variant_id,从 metadata.origin.variant[vid].price 读)
|
|
499
|
+
// 3) _origin.price / _origin.base_price(后端语义的基础价)
|
|
500
|
+
// 4) v1 兼容:无 v2 标记但存在 metadata.main_product_original_price(v1 main-only,即旧 source)
|
|
501
|
+
// 5) 入参 original_price(v1 addProduct 约定:original_price 为 pre-discount 基础价)
|
|
502
|
+
// 6) 入参 selling_price(最末兜底,新添加路径 caller 只给 selling_price)
|
|
503
|
+
var isV2 = metadata.price_schema_version === 2 || metadata.price_schema_version === '2';
|
|
504
|
+
var variantId = Number(product.product_variant_id || 0);
|
|
505
|
+
var variantList = variantId ? metadata === null || metadata === void 0 || (_metadata$origin = metadata.origin) === null || _metadata$origin === void 0 ? void 0 : _metadata$origin.variant : null;
|
|
506
|
+
var variantPrice = Array.isArray(variantList) ? (_variantList$find = variantList.find(function (v) {
|
|
507
|
+
return Number(v === null || v === void 0 ? void 0 : v.id) === variantId;
|
|
508
|
+
})) === null || _variantList$find === void 0 ? void 0 : _variantList$find.price : undefined;
|
|
509
|
+
var resolvedSource = function (_product$_origin, _product$_origin2, _ref5, _product$original_pri) {
|
|
510
|
+
if (metadata.source_product_price !== undefined) {
|
|
511
|
+
return String(metadata.source_product_price);
|
|
512
|
+
}
|
|
513
|
+
if (variantPrice !== undefined && variantPrice !== null) {
|
|
514
|
+
return String(variantPrice);
|
|
515
|
+
}
|
|
516
|
+
var originPrice = (_product$_origin = product._origin) === null || _product$_origin === void 0 ? void 0 : _product$_origin.price;
|
|
517
|
+
if (originPrice !== undefined && originPrice !== null) {
|
|
518
|
+
return String(originPrice);
|
|
519
|
+
}
|
|
520
|
+
var originBasePrice = (_product$_origin2 = product._origin) === null || _product$_origin2 === void 0 ? void 0 : _product$_origin2.base_price;
|
|
521
|
+
if (originBasePrice !== undefined && originBasePrice !== null) {
|
|
522
|
+
return String(originBasePrice);
|
|
523
|
+
}
|
|
524
|
+
if (!isV2 && metadata.main_product_original_price !== undefined) {
|
|
525
|
+
return String(metadata.main_product_original_price);
|
|
526
|
+
}
|
|
527
|
+
return (_ref5 = (_product$original_pri = product.original_price) !== null && _product$original_pri !== void 0 ? _product$original_pri : product.selling_price) !== null && _ref5 !== void 0 ? _ref5 : '0.00';
|
|
528
|
+
}();
|
|
529
|
+
|
|
530
|
+
// 2) 派生 main_product_original_price(含 option、不含折扣)
|
|
531
|
+
var mainOriginalDec = new Decimal(Number(resolvedSource) || 0).plus(optionSum);
|
|
532
|
+
var mainOriginalStr = mainOriginalDec.toDecimalPlaces(2).toFixed(2);
|
|
533
|
+
|
|
534
|
+
// 3) 派生 main_product_selling_price(含 option、含主商品折扣)
|
|
535
|
+
// - v2 数据:直接沿用 metadata.main_product_selling_price(保留折扣)
|
|
536
|
+
// - v1 metadata:main_product_selling_price 旧语义是 main-only(≈ source-level 折后价),
|
|
537
|
+
// 反推 legacyDiscount = main_original(旧) - main_selling(旧),再用新 main_original - legacyDiscount
|
|
538
|
+
// - v1 addProduct 入参:top-level selling_price < original_price 表示主商品折扣;
|
|
539
|
+
// 用差额作为 legacyDiscount 映射到新 main_selling
|
|
540
|
+
// - 其它:视为无折扣,main_selling = main_original
|
|
541
|
+
var mainSellingDec;
|
|
542
|
+
if (isV2 && metadata.main_product_selling_price != null) {
|
|
543
|
+
mainSellingDec = new Decimal(Number(metadata.main_product_selling_price) || 0);
|
|
544
|
+
} else if (metadata.main_product_selling_price != null && metadata.main_product_original_price != null) {
|
|
545
|
+
var legacyOriginal = new Decimal(Number(metadata.main_product_original_price) || 0);
|
|
546
|
+
var legacySelling = new Decimal(Number(metadata.main_product_selling_price) || 0);
|
|
547
|
+
var legacyDiscount = legacyOriginal.minus(legacySelling);
|
|
548
|
+
mainSellingDec = mainOriginalDec.minus(legacyDiscount);
|
|
549
|
+
} else if (product.original_price != null && product.selling_price != null && new Decimal(Number(product.original_price) || 0).greaterThan(new Decimal(Number(product.selling_price) || 0))) {
|
|
550
|
+
var topOriginal = new Decimal(Number(product.original_price) || 0);
|
|
551
|
+
var topSelling = new Decimal(Number(product.selling_price) || 0);
|
|
552
|
+
var _legacyDiscount = topOriginal.minus(topSelling);
|
|
553
|
+
mainSellingDec = mainOriginalDec.minus(_legacyDiscount);
|
|
554
|
+
} else {
|
|
555
|
+
mainSellingDec = mainOriginalDec;
|
|
556
|
+
}
|
|
557
|
+
var mainSellingStr = mainSellingDec.toDecimalPlaces(2).toFixed(2);
|
|
558
|
+
|
|
559
|
+
// 4) 落盘 metadata:三字段 + schema 版本 sentinel
|
|
560
|
+
metadata.source_product_price = resolvedSource;
|
|
561
|
+
metadata.main_product_original_price = mainOriginalStr;
|
|
562
|
+
metadata.main_product_selling_price = mainSellingStr;
|
|
563
|
+
metadata.price_schema_version = 2;
|
|
564
|
+
|
|
565
|
+
// 5) 合成行级 composite(main 已含 option,本步只叠 bundle)
|
|
566
|
+
var composedSellingPrice = composeLinePrice({
|
|
567
|
+
mainPrice: mainSellingStr,
|
|
568
|
+
bundle: normalizedBundle
|
|
569
|
+
});
|
|
570
|
+
var composedOriginalPrice = composeLinePrice({
|
|
571
|
+
mainPrice: mainOriginalStr,
|
|
572
|
+
bundle: normalizedBundle,
|
|
573
|
+
useOriginalBundle: true
|
|
574
|
+
});
|
|
493
575
|
return {
|
|
494
576
|
order_detail_id: product.order_detail_id || null,
|
|
495
577
|
product_id: product.product_id,
|
|
496
578
|
num: getSafeProductNum(product.num),
|
|
497
579
|
product_variant_id: product.product_variant_id,
|
|
498
580
|
identity_key: resolvedIdentityKey,
|
|
499
|
-
product_option_item:
|
|
500
|
-
selling_price:
|
|
501
|
-
original_price:
|
|
581
|
+
product_option_item: normalizedOptions,
|
|
582
|
+
selling_price: composedSellingPrice,
|
|
583
|
+
original_price: composedOriginalPrice,
|
|
502
584
|
tax_fee: product.tax_fee || '0.00',
|
|
503
585
|
is_charge_tax: (_product$is_charge_ta = product.is_charge_tax) !== null && _product$is_charge_ta !== void 0 ? _product$is_charge_ta : 0,
|
|
504
586
|
discount_list: product.discount_list || [],
|
|
@@ -579,7 +661,7 @@ export function hasCustomCapacityProduct(products) {
|
|
|
579
661
|
/**
|
|
580
662
|
* 根据预约规则商品的 resource.type 计算桌台是否已被"占满"。
|
|
581
663
|
* - single:只要有 `lastOrderId` 即视为占用
|
|
582
|
-
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和
|
|
664
|
+
* - multiple:当前时间落在 `capacity_list[i]` 的 `[start_at, end_at]`(inclusive)内的 pax 之和 >= 总容量
|
|
583
665
|
* - 其他('capacity' / undefined):返回 false,不施加限制
|
|
584
666
|
*/
|
|
585
667
|
export function computeResourceIsFull(params) {
|
|
@@ -611,7 +693,7 @@ export function computeResourceIsFull(params) {
|
|
|
611
693
|
} finally {
|
|
612
694
|
_iterator8.f();
|
|
613
695
|
}
|
|
614
|
-
return occupied
|
|
696
|
+
return occupied >= totalCapacity;
|
|
615
697
|
}
|
|
616
698
|
|
|
617
699
|
/**
|
|
@@ -45,7 +45,7 @@ import { extractResourceIds, buildResourceProductMap } from "./utils/resource";
|
|
|
45
45
|
import { buildTimeSlotGrid, isBusinessHoursCrossDay, generateTimeLabels } from "./utils/timeSlot";
|
|
46
46
|
import { buildDateRangeSummary } from "./utils/dateSummary";
|
|
47
47
|
import { mergeConsecutiveSlots, expandMergedSlotToIndividual, buildVenueIdentityKey, buildVenueBookingEntry, buildPriceBreakdown } from "./utils/slotMerge";
|
|
48
|
-
import { createUuidV4 } from "../../modules/Order/utils";
|
|
48
|
+
import { composeLinePrice, createUuidV4, sumOptionUnitPrice } from "../../modules/Order/utils";
|
|
49
49
|
import { OrderModule } from "../../modules/Order";
|
|
50
50
|
import { RegisterAndLoginHooks } from "../RegisterAndLogin/types";
|
|
51
51
|
import Decimal from 'decimal.js';
|
|
@@ -2027,7 +2027,7 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2027
2027
|
key: "setDiscountSelected",
|
|
2028
2028
|
value: (function () {
|
|
2029
2029
|
var _setDiscountSelected = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21(params) {
|
|
2030
|
-
var _tempOrder$holder, _this$store$order$get, _this$store$order$get2, list, beforeTarget, updated, updatedTarget, tempOrder, orderStore, discountModule, rulesModule, holders, nextDiscountList, _tempOrder$holder2, result, beforeSelectedIds, _iterator13, _step13, d, selectedResourceIds, _iterator14, _step14, _product$_origin, product, totalPerUnitDiscount,
|
|
2030
|
+
var _tempOrder$holder, _this$store$order$get, _this$store$order$get2, list, beforeTarget, updated, updatedTarget, tempOrder, orderStore, discountModule, rulesModule, holders, nextDiscountList, _tempOrder$holder2, result, beforeSelectedIds, _iterator13, _step13, d, selectedResourceIds, _iterator14, _step14, _product$_origin, _product$metadata$sou, _product$metadata3, _product$metadata4, _product$original_pri, product, totalPerUnitDiscount, optionSum, sourcePrice, newSourceSellingPrice, newMainSellingPrice, afterApplyTarget, finalSummary, finalProduct, finalTarget;
|
|
2031
2031
|
return _regeneratorRuntime().wrap(function _callee21$(_context21) {
|
|
2032
2032
|
while (1) switch (_context21.prev = _context21.next) {
|
|
2033
2033
|
case 0:
|
|
@@ -2116,7 +2116,7 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2116
2116
|
_iterator14.s();
|
|
2117
2117
|
case 21:
|
|
2118
2118
|
if ((_step14 = _iterator14.n()).done) {
|
|
2119
|
-
_context21.next =
|
|
2119
|
+
_context21.next = 35;
|
|
2120
2120
|
break;
|
|
2121
2121
|
}
|
|
2122
2122
|
product = _step14.value;
|
|
@@ -2124,7 +2124,7 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2124
2124
|
_context21.next = 25;
|
|
2125
2125
|
break;
|
|
2126
2126
|
}
|
|
2127
|
-
return _context21.abrupt("continue",
|
|
2127
|
+
return _context21.abrupt("continue", 33);
|
|
2128
2128
|
case 25:
|
|
2129
2129
|
// 1. 把 product.discount_list 和当前选中的 discount 对齐(剔除已取消的券)
|
|
2130
2130
|
product.discount_list = (product.discount_list || []).filter(function (pd) {
|
|
@@ -2133,45 +2133,53 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2133
2133
|
return rid != null && selectedResourceIds.has(rid);
|
|
2134
2134
|
});
|
|
2135
2135
|
|
|
2136
|
-
// 2. 以
|
|
2136
|
+
// 2. 以 source_product_price 为券作用基准:券作用于 source(不含 option),
|
|
2137
|
+
// 再把 option 加回得到含 option 的 main_product_selling_price,最后合成 composite。
|
|
2137
2138
|
totalPerUnitDiscount = (product.discount_list || []).reduce(function (sum, pd) {
|
|
2138
2139
|
return sum + (pd.amount || 0);
|
|
2139
2140
|
}, 0);
|
|
2140
|
-
|
|
2141
|
-
product.
|
|
2141
|
+
optionSum = sumOptionUnitPrice(product.product_option_item);
|
|
2142
|
+
sourcePrice = (_product$metadata$sou = (_product$metadata3 = product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.source_product_price) !== null && _product$metadata$sou !== void 0 ? _product$metadata$sou : ((_product$metadata4 = product.metadata) === null || _product$metadata4 === void 0 ? void 0 : _product$metadata4.main_product_original_price) != null ? new Decimal(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : (_product$original_pri = product.original_price) !== null && _product$original_pri !== void 0 ? _product$original_pri : '0';
|
|
2143
|
+
newSourceSellingPrice = new Decimal(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
|
|
2144
|
+
newMainSellingPrice = new Decimal(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
|
|
2142
2145
|
if (product.metadata) {
|
|
2143
|
-
product.metadata.main_product_selling_price =
|
|
2146
|
+
product.metadata.main_product_selling_price = newMainSellingPrice;
|
|
2147
|
+
product.metadata.price_schema_version = 2;
|
|
2144
2148
|
}
|
|
2145
|
-
|
|
2149
|
+
product.selling_price = composeLinePrice({
|
|
2150
|
+
mainPrice: newMainSellingPrice,
|
|
2151
|
+
bundle: product.product_bundle
|
|
2152
|
+
});
|
|
2153
|
+
case 33:
|
|
2146
2154
|
_context21.next = 21;
|
|
2147
2155
|
break;
|
|
2148
|
-
case
|
|
2149
|
-
_context21.next =
|
|
2156
|
+
case 35:
|
|
2157
|
+
_context21.next = 40;
|
|
2150
2158
|
break;
|
|
2151
|
-
case 34:
|
|
2152
|
-
_context21.prev = 34;
|
|
2153
|
-
_context21.t0 = _context21["catch"](19);
|
|
2154
|
-
_iterator14.e(_context21.t0);
|
|
2155
2159
|
case 37:
|
|
2156
2160
|
_context21.prev = 37;
|
|
2157
|
-
|
|
2158
|
-
|
|
2161
|
+
_context21.t0 = _context21["catch"](19);
|
|
2162
|
+
_iterator14.e(_context21.t0);
|
|
2159
2163
|
case 40:
|
|
2164
|
+
_context21.prev = 40;
|
|
2165
|
+
_iterator14.f();
|
|
2166
|
+
return _context21.finish(40);
|
|
2167
|
+
case 43:
|
|
2160
2168
|
OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
|
|
2161
|
-
_context21.next =
|
|
2169
|
+
_context21.next = 46;
|
|
2162
2170
|
return discountModule === null || discountModule === void 0 ? void 0 : discountModule.setDiscountList(nextDiscountList);
|
|
2163
|
-
case
|
|
2171
|
+
case 46:
|
|
2164
2172
|
tempOrder.discount_list = (nextDiscountList || []).filter(function (d) {
|
|
2165
2173
|
return d.isSelected;
|
|
2166
2174
|
});
|
|
2167
2175
|
afterApplyTarget = this.store.order.getDiscountList().find(function (d) {
|
|
2168
2176
|
return d.id === params.discountId;
|
|
2169
2177
|
}) || null;
|
|
2170
|
-
_context21.next =
|
|
2178
|
+
_context21.next = 50;
|
|
2171
2179
|
return this.store.order.recalculateSummary({
|
|
2172
2180
|
createIfMissing: true
|
|
2173
2181
|
});
|
|
2174
|
-
case
|
|
2182
|
+
case 50:
|
|
2175
2183
|
this.store.order.persistTempOrder();
|
|
2176
2184
|
finalSummary = ((_this$store$order$get = this.store.order.getTempOrder()) === null || _this$store$order$get === void 0 ? void 0 : _this$store$order$get.summary) || null;
|
|
2177
2185
|
finalProduct = ((_this$store$order$get2 = this.store.order.getTempOrder()) === null || _this$store$order$get2 === void 0 || (_this$store$order$get2 = _this$store$order$get2.products) === null || _this$store$order$get2 === void 0 ? void 0 : _this$store$order$get2[0]) || null;
|
|
@@ -2180,16 +2188,16 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2180
2188
|
return d.id === params.discountId;
|
|
2181
2189
|
}) || null;
|
|
2182
2190
|
return _context21.abrupt("return", this.store.order.getDiscountList());
|
|
2183
|
-
case
|
|
2184
|
-
_context21.prev =
|
|
2191
|
+
case 58:
|
|
2192
|
+
_context21.prev = 58;
|
|
2185
2193
|
_context21.t1 = _context21["catch"](1);
|
|
2186
2194
|
this.logMethodError('setDiscountSelected', _context21.t1);
|
|
2187
2195
|
throw _context21.t1;
|
|
2188
|
-
case
|
|
2196
|
+
case 62:
|
|
2189
2197
|
case "end":
|
|
2190
2198
|
return _context21.stop();
|
|
2191
2199
|
}
|
|
2192
|
-
}, _callee21, this, [[1,
|
|
2200
|
+
}, _callee21, this, [[1, 58], [19, 37, 40, 43]]);
|
|
2193
2201
|
}));
|
|
2194
2202
|
function setDiscountSelected(_x15) {
|
|
2195
2203
|
return _setDiscountSelected.apply(this, arguments);
|
|
@@ -2336,7 +2344,7 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2336
2344
|
key: "addProductToOrder",
|
|
2337
2345
|
value: function () {
|
|
2338
2346
|
var _addProductToOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee25(product) {
|
|
2339
|
-
var _product$
|
|
2347
|
+
var _product$metadata5, _product$product_vari2, quotationPrice, products;
|
|
2340
2348
|
return _regeneratorRuntime().wrap(function _callee25$(_context25) {
|
|
2341
2349
|
while (1) switch (_context25.prev = _context25.next) {
|
|
2342
2350
|
case 0:
|
|
@@ -2351,7 +2359,7 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
|
|
|
2351
2359
|
}
|
|
2352
2360
|
throw new Error('order 模块未初始化');
|
|
2353
2361
|
case 4:
|
|
2354
|
-
if (!((_product$
|
|
2362
|
+
if (!((_product$metadata5 = product.metadata) !== null && _product$metadata5 !== void 0 && _product$metadata5.venue_booking) && this.store.quotation && product.product_id != null) {
|
|
2355
2363
|
quotationPrice = this.store.quotation.getPriceForProduct({
|
|
2356
2364
|
productId: product.product_id,
|
|
2357
2365
|
variantId: (_product$product_vari2 = product.product_variant_id) !== null && _product$product_vari2 !== void 0 ? _product$product_vari2 : undefined,
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
|
|
29
|
-
// src/model/strategy/adapter/promotion/index.ts
|
|
30
|
-
var promotion_exports = {};
|
|
31
|
-
__export(promotion_exports, {
|
|
32
|
-
BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
|
|
33
|
-
PromotionAdapter: () => import_adapter.PromotionAdapter,
|
|
34
|
-
PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
|
|
35
|
-
X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
|
|
36
|
-
default: () => import_adapter2.default
|
|
37
|
-
});
|
|
38
|
-
module.exports = __toCommonJS(promotion_exports);
|
|
39
|
-
var import_evaluator = require("./evaluator");
|
|
40
|
-
var import_adapter = require("./adapter");
|
|
41
|
-
var import_adapter2 = __toESM(require("./adapter"));
|
|
42
|
-
var import_examples = require("./examples");
|
|
43
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
-
0 && (module.exports = {
|
|
45
|
-
BUY_X_GET_Y_FREE_STRATEGY,
|
|
46
|
-
PromotionAdapter,
|
|
47
|
-
PromotionEvaluator,
|
|
48
|
-
X_ITEMS_FOR_Y_PRICE_STRATEGY
|
|
49
|
-
});
|
|
@@ -82,7 +82,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
82
82
|
enhancePayload?: SubmitPayloadEnhancer;
|
|
83
83
|
}): Promise<T>;
|
|
84
84
|
createOrder(params: CommitOrderParams['query']): {
|
|
85
|
-
type: "
|
|
85
|
+
type: "appointment_booking" | "virtual";
|
|
86
86
|
platform: string;
|
|
87
87
|
sales_channel: string;
|
|
88
88
|
order_sales_channel: string;
|
|
@@ -289,7 +289,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
289
289
|
return;
|
|
290
290
|
}
|
|
291
291
|
if (Array.isArray(parsedData.products)) {
|
|
292
|
-
for (
|
|
292
|
+
for (let i = 0; i < parsedData.products.length; i++) {
|
|
293
|
+
const p = parsedData.products[i];
|
|
293
294
|
if (!p || typeof p !== "object")
|
|
294
295
|
continue;
|
|
295
296
|
if (!Array.isArray(p.product_option_item)) {
|
|
@@ -309,6 +310,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
309
310
|
row.metadata.unique_identification_number = newKey;
|
|
310
311
|
}
|
|
311
312
|
}
|
|
313
|
+
parsedData.products[i] = (0, import_utils3.normalizeOrderProduct)(row);
|
|
312
314
|
}
|
|
313
315
|
}
|
|
314
316
|
this.store.tempOrder = parsedData;
|
|
@@ -478,6 +480,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
478
480
|
return tempOrder.products;
|
|
479
481
|
}
|
|
480
482
|
async updateProductInOrder(params) {
|
|
483
|
+
var _a, _b, _c;
|
|
481
484
|
const {
|
|
482
485
|
product_id,
|
|
483
486
|
product_variant_id,
|
|
@@ -509,7 +512,17 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
509
512
|
product_variant_id
|
|
510
513
|
};
|
|
511
514
|
nextProduct.num = (0, import_utils3.getSafeProductNum)(nextProduct.num);
|
|
512
|
-
|
|
515
|
+
const callerUpdatesTopPrice = Object.prototype.hasOwnProperty.call(updates || {}, "selling_price") || Object.prototype.hasOwnProperty.call(updates || {}, "original_price");
|
|
516
|
+
const callerUpdatesMainMeta = ((_a = updates == null ? void 0 : updates.metadata) == null ? void 0 : _a.main_product_selling_price) !== void 0 || ((_b = updates == null ? void 0 : updates.metadata) == null ? void 0 : _b.main_product_original_price) !== void 0 || ((_c = updates == null ? void 0 : updates.metadata) == null ? void 0 : _c.source_product_price) !== void 0;
|
|
517
|
+
if (callerUpdatesTopPrice && !callerUpdatesMainMeta) {
|
|
518
|
+
const existedMeta = nextProduct.metadata || {};
|
|
519
|
+
nextProduct.metadata = { ...existedMeta };
|
|
520
|
+
delete nextProduct.metadata.source_product_price;
|
|
521
|
+
delete nextProduct.metadata.main_product_selling_price;
|
|
522
|
+
delete nextProduct.metadata.main_product_original_price;
|
|
523
|
+
delete nextProduct.metadata.price_schema_version;
|
|
524
|
+
}
|
|
525
|
+
tempOrder.products[productIndex] = (0, import_utils3.normalizeOrderProduct)(nextProduct);
|
|
513
526
|
this.applyDiscount();
|
|
514
527
|
await this.recalculateSummary({ createIfMissing: true });
|
|
515
528
|
this.persistTempOrder();
|
|
@@ -541,9 +554,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
541
554
|
});
|
|
542
555
|
let result;
|
|
543
556
|
if (tempOrder.order_id) {
|
|
544
|
-
|
|
545
|
-
(0, import_utils.filterProductsForScanOrderMore)(payload.products)
|
|
546
|
-
);
|
|
557
|
+
const products = (0, import_utils.filterProductsForScanOrderMore)(payload.products);
|
|
547
558
|
const moreResult = await this.scanOrderMore({
|
|
548
559
|
query: {
|
|
549
560
|
order_id: tempOrder.order_id,
|
|
@@ -771,7 +782,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
771
782
|
async submitScanOrder(params) {
|
|
772
783
|
const { url, query } = params;
|
|
773
784
|
const fetchUrl = url || "/order/sales/checkout";
|
|
774
|
-
return this.request.post(fetchUrl, query)
|
|
785
|
+
return this.request.post(fetchUrl, query, { customToast: () => {
|
|
786
|
+
} });
|
|
775
787
|
}
|
|
776
788
|
async scanOrderMore(params) {
|
|
777
789
|
const { url, query } = params;
|
|
@@ -780,7 +792,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
|
|
|
780
792
|
products: query.products,
|
|
781
793
|
request_unique_idempotency_token: query.request_unique_idempotency_token
|
|
782
794
|
};
|
|
783
|
-
return this.request.put(fetchUrl, requestBody)
|
|
795
|
+
return this.request.put(fetchUrl, requestBody, { customToast: () => {
|
|
796
|
+
} });
|
|
784
797
|
}
|
|
785
798
|
// TODO 获取详情的接口
|
|
786
799
|
async getOrderInfoByRemote(order_id) {
|
|
@@ -44,8 +44,19 @@ export interface SubmitScanOrderProduct {
|
|
|
44
44
|
num: number;
|
|
45
45
|
product_variant_id: number;
|
|
46
46
|
product_option_item: any[];
|
|
47
|
+
/**
|
|
48
|
+
* 行 composite 券后单价。
|
|
49
|
+
* 公式:`metadata.main_product_selling_price` + Σ(bundle_selling_price × num)。
|
|
50
|
+
* 主商品(含 option、含主商品折扣)的单价存在 `metadata.main_product_selling_price`。
|
|
51
|
+
*/
|
|
47
52
|
selling_price: string;
|
|
53
|
+
/**
|
|
54
|
+
* 行 composite 券前单价。
|
|
55
|
+
* 公式:`metadata.main_product_original_price` + Σ(bundle 原价 × num)。
|
|
56
|
+
* 主商品(含 option、不含折扣)的单价存在 `metadata.main_product_original_price`。
|
|
57
|
+
*/
|
|
48
58
|
original_price: string;
|
|
59
|
+
/** 出站兼容字段,直接由 `selling_price` 派生,语义同 composite。 */
|
|
49
60
|
payment_price: string;
|
|
50
61
|
tax_fee: string;
|
|
51
62
|
is_charge_tax: number;
|