@pisell/pisellos 2.2.168 → 2.2.169

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.
Files changed (43) hide show
  1. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +51 -15
  2. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +11 -1
  3. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +26 -2
  4. package/dist/modules/Customer/index.d.ts +6 -0
  5. package/dist/modules/Customer/index.js +122 -77
  6. package/dist/modules/Customer/types.d.ts +2 -0
  7. package/dist/modules/Order/index.d.ts +2 -1
  8. package/dist/modules/Order/index.js +47 -7
  9. package/dist/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  10. package/dist/modules/Order/utils/manualProductDiscount.js +212 -0
  11. package/dist/modules/Order/utils.d.ts +4 -0
  12. package/dist/modules/Order/utils.js +24 -9
  13. package/dist/modules/Rules/index.d.ts +4 -0
  14. package/dist/modules/Rules/index.js +26 -10
  15. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +37 -6
  16. package/dist/solution/BaseSales/utils.js +11 -2
  17. package/dist/solution/BookingByStep/index.d.ts +1 -1
  18. package/dist/solution/BookingTicket/index.d.ts +1 -1
  19. package/dist/solution/BookingTicket/index.js +4 -4
  20. package/dist/solution/BookingTicket/utils/addProductDecision.js +3 -1
  21. package/dist/solution/ScanOrder/utils.js +11 -2
  22. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +42 -9
  23. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +11 -1
  24. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +22 -1
  25. package/lib/modules/Customer/index.d.ts +6 -0
  26. package/lib/modules/Customer/index.js +18 -3
  27. package/lib/modules/Customer/types.d.ts +2 -0
  28. package/lib/modules/Order/index.d.ts +2 -1
  29. package/lib/modules/Order/index.js +46 -3
  30. package/lib/modules/Order/utils/manualProductDiscount.d.ts +106 -0
  31. package/lib/modules/Order/utils/manualProductDiscount.js +207 -0
  32. package/lib/modules/Order/utils.d.ts +4 -0
  33. package/lib/modules/Order/utils.js +45 -9
  34. package/lib/modules/Rules/index.d.ts +4 -0
  35. package/lib/modules/Rules/index.js +22 -14
  36. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +42 -4
  37. package/lib/solution/BaseSales/utils.js +10 -2
  38. package/lib/solution/BookingByStep/index.d.ts +1 -1
  39. package/lib/solution/BookingTicket/index.d.ts +1 -1
  40. package/lib/solution/BookingTicket/index.js +2 -2
  41. package/lib/solution/BookingTicket/utils/addProductDecision.js +3 -1
  42. package/lib/solution/ScanOrder/utils.js +10 -2
  43. package/package.json +1 -1
@@ -30,6 +30,7 @@ import { generateDuration, getAllDiscountList, mergeRelationForms, buildSubmitPa
30
30
  import { isNormalProduct } from "../Product/utils";
31
31
  import dayjs from 'dayjs';
32
32
  import { buildProductLineFingerprint, getProductIdentityIndex, getSafeProductNum, isIdentityMatch, normalizeOrderProduct } from "../../solution/ScanOrder/utils";
33
+ import { syncManualProductDiscountProductNum } from "./utils/manualProductDiscount";
33
34
  import { DiscountModule } from "../Discount";
34
35
  import { RulesModule } from "../Rules";
35
36
  import { UnavailableReason } from "../Rules/types";
@@ -375,7 +376,11 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
375
376
  orderTotalAmount: Number(((_this$store$summary2 = this.store.summary) === null || _this$store$summary2 === void 0 ? void 0 : _this$store$summary2.total_amount) || 0)
376
377
  });
377
378
  if (result !== null && result !== void 0 && result.productList) {
378
- tempOrder.products = result.productList;
379
+ tempOrder.products = (result.productList || []).map(function (product) {
380
+ return _objectSpread(_objectSpread({}, product), {}, {
381
+ discount_list: syncManualProductDiscountProductNum(product.discount_list, product.num)
382
+ });
383
+ });
379
384
  }
380
385
  if (result !== null && result !== void 0 && result.discountList) {
381
386
  var _this$store$discount8;
@@ -1284,25 +1289,51 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1284
1289
  this.persistTempOrder();
1285
1290
  return tempOrder.contacts_info;
1286
1291
  }
