@pisell/pisellos 2.2.310 → 2.2.311

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.
@@ -1,9 +0,0 @@
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, ITEM_REWARD_STRATEGY } from "./examples";
@@ -121,8 +121,9 @@ export declare function getBundleSellingMagnitude(bundle: Record<string, any> |
121
121
  * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
122
122
  * - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
123
123
  * 不含折扣。**权威源**。
124
- * - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
125
- * - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
124
+ * - `product_sku.option[].add_price` 保留单规格折前单价;Rules 的 option.price 只用于本次计算。
125
+ * - `metadata.main_product_original_price` = source + Σ(option.add_price × option.num)(含 option、不含折扣)。
126
+ * - `metadata.main_product_selling_price` = main_original − 行内 per-unit amount(含主商品及 option 优惠)。
126
127
  * - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
127
128
  *
128
129
  * Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
@@ -131,8 +132,9 @@ export declare function getBundleSellingMagnitude(bundle: Record<string, any> |
131
132
  * `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
132
133
  * - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
133
134
  * total(source + option + bundle)对齐。
135
+ * - `getProduct.options` 用单规格原价参与重算;主商品折后价从 main_selling 减去 option 折后合计反推。
134
136
  * - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
135
- * 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
137
+ * 加回单规格原价合计,再减去 optionDiscountAmount;保留订单单规格原价供取消折扣及后续重算。
136
138
  * 优先级:
137
139
  * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
138
140
  * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
@@ -579,8 +579,9 @@ export function getBundleSellingMagnitude(bundle) {
579
579
  * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
580
580
  * - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
581
581
  * 不含折扣。**权威源**。
582
- * - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
583
- * - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
582
+ * - `product_sku.option[].add_price` 保留单规格折前单价;Rules 的 option.price 只用于本次计算。
583
+ * - `metadata.main_product_original_price` = source + Σ(option.add_price × option.num)(含 option、不含折扣)。
584
+ * - `metadata.main_product_selling_price` = main_original − 行内 per-unit amount(含主商品及 option 优惠)。
584
585
  * - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
585
586
  *
586
587
  * Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
@@ -589,8 +590,9 @@ export function getBundleSellingMagnitude(bundle) {
589
590
  * `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
590
591
  * - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
591
592
  * total(source + option + bundle)对齐。
593
+ * - `getProduct.options` 用单规格原价参与重算;主商品折后价从 main_selling 减去 option 折后合计反推。
592
594
  * - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
593
- * 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
595
+ * 加回单规格原价合计,再减去 optionDiscountAmount;保留订单单规格原价供取消折扣及后续重算。
594
596
  * 优先级:
595
597
  * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
596
598
  * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
@@ -813,6 +815,15 @@ export function createDefaultOrderRulesHooks(getBookings) {
813
815
  var effectiveNum = Number(num) > 0 ? Number(num) : 1;
814
816
  return new Decimal(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
815
817
  };
818
+
819
+ // optionDiscountAmount 已是每件主商品内的单规格优惠合计,不再乘商品数量。
820
+ var getOptionDiscountAmount = function getOptionDiscountAmount(discountList) {
821
+ return (discountList || []).reduce(function (total, discount) {
822
+ var _discount$metadata, _discount$metadata2;
823
+ if (discount !== null && discount !== void 0 && (_discount$metadata = discount.metadata) !== null && _discount$metadata !== void 0 && _discount$metadata.custom_product_bundle_map_id) return total;
824
+ return total.plus(Number(discount === null || discount === void 0 || (_discount$metadata2 = discount.metadata) === null || _discount$metadata2 === void 0 ? void 0 : _discount$metadata2.optionDiscountAmount) || 0);
825
+ }, new Decimal(0));
826
+ };
816
827
  var getBundleIdentity = function getBundleIdentity(bundle) {
817
828
  var _ref21, _bundle$bundle_id, _ref22, _ref23, _bundle$bundle_produc, _ref24, _ref25, _bundle$bundle_varian, _ref26, _bundle$bundle_group_;
818
829
  return [(_ref21 = (_bundle$bundle_id = bundle.bundle_id) !== null && _bundle$bundle_id !== void 0 ? _bundle$bundle_id : bundle.id) !== null && _ref21 !== void 0 ? _ref21 : '', (_ref22 = (_ref23 = (_bundle$bundle_produc = bundle.bundle_product_id) !== null && _bundle$bundle_produc !== void 0 ? _bundle$bundle_produc : bundle._bundle_product_id) !== null && _ref23 !== void 0 ? _ref23 : bundle.product_id) !== null && _ref22 !== void 0 ? _ref22 : '', (_ref24 = (_ref25 = (_bundle$bundle_varian = bundle.bundle_variant_id) !== null && _bundle$bundle_varian !== void 0 ? _bundle$bundle_varian : bundle.variant_id) !== null && _ref25 !== void 0 ? _ref25 : bundle.product_variant_id) !== null && _ref24 !== void 0 ? _ref24 : 0, (_ref26 = (_bundle$bundle_group_ = bundle.bundle_group_id) !== null && _bundle$bundle_group_ !== void 0 ? _bundle$bundle_group_ : bundle.group_id) !== null && _ref26 !== void 0 ? _ref26 : ''].join('|');
@@ -850,12 +861,14 @@ export function createDefaultOrderRulesHooks(getBookings) {
850
861
  var _product$metadata7, _product$metadata8, _product$metadata9, _metadataAny$_promoti;
851
862
  // source_product_price 是权威源;兜底链:source → mainSelling − options(反推)→ 行 selling_price
852
863
  var metadataAny = product.metadata || {};
853
- var optionSum = sumOptionUnitPrice(getProductSkuOptions(product));
864
+ var productOptions = getProductSkuOptions(product);
865
+ var optionSum = sumOptionUnitPrice(productOptions);
866
+ var optionSellingSum = optionSum.minus(getOptionDiscountAmount(product.discount_list));
854
867
  var sourcePrice;
855
868
  if (metadataAny.source_product_price !== undefined) {
856
869
  sourcePrice = String(metadataAny.source_product_price);
857
870
  } else if (metadataAny.main_product_selling_price !== undefined) {
858
- sourcePrice = new Decimal(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString();
871
+ sourcePrice = new Decimal(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString();
859
872
  } else {
860
873
  var _product$selling_pric;
861
874
  sourcePrice = String((_product$selling_pric = product.selling_price) !== null && _product$selling_pric !== void 0 ? _product$selling_pric : 0);
@@ -886,6 +899,12 @@ export function createDefaultOrderRulesHooks(getBookings) {
886
899
  num: product.num || 1,
887
900
  discount_list: product.discount_list || [],
888
901
  bundle: product.product_bundle || [],
902
+ // 仅在 Rules 入参中映射 price,避免折后价污染订单的 add_price。
903
+ options: productOptions.map(function (option) {
904
+ return _objectSpread(_objectSpread({}, option), {}, {
905
+ price: option.add_price
906
+ });
907
+ }),
889
908
  booking_id: ((_product$metadata8 = product.metadata) === null || _product$metadata8 === void 0 ? void 0 : _product$metadata8.booking_id) || null,
890
909
  isClient: false,
891
910
  // 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
@@ -893,20 +912,22 @@ export function createDefaultOrderRulesHooks(getBookings) {
893
912
  isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
894
913
  holder_id: (_product$metadata9 = product.metadata) === null || _product$metadata9 === void 0 ? void 0 : _product$metadata9.holder_id,
895
914
  startDate: getProductStartDate(product),
896
- main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new Decimal(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString() : undefined,
915
+ main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new Decimal(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString() : undefined,
897
916
  inPromotion: ((_metadataAny$_promoti = metadataAny._promotion) === null || _metadataAny$_promoti === void 0 ? void 0 : _metadataAny$_promoti.inPromotion) === true,
898
917
  _promotion: metadataAny._promotion
899
918
  };
900
919
  },
901
920
  setProduct: function setProduct(product, values) {
902
- var _ref32, _values$quantity, _ref33, _metadataAny$source_p, _product$product_sku, _values$discount_list, _values$quantity2;
921
+ var _ref32, _values$quantity, _ref33, _metadataAny$source_p, _values$discount_list, _product$product_sku, _values$quantity2;
903
922
  var nextNum = Number((_ref32 = (_values$quantity = values.quantity) !== null && _values$quantity !== void 0 ? _values$quantity : product.num) !== null && _ref32 !== void 0 ? _ref32 : 1) || 1;
904
923
  var metadataAny = product.metadata || {};
905
924
  var existedSource = (_ref33 = (_metadataAny$source_p = metadataAny.source_product_price) !== null && _metadataAny$source_p !== void 0 ? _metadataAny$source_p : product.selling_price) !== null && _ref33 !== void 0 ? _ref33 : '0';
906
925
  var nextOptions = getProductSkuOptions(product);
907
926
  var optionSum = sumOptionUnitPrice(nextOptions);
927
+ var nextDiscountList = (_values$discount_list = values.discount_list) !== null && _values$discount_list !== void 0 ? _values$discount_list : product.discount_list;
928
+ var optionSellingSum = optionSum.minus(getOptionDiscountAmount(nextDiscountList));
908
929
 
909
- // Rules 返回的 main_product_selling_price / price / total 均为 source-level。
930
+ // Rules 返回的 main_product_selling_price / price 为不含 option 的主商品价。
910
931
  // 优先级:main_product_selling_price(per-unit 券后 source)> price(还原/good_pass 分支)>
911
932
  // total/num(仅当 Rules 只给 total 时的兜底)> 保留当前 source。
912
933
  var nextSourceSellingPrice = values.main_product_selling_price !== undefined ? String(values.main_product_selling_price) : values.price !== undefined ? String(values.price) : values.total !== undefined ? toUnitPriceString(values.total, nextNum) : String(existedSource);
@@ -915,8 +936,8 @@ export function createDefaultOrderRulesHooks(getBookings) {
915
936
  // 缺省时保留现有 source(券前 = 当前 source)。
916
937
  var nextSourceOriginalPrice = values.original_price !== undefined ? String(values.original_price) : String(existedSource);
917
938
 
918
- // 含 option 的 main_product_*
919
- var nextMainSellingPrice = new Decimal(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
939
+ // 成交价只加回 option 折后合计;原价仍使用订单中保存的 option 原价。
940
+ var nextMainSellingPrice = new Decimal(Number(nextSourceSellingPrice) || 0).plus(optionSellingSum).toDecimalPlaces(2).toFixed(2);
920
941
  var nextMainOriginalPrice = new Decimal(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
921
942
  var nextBundle = values.bundle !== undefined ? mergeRulesBundlePrices(product.product_bundle, values.bundle) : product.product_bundle;
922
943
  var composedSellingPrice = composeLinePrice({
@@ -936,7 +957,7 @@ export function createDefaultOrderRulesHooks(getBookings) {
936
957
  return _objectSpread(_objectSpread({}, product), {}, {
937
958
  selling_price: composedSellingPrice,
938
959
  original_price: finalOriginalPrice,
939
- discount_list: (_values$discount_list = values.discount_list) !== null && _values$discount_list !== void 0 ? _values$discount_list : product.discount_list,
960
+ discount_list: nextDiscountList,
940
961
  num: (_values$quantity2 = values.quantity) !== null && _values$quantity2 !== void 0 ? _values$quantity2 : product.num,
941
962
  product_bundle: nextBundle,
942
963
  metadata: _objectSpread(_objectSpread({}, metadataAny), {}, {
@@ -31,6 +31,33 @@ import { FloorPlanHooks } from "./types";
31
31
  var FLOOR_PLAN_SYNC_DEBOUNCE_MS = 3000;
32
32
  var FLOOR_PLAN_STORE_NAME = 'floor_plans';
33
33
 
34
+ /**
35
+ * Request failures can be plain response objects (rather than Error instances).
36
+ * Keep diagnostics useful without allowing the UI bridge to stringify them as
37
+ * "[object Object]".
38
+ */
39
+ function getRequestErrorInfo(error) {
40
+ var _ref, _ref2, _value$resData$res, _value$resData, _value$response, _response$code, _response$status, _value$response2;
41
+ if (error instanceof Error && error.message) return {
42
+ message: error.message
43
+ };
44
+ if (typeof error === 'string' && error) return {
45
+ message: error
46
+ };
47
+ var value = error;
48
+ var response = (_ref = (_ref2 = (_value$resData$res = value === null || value === void 0 || (_value$resData = value.resData) === null || _value$resData === void 0 ? void 0 : _value$resData.res) !== null && _value$resData$res !== void 0 ? _value$resData$res : value === null || value === void 0 || (_value$response = value.response) === null || _value$response === void 0 ? void 0 : _value$response.data) !== null && _ref2 !== void 0 ? _ref2 : value === null || value === void 0 ? void 0 : value.data) !== null && _ref !== void 0 ? _ref : value;
49
+ var candidates = [value === null || value === void 0 ? void 0 : value.message, value === null || value === void 0 ? void 0 : value.error, response === null || response === void 0 ? void 0 : response.message, response === null || response === void 0 ? void 0 : response.error];
50
+ var message = candidates.find(function (candidate) {
51
+ return typeof candidate === 'string' && candidate.trim() !== '';
52
+ });
53
+ return {
54
+ message: message || '平面图加载失败(未提供错误详情)',
55
+ code: (_response$code = response === null || response === void 0 ? void 0 : response.code) !== null && _response$code !== void 0 ? _response$code : value === null || value === void 0 ? void 0 : value.code,
56
+ status: (_response$status = response === null || response === void 0 ? void 0 : response.status) !== null && _response$status !== void 0 ? _response$status : value === null || value === void 0 ? void 0 : value.status,
57
+ httpStatus: value === null || value === void 0 || (_value$response2 = value.response) === null || _value$response2 === void 0 ? void 0 : _value$response2.status
58
+ };
59
+ }
60
+
34
61
  /**
35
62
  * 平面图模块:预加载列表、pubsub 同步、供 OS Server 路由读本地 store
36
63
  */
@@ -230,7 +257,7 @@ export var FloorPlanModule = /*#__PURE__*/function (_BaseModule) {
230
257
  key: "loadListFromServer",
231
258
  value: function () {
232
259
  var _loadListFromServer = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
233
- var res, body, raw, list;
260
+ var res, body, raw, list, errorInfo;
234
261
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
235
262
  while (1) switch (_context2.prev = _context2.next) {
236
263
  case 0:
@@ -248,11 +275,15 @@ export var FloorPlanModule = /*#__PURE__*/function (_BaseModule) {
248
275
  case 10:
249
276
  _context2.prev = 10;
250
277
  _context2.t0 = _context2["catch"](0);
278
+ errorInfo = getRequestErrorInfo(_context2.t0);
251
279
  this.logWarning('loadListFromServer 失败', {
252
- error: _context2.t0 instanceof Error ? _context2.t0.message : String(_context2.t0)
280
+ error: errorInfo.message,
281
+ code: errorInfo.code,
282
+ status: errorInfo.status,
283
+ httpStatus: errorInfo.httpStatus
253
284
  });
254
285
  return _context2.abrupt("return", []);
255
- case 14:
286
+ case 15:
256
287
  case "end":
257
288
  return _context2.stop();
258
289
  }
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 2 | 1 | 6 | 4 | 5 | 3;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -346,7 +346,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
346
346
  * 获取当前的客户搜索条件
347
347
  * @returns 当前搜索条件
348
348
  */
349
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
349
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
350
350
  /**
351
351
  * 获取客户列表状态(包含滚动加载相关状态)
352
352
  * @returns 客户状态
@@ -121,8 +121,9 @@ export declare function getBundleSellingMagnitude(bundle: Record<string, any> |
121
121
  * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
122
122
  * - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
123
123
  * 不含折扣。**权威源**。
124
- * - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
125
- * - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
124
+ * - `product_sku.option[].add_price` 保留单规格折前单价;Rules 的 option.price 只用于本次计算。
125
+ * - `metadata.main_product_original_price` = source + Σ(option.add_price × option.num)(含 option、不含折扣)。
126
+ * - `metadata.main_product_selling_price` = main_original − 行内 per-unit amount(含主商品及 option 优惠)。
126
127
  * - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
127
128
  *
128
129
  * Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
@@ -131,8 +132,9 @@ export declare function getBundleSellingMagnitude(bundle: Record<string, any> |
131
132
  * `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
132
133
  * - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
133
134
  * total(source + option + bundle)对齐。
135
+ * - `getProduct.options` 用单规格原价参与重算;主商品折后价从 main_selling 减去 option 折后合计反推。
134
136
  * - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
135
- * 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
137
+ * 加回单规格原价合计,再减去 optionDiscountAmount;保留订单单规格原价供取消折扣及后续重算。
136
138
  * 优先级:
137
139
  * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
138
140
  * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
@@ -632,8 +632,9 @@ function getBundleSellingMagnitude(bundle) {
632
632
  * = `metadata.main_product_original_price` + Σ(bundle 原价 × num)。
633
633
  * - `metadata.source_product_price`:主商品/variant 基础价(已应用报价单),不含 option、
634
634
  * 不含折扣。**权威源**。
635
- * - `metadata.main_product_original_price` = source + Σ(option.price × option.num)(含 option、不含折扣)。
636
- * - `metadata.main_product_selling_price` = main_original − 主商品券 per-unit amount(含 option、含折扣)。
635
+ * - `product_sku.option[].add_price` 保留单规格折前单价;Rules 的 option.price 只用于本次计算。
636
+ * - `metadata.main_product_original_price` = source + Σ(option.add_price × option.num)(含 option、不含折扣)。
637
+ * - `metadata.main_product_selling_price` = main_original − 行内 per-unit amount(含主商品及 option 优惠)。
637
638
  * - `payment_price`:出站 payload 中为行 composite 已减整单折扣均摊价(无折扣时与 `selling_price` 同义)。
638
639
  *
639
640
  * Rules 钩子契约(hook_adapt 方案,Rules 内部保持不变):
@@ -642,8 +643,9 @@ function getBundleSellingMagnitude(bundle) {
642
643
  * `getProductOriginTotalPrice` 会自行叠加 option + bundle,喂 source 可避免 option 双加。
643
644
  * - `getProduct.total` = `selling_price × num`(行 composite × num),与 Rules 内部产出的
644
645
  * total(source + option + bundle)对齐。
646
+ * - `getProduct.options` 用单规格原价参与重算;主商品折后价从 main_selling 减去 option 折后合计反推。
645
647
  * - `setProduct` 反向流程:把 Rules 返回的 source-level `main_product_selling_price` / `price`
646
- * 加回 Σoptions,重新合成含 option 的 main_product_* 并派生 composite。
648
+ * 加回单规格原价合计,再减去 optionDiscountAmount;保留订单单规格原价供取消折扣及后续重算。
647
649
  * 优先级:
648
650
  * 1. `values.main_product_selling_price`(券应用分支,per-unit 券后 source-level 主价)
649
651
  * 2. `values.price`(还原分支 `restoredPrice`、good_pass 归零)
@@ -842,6 +844,14 @@ function createDefaultOrderRulesHooks(getBookings) {
842
844
  const effectiveNum = Number(num) > 0 ? Number(num) : 1;
843
845
  return new _decimal.default(Number(totalLike) || 0).dividedBy(effectiveNum).toDecimalPlaces(2).toString();
844
846
  };
847
+
848
+ // optionDiscountAmount 已是每件主商品内的单规格优惠合计,不再乘商品数量。
849
+ const getOptionDiscountAmount = discountList => {
850
+ return (discountList || []).reduce((total, discount) => {
851
+ if (discount?.metadata?.custom_product_bundle_map_id) return total;
852
+ return total.plus(Number(discount?.metadata?.optionDiscountAmount) || 0);
853
+ }, new _decimal.default(0));
854
+ };
845
855
  const getBundleIdentity = bundle => {
846
856
  return [bundle.bundle_id ?? bundle.id ?? '', bundle.bundle_product_id ?? bundle._bundle_product_id ?? bundle.product_id ?? '', bundle.bundle_variant_id ?? bundle.variant_id ?? bundle.product_variant_id ?? 0, bundle.bundle_group_id ?? bundle.group_id ?? ''].join('|');
847
857
  };
@@ -884,12 +894,14 @@ function createDefaultOrderRulesHooks(getBookings) {
884
894
  getProduct: product => {
885
895
  // source_product_price 是权威源;兜底链:source → mainSelling − options(反推)→ 行 selling_price
886
896
  const metadataAny = product.metadata || {};
887
- const optionSum = sumOptionUnitPrice(getProductSkuOptions(product));
897
+ const productOptions = getProductSkuOptions(product);
898
+ const optionSum = sumOptionUnitPrice(productOptions);
899
+ const optionSellingSum = optionSum.minus(getOptionDiscountAmount(product.discount_list));
888
900
  let sourcePrice;
889
901
  if (metadataAny.source_product_price !== undefined) {
890
902
  sourcePrice = String(metadataAny.source_product_price);
891
903
  } else if (metadataAny.main_product_selling_price !== undefined) {
892
- sourcePrice = new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString();
904
+ sourcePrice = new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString();
893
905
  } else {
894
906
  sourcePrice = String(product.selling_price ?? 0);
895
907
  }
@@ -919,6 +931,11 @@ function createDefaultOrderRulesHooks(getBookings) {
919
931
  num: product.num || 1,
920
932
  discount_list: product.discount_list || [],
921
933
  bundle: product.product_bundle || [],
934
+ // 仅在 Rules 入参中映射 price,避免折后价污染订单的 add_price。
935
+ options: productOptions.map(option => ({
936
+ ...option,
937
+ price: option.add_price
938
+ })),
922
939
  booking_id: product.metadata?.booking_id || null,
923
940
  isClient: false,
924
941
  // 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
@@ -926,7 +943,7 @@ function createDefaultOrderRulesHooks(getBookings) {
926
943
  isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
927
944
  holder_id: product.metadata?.holder_id,
928
945
  startDate: getProductStartDate(product),
929
- main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSum).toDecimalPlaces(2).toString() : undefined,
946
+ main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString() : undefined,
930
947
  inPromotion: metadataAny._promotion?.inPromotion === true,
931
948
  _promotion: metadataAny._promotion
932
949
  };
@@ -937,8 +954,10 @@ function createDefaultOrderRulesHooks(getBookings) {
937
954
  const existedSource = metadataAny.source_product_price ?? product.selling_price ?? '0';
938
955
  const nextOptions = getProductSkuOptions(product);
939
956
  const optionSum = sumOptionUnitPrice(nextOptions);
957
+ const nextDiscountList = values.discount_list ?? product.discount_list;
958
+ const optionSellingSum = optionSum.minus(getOptionDiscountAmount(nextDiscountList));
940
959
 
941
- // Rules 返回的 main_product_selling_price / price / total 均为 source-level。
960
+ // Rules 返回的 main_product_selling_price / price 为不含 option 的主商品价。
942
961
  // 优先级:main_product_selling_price(per-unit 券后 source)> price(还原/good_pass 分支)>
943
962
  // total/num(仅当 Rules 只给 total 时的兜底)> 保留当前 source。
944
963
  const nextSourceSellingPrice = values.main_product_selling_price !== undefined ? String(values.main_product_selling_price) : values.price !== undefined ? String(values.price) : values.total !== undefined ? toUnitPriceString(values.total, nextNum) : String(existedSource);
@@ -947,8 +966,8 @@ function createDefaultOrderRulesHooks(getBookings) {
947
966
  // 缺省时保留现有 source(券前 = 当前 source)。
948
967
  const nextSourceOriginalPrice = values.original_price !== undefined ? String(values.original_price) : String(existedSource);
949
968
 
950
- // 含 option 的 main_product_*
951
- const nextMainSellingPrice = new _decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
969
+ // 成交价只加回 option 折后合计;原价仍使用订单中保存的 option 原价。
970
+ const nextMainSellingPrice = new _decimal.default(Number(nextSourceSellingPrice) || 0).plus(optionSellingSum).toDecimalPlaces(2).toFixed(2);
952
971
  const nextMainOriginalPrice = new _decimal.default(Number(nextSourceOriginalPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
953
972
  const nextBundle = values.bundle !== undefined ? mergeRulesBundlePrices(product.product_bundle, values.bundle) : product.product_bundle;
954
973
  const composedSellingPrice = composeLinePrice({
@@ -969,7 +988,7 @@ function createDefaultOrderRulesHooks(getBookings) {
969
988
  ...product,
970
989
  selling_price: composedSellingPrice,
971
990
  original_price: finalOriginalPrice,
972
- discount_list: values.discount_list ?? product.discount_list,
991
+ discount_list: nextDiscountList,
973
992
  num: values.quantity ?? product.num,
974
993
  product_bundle: nextBundle,
975
994
  metadata: {
@@ -9,6 +9,30 @@ var _types = require("./types");
9
9
  const FLOOR_PLAN_SYNC_DEBOUNCE_MS = 3000;
10
10
  const FLOOR_PLAN_STORE_NAME = 'floor_plans';
11
11
 
12
+ /**
13
+ * Request failures can be plain response objects (rather than Error instances).
14
+ * Keep diagnostics useful without allowing the UI bridge to stringify them as
15
+ * "[object Object]".
16
+ */
17
+ function getRequestErrorInfo(error) {
18
+ if (error instanceof Error && error.message) return {
19
+ message: error.message
20
+ };
21
+ if (typeof error === 'string' && error) return {
22
+ message: error
23
+ };
24
+ const value = error;
25
+ const response = value?.resData?.res ?? value?.response?.data ?? value?.data ?? value;
26
+ const candidates = [value?.message, value?.error, response?.message, response?.error];
27
+ const message = candidates.find(candidate => typeof candidate === 'string' && candidate.trim() !== '');
28
+ return {
29
+ message: message || '平面图加载失败(未提供错误详情)',
30
+ code: response?.code ?? value?.code,
31
+ status: response?.status ?? value?.status,
32
+ httpStatus: value?.response?.status
33
+ };
34
+ }
35
+
12
36
  /**
13
37
  * 平面图模块:预加载列表、pubsub 同步、供 OS Server 路由读本地 store
14
38
  */
@@ -144,8 +168,12 @@ class FloorPlanModule extends _BaseModule.BaseModule {
144
168
  const list = Array.isArray(raw) ? raw : [];
145
169
  return list;
146
170
  } catch (e) {
171
+ const errorInfo = getRequestErrorInfo(e);
147
172
  this.logWarning('loadListFromServer 失败', {
148
- error: e instanceof Error ? e.message : String(e)
173
+ error: errorInfo.message,
174
+ code: errorInfo.code,
175
+ status: errorInfo.status,
176
+ httpStatus: errorInfo.httpStatus
149
177
  });
150
178
  return [];
151
179
  }
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 2 | 1 | 6 | 4 | 5 | 3;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -346,7 +346,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
346
346
  * 获取当前的客户搜索条件
347
347
  * @returns 当前搜索条件
348
348
  */
349
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
349
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
350
350
  /**
351
351
  * 获取客户列表状态(包含滚动加载相关状态)
352
352
  * @returns 客户状态
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.310",
4
+ "version": "2.2.311",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",