1292
+ }, {
1293
+ key: "buildTempOrderCustomer",
1294
+ value: function buildTempOrderCustomer(params) {
1295
+ var _ref8, _ref9, _ref10, _source$name, _ref11, _ref12, _ref13, _source$customer_name, _source$id, _source$customer_id, _ref14, _source$country_calli, _source$phone, _source$email;
1296
+ if (!params.customerId) return null;
1297
+ var source = params.source ? cloneDeep(params.source) : {};
1298
+ var name = (_ref8 = (_ref9 = (_ref10 = (_source$name = source.name) !== null && _source$name !== void 0 ? _source$name : source.display_name) !== null && _ref10 !== void 0 ? _ref10 : source.customerName) !== null && _ref9 !== void 0 ? _ref9 : source.customer_name) !== null && _ref8 !== void 0 ? _ref8 : params.customerName;
1299
+ var customerName = (_ref11 = (_ref12 = (_ref13 = (_source$customer_name = source.customer_name) !== null && _source$customer_name !== void 0 ? _source$customer_name : source.customerName) !== null && _ref13 !== void 0 ? _ref13 : source.display_name) !== null && _ref12 !== void 0 ? _ref12 : source.name) !== null && _ref11 !== void 0 ? _ref11 : params.customerName;
1300
+ return _objectSpread(_objectSpread({}, source), {}, {
1301
+ id: (_source$id = source.id) !== null && _source$id !== void 0 ? _source$id : params.customerId,
1302
+ customer_id: (_source$customer_id = source.customer_id) !== null && _source$customer_id !== void 0 ? _source$customer_id : params.customerId,
1303
+ name: String(name || ''),
1304
+ customer_name: String(customerName || ''),
1305
+ country_calling_code: String((_ref14 = (_source$country_calli = source.country_calling_code) !== null && _source$country_calli !== void 0 ? _source$country_calli : source.countryCallingCode) !== null && _ref14 !== void 0 ? _ref14 : params.countryCallingCode),
1306
+ phone: String((_source$phone = source.phone) !== null && _source$phone !== void 0 ? _source$phone : params.phone),
1307
+ email: String((_source$email = source.email) !== null && _source$email !== void 0 ? _source$email : params.email)
1308
+ });
1309
+ }
1287
1310
 
1288
1311
  /**
1289
1312
  * 更新当前 tempOrder 的客户协议字段。
1290
1313
  *
1291
- * PaymentModal 只需要修改订单里的客户字段;如果外部还有客户模块需要同步,
1314
+ * PaymentModal 只需要修改订单里的客户事实;如果外部还有客户模块需要同步,
1292
1315
  * 应由调用方通过回调处理,不能把外部 UI 状态写进 tempOrder。
1293
1316
  */
1294
1317
  }, {
1295
1318
  key: "updateTempOrderCustomer",
1296
1319
  value: function updateTempOrderCustomer(customer) {
1297
- var _ref8, _ref9, _customer$customer_id, _ref10, _ref11, _ref12, _customer$customer_na, _ref13, _customer$country_cal;
1320
+ var _ref15, _ref16, _customer$customer_id, _ref17, _ref18, _ref19, _customer$customer_na, _ref20, _customer$country_cal;
1298
1321
  var tempOrder = this.ensureTempOrder();
1299
- var customerId = (_ref8 = (_ref9 = (_customer$customer_id = customer.customer_id) !== null && _customer$customer_id !== void 0 ? _customer$customer_id : customer.customerId) !== null && _ref9 !== void 0 ? _ref9 : customer.id) !== null && _ref8 !== void 0 ? _ref8 : null;
1300
- var customerName = (_ref10 = (_ref11 = (_ref12 = (_customer$customer_na = customer.customer_name) !== null && _customer$customer_na !== void 0 ? _customer$customer_na : customer.customerName) !== null && _ref12 !== void 0 ? _ref12 : customer.display_name) !== null && _ref11 !== void 0 ? _ref11 : customer.name) !== null && _ref10 !== void 0 ? _ref10 : '';
1322
+ var customerId = (_ref15 = (_ref16 = (_customer$customer_id = customer.customer_id) !== null && _customer$customer_id !== void 0 ? _customer$customer_id : customer.customerId) !== null && _ref16 !== void 0 ? _ref16 : customer.id) !== null && _ref15 !== void 0 ? _ref15 : null;
1323
+ var customerName = (_ref17 = (_ref18 = (_ref19 = (_customer$customer_na = customer.customer_name) !== null && _customer$customer_na !== void 0 ? _customer$customer_na : customer.customerName) !== null && _ref19 !== void 0 ? _ref19 : customer.display_name) !== null && _ref18 !== void 0 ? _ref18 : customer.name) !== null && _ref17 !== void 0 ? _ref17 : '';
1301
1324
  tempOrder.customer_id = customerId === null || customerId === undefined || customerId === '' ? null : Number(customerId);
1302
1325
  tempOrder.customer_name = String(customerName || '');
1303
- tempOrder.country_calling_code = String((_ref13 = (_customer$country_cal = customer.country_calling_code) !== null && _customer$country_cal !== void 0 ? _customer$country_cal : customer.countryCallingCode) !== null && _ref13 !== void 0 ? _ref13 : '');
1326
+ tempOrder.country_calling_code = String((_ref20 = (_customer$country_cal = customer.country_calling_code) !== null && _customer$country_cal !== void 0 ? _customer$country_cal : customer.countryCallingCode) !== null && _ref20 !== void 0 ? _ref20 : '');
1304
1327
  tempOrder.phone = String(customer.phone || '');
1305
1328
  tempOrder.email = String(customer.email || '');
1329
+ tempOrder.customer = this.buildTempOrderCustomer({
1330
+ source: customer,
1331
+ customerId: tempOrder.customer_id,
1332
+ customerName: tempOrder.customer_name,
1333
+ countryCallingCode: tempOrder.country_calling_code,
1334
+ phone: tempOrder.phone,
1335
+ email: tempOrder.email
1336
+ });
1306
1337
  this.persistTempOrder();
1307
1338
  return {
1308
1339
  customerId: tempOrder.customer_id,
@@ -1324,6 +1355,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1324
1355
  tempOrder.country_calling_code = String(patch.country_calling_code || '');
1325
1356
  tempOrder.phone = String(patch.phone || '');
1326
1357
  tempOrder.email = String(patch.email || '');
1358
+ tempOrder.customer = this.buildTempOrderCustomer({
1359
+ source: snapshot || null,
1360
+ customerId: tempOrder.customer_id,
1361
+ customerName: tempOrder.customer_name,
1362
+ countryCallingCode: tempOrder.country_calling_code,
1363
+ phone: tempOrder.phone,
1364
+ email: tempOrder.email
1365
+ });
1327
1366
  if (snapshot !== undefined) {
1328
1367
  var extend = this.ensureExtend(tempOrder);
1329
1368
  if (snapshot === null) delete extend.customerSnapshot;else extend.customerSnapshot = cloneDeep(snapshot);
@@ -1358,11 +1397,12 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1358
1397
  key: "clearOrderCustomer",
1359
1398
  value: function clearOrderCustomer() {
1360
1399
  var tempOrder = this.ensureTempOrder();
1361
- tempOrder.customer_id = 0;
1400
+ tempOrder.customer_id = null;
1362
1401
  tempOrder.customer_name = '';
1363
1402
  tempOrder.country_calling_code = '';
1364
1403
  tempOrder.phone = '';
1365
1404
  tempOrder.email = '';
1405
+ tempOrder.customer = null;
1366
1406
  if (tempOrder._extend) delete tempOrder._extend.customerSnapshot;
1367
1407
  this.persistTempOrder();
1368
1408
  this.saveDraftInBackground();
@@ -0,0 +1,106 @@
1
+ /** 解析商品行数量(checkout 协议 product_num 语义 = 当前行 num) */
2
+ export declare function resolveSafeProductNum(num?: number | null): number;
3
+ /**
4
+ * 将 discount_list 中 type=product 项的 product_num 同步为当前商品数量。
5
+ *
6
+ * @example
7
+ * syncManualProductDiscountProductNum(line.discount_list, line.num);
8
+ */
9
+ export declare function syncManualProductDiscountProductNum(discountList: any[] | undefined | null, productNum?: number | null): any[];
10
+ /** 从多源解析改价前行总价(与 cacheItem._extend.origin_total 语义一致) */
11
+ export declare function resolveManualDiscountOriginTotal(sources: {
12
+ originTotal?: unknown;
13
+ extendOriginTotal?: unknown;
14
+ originExtendOriginTotal?: unknown;
15
+ sourceExtendOriginTotal?: unknown;
16
+ catalogUnitPrice?: unknown;
17
+ quantity?: number;
18
+ }): number;
19
+ /** 从 payload / extend / origin 解析手动折扣原因 */
20
+ export declare function resolveManualDiscountReasonFromSources(sources: {
21
+ discountReason?: unknown;
22
+ extendDiscountReason?: unknown;
23
+ originExtendDiscountReason?: unknown;
24
+ }): string;
25
+ /** 是否带手动改价标记(price_override / is_manual_discount) */
26
+ export declare function hasManualProductDiscountFlag(metadata?: Record<string, any> | null): boolean;
27
+ /**
28
+ * normalize 兜底:手动改价但 discount_list 缺 type=product 时,按行级原价/折后价补写。
29
+ *
30
+ * @example
31
+ * ensureManualProductDiscountList({
32
+ * discountList: [],
33
+ * metadata: { price_override: '5', is_manual_discount: 1 },
34
+ * originalPrice: '11.00',
35
+ * sellingPrice: '5.00',
36
+ * quantity: 1,
37
+ * });
38
+ */
39
+ export declare function ensureManualProductDiscountList(params: {
40
+ discountList?: any[] | null;
41
+ metadata?: Record<string, any> | null;
42
+ originalPrice: string | number;
43
+ sellingPrice: string | number;
44
+ quantity?: number;
45
+ }): any[];
46
+ /** 商品手动折扣 discount_list 项(checkout 协议,type = product) */
47
+ export interface ManualProductDiscountItem {
48
+ amount: number;
49
+ type: 'product';
50
+ discount: {
51
+ message: string;
52
+ discountway: string;
53
+ product_num: number;
54
+ discount_per: string;
55
+ discount_type: 'discount' | 'change_price';
56
+ };
57
+ }
58
+ /**
59
+ * 从 discount_list 中取手动改价项(type = product)。
60
+ *
61
+ * @example
62
+ * const manual = findManualProductDiscountItem(product.discount_list);
63
+ * manual?.discount.message; // 折扣原因
64
+ */
65
+ export declare function findManualProductDiscountItem(discountList?: any[] | null): ManualProductDiscountItem | undefined;
66
+ /**
67
+ * 解析折扣原因:优先 discount_list[type=product].discount.message。
68
+ *
69
+ * @example
70
+ * resolveManualDiscountMessage(line.discount_list, line.metadata?.legacy_reason);
71
+ */
72
+ export declare function resolveManualDiscountMessage(discountList?: any[] | null, fallback?: string): string;
73
+ /** 去掉 discount_list 中已有的手动改价项,避免重复叠加 */
74
+ export declare function stripManualProductDiscountItems(discountList?: any[] | null): any[];
75
+ /**
76
+ * 由改价前后行总价构建手动折扣项;amount = |originTotal - sellingTotal|(行级差额)。
77
+ *
78
+ * @example
79
+ * buildManualProductDiscountItem({
80
+ * originTotal: 11,
81
+ * sellingTotal: 4,
82
+ * quantity: 1,
83
+ * message: 'VIP',
84
+ * });
85
+ */
86
+ export declare function buildManualProductDiscountItem(params: {
87
+ originTotal: number;
88
+ sellingTotal: number;
89
+ quantity?: number;
90
+ message?: string;
91
+ discountway?: string;
92
+ discount_per?: string;
93
+ }): ManualProductDiscountItem;
94
+ /**
95
+ * 将手动改价项合并进 discount_list(替换已有 type=product 项)。
96
+ *
97
+ * @example
98
+ * mergeManualProductDiscountIntoList(coupons, manualItem);
99
+ */
100
+ export declare function mergeManualProductDiscountIntoList(discountList: any[] | undefined | null, manualItem: ManualProductDiscountItem | null | undefined): any[];
101
+ /** 是否应写入手动改价 discount_list 项 */
102
+ export declare function shouldBuildManualProductDiscount(params: {
103
+ hasPriceOverride?: boolean;
104
+ originTotal?: number;
105
+ sellingTotal?: number;
106
+ }): boolean;
@@ -0,0 +1,212 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ 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); }
5
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
6
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
7
+ 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; }
8
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
10
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
12
+ 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); }
13
+ import Decimal from 'decimal.js';
14
+
15
+ /** 解析商品行数量(checkout 协议 product_num 语义 = 当前行 num) */
16
+ export function resolveSafeProductNum(num) {
17
+ var parsed = Number(num);
18
+ if (!Number.isFinite(parsed) || parsed <= 0) return 1;
19
+ return Math.floor(parsed);
20
+ }
21
+
22
+ /**
23
+ * 将 discount_list 中 type=product 项的 product_num 同步为当前商品数量。
24
+ *
25
+ * @example
26
+ * syncManualProductDiscountProductNum(line.discount_list, line.num);
27
+ */
28
+ export function syncManualProductDiscountProductNum(discountList, productNum) {
29
+ var quantity = resolveSafeProductNum(productNum);
30
+ return (discountList || []).map(function (item) {
31
+ if ((item === null || item === void 0 ? void 0 : item.type) !== 'product') return item;
32
+ return _objectSpread(_objectSpread({}, item), {}, {
33
+ discount: _objectSpread(_objectSpread({}, item.discount || {}), {}, {
34
+ product_num: quantity
35
+ })
36
+ });
37
+ });
38
+ }
39
+
40
+ /** 从多源解析改价前行总价(与 cacheItem._extend.origin_total 语义一致) */
41
+ export function resolveManualDiscountOriginTotal(sources) {
42
+ var _sources$quantity;
43
+ var candidates = [sources.originTotal, sources.extendOriginTotal, sources.originExtendOriginTotal, sources.sourceExtendOriginTotal];
44
+ for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
45
+ var candidate = _candidates[_i];
46
+ if (candidate === undefined || candidate === null || candidate === '') continue;
47
+ var parsed = Number(candidate);
48
+ if (Number.isFinite(parsed)) return parsed;
49
+ }
50
+ var unit = Number(sources.catalogUnitPrice);
51
+ var quantity = (_sources$quantity = sources.quantity) !== null && _sources$quantity !== void 0 ? _sources$quantity : 1;
52
+ if (Number.isFinite(unit) && unit > 0) {
53
+ return new Decimal(unit).mul(quantity).toNumber();
54
+ }
55
+ return NaN;
56
+ }
57
+
58
+ /** 从 payload / extend / origin 解析手动折扣原因 */
59
+ export function resolveManualDiscountReasonFromSources(sources) {
60
+ for (var _i2 = 0, _arr = [sources.discountReason, sources.extendDiscountReason, sources.originExtendDiscountReason]; _i2 < _arr.length; _i2++) {
61
+ var candidate = _arr[_i2];
62
+ if (candidate != null && String(candidate).trim() !== '') {
63
+ return String(candidate);
64
+ }
65
+ }
66
+ return '';
67
+ }
68
+
69
+ /** 是否带手动改价标记(price_override / is_manual_discount) */
70
+ export function hasManualProductDiscountFlag(metadata) {
71
+ if (!metadata) return false;
72
+ var override = metadata.price_override;
73
+ if (override !== undefined && override !== null && override !== '') {
74
+ return true;
75
+ }
76
+ return metadata.is_manual_discount === 1 || metadata.is_manual_discount === true;
77
+ }
78
+
79
+ /**
80
+ * normalize 兜底:手动改价但 discount_list 缺 type=product 时,按行级原价/折后价补写。
81
+ *
82
+ * @example
83
+ * ensureManualProductDiscountList({
84
+ * discountList: [],
85
+ * metadata: { price_override: '5', is_manual_discount: 1 },
86
+ * originalPrice: '11.00',
87
+ * sellingPrice: '5.00',
88
+ * quantity: 1,
89
+ * });
90
+ */
91
+ export function ensureManualProductDiscountList(params) {
92
+ var _metadata$origin, _metadata$origin2, _metadata$origin3, _metadata$origin4;
93
+ var list = params.discountList || [];
94
+ var quantity = resolveSafeProductNum(params.quantity);
95
+ if (findManualProductDiscountItem(list)) {
96
+ return syncManualProductDiscountProductNum(list, quantity);
97
+ }
98
+ var metadata = params.metadata || {};
99
+ var originalNum = Number(params.originalPrice);
100
+ var sellingNum = Number(params.sellingPrice);
101
+ var shouldBuild = hasManualProductDiscountFlag(metadata) || shouldBuildManualProductDiscount({
102
+ originTotal: originalNum,
103
+ sellingTotal: sellingNum
104
+ });
105
+ if (!shouldBuild) {
106
+ return list;
107
+ }
108
+ if (!Number.isFinite(originalNum) || !Number.isFinite(sellingNum) || originalNum === sellingNum) {
109
+ return list;
110
+ }
111
+ var message = resolveManualDiscountMessage(list, resolveManualDiscountReasonFromSources({
112
+ extendDiscountReason: (_metadata$origin = metadata.origin) === null || _metadata$origin === void 0 || (_metadata$origin = _metadata$origin._extend) === null || _metadata$origin === void 0 ? void 0 : _metadata$origin.discount_reason,
113
+ originExtendDiscountReason: (_metadata$origin2 = metadata.origin) === null || _metadata$origin2 === void 0 || (_metadata$origin2 = _metadata$origin2._extend) === null || _metadata$origin2 === void 0 ? void 0 : _metadata$origin2.discount_reason
114
+ }));
115
+ return mergeManualProductDiscountIntoList(list, buildManualProductDiscountItem({
116
+ originTotal: originalNum,
117
+ sellingTotal: sellingNum,
118
+ quantity: quantity,
119
+ message: message,
120
+ discountway: (_metadata$origin3 = metadata.origin) === null || _metadata$origin3 === void 0 || (_metadata$origin3 = _metadata$origin3._extend) === null || _metadata$origin3 === void 0 ? void 0 : _metadata$origin3.discountway,
121
+ discount_per: (_metadata$origin4 = metadata.origin) === null || _metadata$origin4 === void 0 || (_metadata$origin4 = _metadata$origin4._extend) === null || _metadata$origin4 === void 0 ? void 0 : _metadata$origin4.discount_per
122
+ }));
123
+ }
124
+
125
+ /** 商品手动折扣 discount_list 项(checkout 协议,type = product) */
126
+
127
+ /**
128
+ * 从 discount_list 中取手动改价项(type = product)。
129
+ *
130
+ * @example
131
+ * const manual = findManualProductDiscountItem(product.discount_list);
132
+ * manual?.discount.message; // 折扣原因
133
+ */
134
+ export function findManualProductDiscountItem(discountList) {
135
+ return (discountList || []).find(function (item) {
136
+ return (item === null || item === void 0 ? void 0 : item.type) === 'product';
137
+ });
138
+ }
139
+
140
+ /**
141
+ * 解析折扣原因:优先 discount_list[type=product].discount.message。
142
+ *
143
+ * @example
144
+ * resolveManualDiscountMessage(line.discount_list, line.metadata?.legacy_reason);
145
+ */
146
+ export function resolveManualDiscountMessage(discountList, fallback) {
147
+ var _findManualProductDis;
148
+ var message = (_findManualProductDis = findManualProductDiscountItem(discountList)) === null || _findManualProductDis === void 0 || (_findManualProductDis = _findManualProductDis.discount) === null || _findManualProductDis === void 0 ? void 0 : _findManualProductDis.message;
149
+ if (message != null && String(message).trim() !== '') {
150
+ return String(message);
151
+ }
152
+ return fallback !== null && fallback !== void 0 ? fallback : '';
153
+ }
154
+
155
+ /** 去掉 discount_list 中已有的手动改价项,避免重复叠加 */
156
+ export function stripManualProductDiscountItems(discountList) {
157
+ return (discountList || []).filter(function (item) {
158
+ return (item === null || item === void 0 ? void 0 : item.type) !== 'product';
159
+ });
160
+ }
161
+
162
+ /**
163
+ * 由改价前后行总价构建手动折扣项;amount = |originTotal - sellingTotal|(行级差额)。
164
+ *
165
+ * @example
166
+ * buildManualProductDiscountItem({
167
+ * originTotal: 11,
168
+ * sellingTotal: 4,
169
+ * quantity: 1,
170
+ * message: 'VIP',
171
+ * });
172
+ */
173
+ export function buildManualProductDiscountItem(params) {
174
+ var _params$message, _params$discountway, _params$discount_per;
175
+ var origin = new Decimal(Number(params.originTotal) || 0);
176
+ var selling = new Decimal(Number(params.sellingTotal) || 0);
177
+ var diff = origin.minus(selling);
178
+ var quantity = resolveSafeProductNum(params.quantity);
179
+ return {
180
+ amount: diff.abs().toDecimalPlaces(2).toNumber(),
181
+ type: 'product',
182
+ discount: {
183
+ message: (_params$message = params.message) !== null && _params$message !== void 0 ? _params$message : '',
184
+ discountway: (_params$discountway = params.discountway) !== null && _params$discountway !== void 0 ? _params$discountway : 'num',
185
+ product_num: quantity,
186
+ discount_per: (_params$discount_per = params.discount_per) !== null && _params$discount_per !== void 0 ? _params$discount_per : '',
187
+ discount_type: diff.isNegative() ? 'change_price' : 'discount'
188
+ }
189
+ };
190
+ }
191
+
192
+ /**
193
+ * 将手动改价项合并进 discount_list(替换已有 type=product 项)。
194
+ *
195
+ * @example
196
+ * mergeManualProductDiscountIntoList(coupons, manualItem);
197
+ */
198
+ export function mergeManualProductDiscountIntoList(discountList, manualItem) {
199
+ var base = stripManualProductDiscountItems(discountList);
200
+ if (!manualItem) return base;
201
+ if (manualItem.amount === 0 && !manualItem.discount.message) return base;
202
+ return [].concat(_toConsumableArray(base), [manualItem]);
203
+ }
204
+
205
+ /** 是否应写入手动改价 discount_list 项 */
206
+ export function shouldBuildManualProductDiscount(params) {
207
+ if (params.hasPriceOverride) return true;
208
+ var origin = Number(params.originTotal);
209
+ var selling = Number(params.sellingTotal);
210
+ if (!Number.isFinite(origin) || !Number.isFinite(selling)) return false;
211
+ return origin !== selling;
212
+ }
@@ -77,6 +77,8 @@ export declare function resolveRulesManualDiscountFlag(metadata: Record<string,
77
77
  export declare function resolveManualOverrideLineOriginalPrice(params: {
78
78
  num?: number;
79
79
  metadata?: Record<string, any> | null;
80
+ /** 已有行级 original_price(origin 被裁剪时兜底划线价) */
81
+ lineOriginalPrice?: string | number | null;
80
82
  }, fallbackCompositeOriginal: string): string;
81
83
  export declare function createDefaultOrderRulesHooks(): RulesParamsHooks;
82
84
  /**
@@ -154,3 +156,5 @@ export declare function formatV1Product(products: OrderSubmitProduct[]): {
154
156
  unique: string;
155
157
  }[];
156
158
  export { createEmptySummary } from '../../solution/ScanOrder/utils';
159
+ export { buildManualProductDiscountItem, ensureManualProductDiscountList, findManualProductDiscountItem, mergeManualProductDiscountIntoList, resolveManualDiscountMessage, resolveManualDiscountOriginTotal, resolveManualDiscountReasonFromSources, resolveSafeProductNum, shouldBuildManualProductDiscount, syncManualProductDiscountProductNum, stripManualProductDiscountItems, } from './utils/manualProductDiscount';
160
+ export type { ManualProductDiscountItem } from './utils/manualProductDiscount';
@@ -1,5 +1,5 @@
1
1
  var _excluded = ["unique_identification_number"],
2
- _excluded2 = ["num", "product_option_item", "surcharge_fee"],
2
+ _excluded2 = ["num", "product_option_item", "surcharge_fee", "discount_amount", "discount_type", "discountway", "product_discount_reason", "discount_per"],
3
3
  _excluded3 = ["_extend", "relation_id", "table_form_id", "resource_id", "summary", "lastOrderInfo", "paid_amount", "shop_id", "shop_note", "shop_service_type", "start_time", "customer", "tax_fee", "total_amount", "total_refund_amount", "create_date", "holder_id"],
4
4
  _excluded4 = ["collect_pax", "table_occupancy_duration"];
5
5
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
@@ -142,14 +142,21 @@ export function resolveManualOverrideLineOriginalPrice(params, fallbackComposite
142
142
  return fallbackCompositeOriginal;
143
143
  }
144
144
  var refTotal = (_metadata$origin = metadata.origin) === null || _metadata$origin === void 0 || (_metadata$origin = _metadata$origin._extend) === null || _metadata$origin === void 0 ? void 0 : _metadata$origin.origin_total;
145
- if (refTotal === undefined || refTotal === null || refTotal === '') {
146
- return fallbackCompositeOriginal;
145
+ if (refTotal !== undefined && refTotal !== null && refTotal !== '') {
146
+ var parsed = Number(refTotal);
147
+ if (Number.isFinite(parsed)) {
148
+ return new Decimal(parsed).toDecimalPlaces(2).toFixed(2);
149
+ }
147
150
  }
148
- var parsed = Number(refTotal);
149
- if (!Number.isFinite(parsed)) {
150
- return fallbackCompositeOriginal;
151
+ var lineOriginal = params.lineOriginalPrice;
152
+ if (lineOriginal !== undefined && lineOriginal !== null && lineOriginal !== '') {
153
+ var parsedLine = Number(lineOriginal);
154
+ var parsedFallback = Number(fallbackCompositeOriginal);
155
+ if (Number.isFinite(parsedLine) && Number.isFinite(parsedFallback) && parsedLine > parsedFallback) {
156
+ return new Decimal(parsedLine).toDecimalPlaces(2).toFixed(2);
157
+ }
151
158
  }
152
- return new Decimal(parsed).toDecimalPlaces(2).toFixed(2);
159
+ return fallbackCompositeOriginal;
153
160
  }
154
161
  export function createDefaultOrderRulesHooks() {
155
162
  var toUnitPriceString = function toUnitPriceString(totalLike, num) {
@@ -238,7 +245,8 @@ export function createDefaultOrderRulesHooks() {
238
245
  });
239
246
  var finalOriginalPrice = resolveManualOverrideLineOriginalPrice({
240
247
  num: nextNum,
241
- metadata: metadataAny
248
+ metadata: metadataAny,
249
+ lineOriginalPrice: product.original_price
242
250
  }, composedOriginalPrice);
243
251
  return _objectSpread(_objectSpread({}, product), {}, {
244
252
  selling_price: composedSellingPrice,
@@ -438,6 +446,11 @@ function normalizeSubmitProduct(product) {
438
446
  var num = submitProduct.num,
439
447
  productOptionItem = submitProduct.product_option_item,
440
448
  _productSurchargeFee = submitProduct.surcharge_fee,
449
+ _deprecatedDiscountAmount = submitProduct.discount_amount,
450
+ _deprecatedDiscountType = submitProduct.discount_type,
451
+ _deprecatedDiscountway = submitProduct.discountway,
452
+ _deprecatedProductDiscountReason = submitProduct.product_discount_reason,
453
+ _deprecatedDiscountPer = submitProduct.discount_per,
441
454
  productRest = _objectWithoutProperties(submitProduct, _excluded2);
442
455
  var rawMetadata = submitProduct.metadata || {};
443
456
  var bookingUid = rawMetadata.booking_uid;
@@ -562,6 +575,7 @@ export function createDefaultTempOrder(params) {
562
575
  country_calling_code: '',
563
576
  phone: '',
564
577
  email: '',
578
+ customer: null,
565
579
  is_price_include_tax: 1,
566
580
  tax_title: '',
567
581
  tax_country_code: '',
@@ -767,4 +781,5 @@ export function formatV1Product(products) {
767
781
  };
768
782
  });
769
783
  }
770
- export { createEmptySummary } from "../../solution/ScanOrder/utils";
784
+ export { createEmptySummary } from "../../solution/ScanOrder/utils";
785
+ export { buildManualProductDiscountItem, ensureManualProductDiscountList, findManualProductDiscountItem, mergeManualProductDiscountIntoList, resolveManualDiscountMessage, resolveManualDiscountOriginTotal, resolveManualDiscountReasonFromSources, resolveSafeProductNum, shouldBuildManualProductDiscount, syncManualProductDiscountProductNum, stripManualProductDiscountItems } from "./utils/manualProductDiscount";
@@ -32,6 +32,10 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
32
32
  unavailableReason?: UnavailableReason;
33
33
  };
34
34
  filterDiscountListByType(discountList: Discount[], type: string): Discount[];
35
+ /** 剔除指定 type/tag 的折扣项,保留手动改价(type=product) / 券等 */
36
+ excludeDiscountListByType(discountList: Discount[], type: string): Discount[];
37
+ /** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
38
+ resolveDiscountListForManualOverride(discountList: Discount[]): Discount[];
35
39
  private getUnavailableReason;
36
40
  calcDiscount({ discountList, productList, holders, isFormSubject, orderTotalAmount }: {
37
41
  discountList: Discount[];
@@ -222,6 +222,22 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
222
222
  return item.type === type || item.tag === type;
223
223
  });
224
224
  }
225
+
226
+ /** 剔除指定 type/tag 的折扣项,保留手动改价(type=product) / 券等 */
227
+ }, {
228
+ key: "excludeDiscountListByType",
229
+ value: function excludeDiscountListByType(discountList, type) {
230
+ return (discountList || []).filter(function (item) {
231
+ return item.type !== type && item.tag !== type;
232
+ });
233
+ }
234
+
235
+ /** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
236
+ }, {
237
+ key: "resolveDiscountListForManualOverride",
238
+ value: function resolveDiscountListForManualOverride(discountList) {
239
+ return this.excludeDiscountListByType(discountList, 'promotion');
240
+ }
225
241
  // 获取券不可用的原因
226
242
  }, {
227
243
  key: "getUnavailableReason",
@@ -1208,7 +1224,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1208
1224
  price: product.price,
1209
1225
  options: restoredOptions
1210
1226
  }), {}, {
1211
- discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion')
1227
+ discount_list: isManualDiscount ? _this3.resolveDiscountListForManualOverride(product.discount_list) : _this3.filterDiscountListByType(product.discount_list, 'promotion')
1212
1228
  }))]);
1213
1229
  } else {
1214
1230
  var _ref13, _product$_promotion$f, _product13, _product$origin_total;
@@ -1231,14 +1247,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1231
1247
  main_product_selling_price: main_product_selling_price,
1232
1248
  options: restoredOptions
1233
1249
  }), {}, {
1234
- discount_list: _this3.filterDiscountListByType(product.discount_list, 'promotion')
1250
+ discount_list: isManualDiscount ? _this3.resolveDiscountListForManualOverride(product.discount_list) : _this3.filterDiscountListByType(product.discount_list, 'promotion')
1235
1251
  }))]);
1236
1252
  }
1237
1253
  } else {
1238
- var _flatItem$bundleItem8;
1254
+ var _flatItem$bundleItem8, _flatItem$bundleItem9;
1239
1255
  // bundle子商品:保存到扁平化Map
1240
1256
  processedFlatItemsMap.set(flatItem._id, [_objectSpread(_objectSpread({}, flatItem), {}, {
1241
- discount_list: _this3.filterDiscountListByType(((_flatItem$bundleItem8 = flatItem.bundleItem) === null || _flatItem$bundleItem8 === void 0 ? void 0 : _flatItem$bundleItem8.discount_list) || [], 'promotion'),
1257
+ discount_list: isManualDiscount ? _this3.resolveDiscountListForManualOverride(((_flatItem$bundleItem8 = flatItem.bundleItem) === null || _flatItem$bundleItem8 === void 0 ? void 0 : _flatItem$bundleItem8.discount_list) || []) : _this3.filterDiscountListByType(((_flatItem$bundleItem9 = flatItem.bundleItem) === null || _flatItem$bundleItem9 === void 0 ? void 0 : _flatItem$bundleItem9.discount_list) || [], 'promotion'),
1242
1258
  price: isManualDiscount ? flatItem.bundleItem.price : flatItem.bundleItem.original_price,
1243
1259
  processed: true
1244
1260
  })]);
@@ -2069,10 +2085,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2069
2085
  return true; // 单独购买时可用
2070
2086
  }
2071
2087
  if (isBundleItem) {
2072
- var _flatItem$bundleItem9, _flatItem$bundleItem10, _flatItem$originProdu, _flatItem$parentProdu10;
2088
+ var _flatItem$bundleItem10, _flatItem$bundleItem11, _flatItem$originProdu, _flatItem$parentProdu10;
2073
2089
  // 套餐中购买时,判断是否为原价
2074
- var priceType = (_flatItem$bundleItem9 = flatItem.bundleItem) === null || _flatItem$bundleItem9 === void 0 ? void 0 : _flatItem$bundleItem9.price_type;
2075
- var priceTypeExt = (_flatItem$bundleItem10 = flatItem.bundleItem) === null || _flatItem$bundleItem10 === void 0 ? void 0 : _flatItem$bundleItem10.price_type_ext;
2090
+ var priceType = (_flatItem$bundleItem10 = flatItem.bundleItem) === null || _flatItem$bundleItem10 === void 0 ? void 0 : _flatItem$bundleItem10.price_type;
2091
+ var priceTypeExt = (_flatItem$bundleItem11 = flatItem.bundleItem) === null || _flatItem$bundleItem11 === void 0 ? void 0 : _flatItem$bundleItem11.price_type_ext;
2076
2092
  // 主商品id
2077
2093
  var mainProductId = (flatItem === null || flatItem === void 0 || (_flatItem$originProdu = flatItem.originProduct) === null || _flatItem$originProdu === void 0 || (_flatItem$originProdu = _flatItem$originProdu._productOrigin) === null || _flatItem$originProdu === void 0 ? void 0 : _flatItem$originProdu.id) || (flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.id) || 0;
2078
2094
  // original_price 对应:
@@ -2139,10 +2155,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2139
2155
  return false; // 单独购买时不可用
2140
2156
  }
2141
2157
  if (isBundleItem) {
2142
- var _flatItem$bundleItem11, _flatItem$bundleItem12;
2158
+ var _flatItem$bundleItem12, _flatItem$bundleItem13;
2143
2159
  // 套餐中购买时,判断是否为原价
2144
- var _priceType = (_flatItem$bundleItem11 = flatItem.bundleItem) === null || _flatItem$bundleItem11 === void 0 ? void 0 : _flatItem$bundleItem11.price_type;
2145
- var _priceTypeExt = (_flatItem$bundleItem12 = flatItem.bundleItem) === null || _flatItem$bundleItem12 === void 0 ? void 0 : _flatItem$bundleItem12.price_type_ext;
2160
+ var _priceType = (_flatItem$bundleItem12 = flatItem.bundleItem) === null || _flatItem$bundleItem12 === void 0 ? void 0 : _flatItem$bundleItem12.price_type;
2161
+ var _priceTypeExt = (_flatItem$bundleItem13 = flatItem.bundleItem) === null || _flatItem$bundleItem13 === void 0 ? void 0 : _flatItem$bundleItem13.price_type_ext;
2146
2162
 
2147
2163
  // original_price 对应:
2148
2164
  // 1. price_type: "markup" && price_type_ext: "product_price"