@pisell/pisellos 2.2.164 → 2.2.165

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 (34) hide show
  1. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +45 -15
  2. package/dist/modules/Order/index.d.ts +10 -3
  3. package/dist/modules/Order/index.js +272 -142
  4. package/dist/modules/Order/types.d.ts +14 -2
  5. package/dist/modules/Order/types.js +2 -0
  6. package/dist/modules/Order/utils.d.ts +10 -0
  7. package/dist/modules/Order/utils.js +67 -15
  8. package/dist/server/index.js +1 -0
  9. package/dist/solution/BaseSales/index.d.ts +9 -1
  10. package/dist/solution/BaseSales/index.js +369 -240
  11. package/dist/solution/BaseSales/types.d.ts +3 -0
  12. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +33 -14
  13. package/dist/solution/BaseSales/utils.js +36 -7
  14. package/dist/solution/BookingTicket/index.d.ts +3 -0
  15. package/dist/solution/BookingTicket/index.js +155 -86
  16. package/dist/solution/BookingTicket/utils/addProductDecision.js +19 -11
  17. package/dist/solution/ScanOrder/utils.js +36 -7
  18. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +35 -9
  19. package/lib/modules/Order/index.d.ts +10 -3
  20. package/lib/modules/Order/index.js +104 -4
  21. package/lib/modules/Order/types.d.ts +14 -2
  22. package/lib/modules/Order/utils.d.ts +10 -0
  23. package/lib/modules/Order/utils.js +58 -9
  24. package/lib/server/index.js +1 -0
  25. package/lib/solution/BaseSales/index.d.ts +9 -1
  26. package/lib/solution/BaseSales/index.js +65 -3
  27. package/lib/solution/BaseSales/types.d.ts +3 -0
  28. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +31 -10
  29. package/lib/solution/BaseSales/utils.js +37 -5
  30. package/lib/solution/BookingTicket/index.d.ts +3 -0
  31. package/lib/solution/BookingTicket/index.js +48 -6
  32. package/lib/solution/BookingTicket/utils/addProductDecision.js +16 -8
  33. package/lib/solution/ScanOrder/utils.js +37 -5
  34. package/package.json +1 -1
@@ -47,6 +47,8 @@ __export(utils_exports, {
47
47
  normalizeBookingSubType: () => normalizeBookingSubType,
48
48
  normalizeSubmitBooking: () => normalizeSubmitBooking,
49
49
  normalizeSubmitCollectPaxValue: () => normalizeSubmitCollectPaxValue,
50
+ resolveManualOverrideLineOriginalPrice: () => resolveManualOverrideLineOriginalPrice,
51
+ resolveRulesManualDiscountFlag: () => resolveRulesManualDiscountFlag,
50
52
  resolveSubmitCollectPax: () => resolveSubmitCollectPax,
51
53
  sumOptionUnitPrice: () => sumOptionUnitPrice
52
54
  });
@@ -80,6 +82,36 @@ function sumOptionUnitPrice(options) {
80
82
  }
81
83
  return total;
82
84
  }
85
+ function resolveRulesManualDiscountFlag(metadata) {
86
+ if (!metadata)
87
+ return void 0;
88
+ if (metadata.is_manual_discount === true || metadata.is_manual_discount === 1) {
89
+ return true;
90
+ }
91
+ const priceOverride = metadata.price_override;
92
+ if (priceOverride !== void 0 && priceOverride !== null && priceOverride !== "") {
93
+ return true;
94
+ }
95
+ return void 0;
96
+ }
97
+ function resolveManualOverrideLineOriginalPrice(params, fallbackCompositeOriginal) {
98
+ var _a, _b;
99
+ const metadata = params.metadata || {};
100
+ const priceOverride = metadata.price_override;
101
+ if (priceOverride === void 0 || priceOverride === null || priceOverride === "") {
102
+ return fallbackCompositeOriginal;
103
+ }
104
+ const refTotal = (_b = (_a = metadata.origin) == null ? void 0 : _a._extend) == null ? void 0 : _b.origin_total;
105
+ if (refTotal === void 0 || refTotal === null || refTotal === "") {
106
+ return fallbackCompositeOriginal;
107
+ }
108
+ const parsed = Number(refTotal);
109
+ if (!Number.isFinite(parsed)) {
110
+ return fallbackCompositeOriginal;
111
+ }
112
+ const num = Number(params.num) > 0 ? Number(params.num) : 1;
113
+ return new import_decimal.default(parsed).dividedBy(num).toDecimalPlaces(2).toFixed(2);
114
+ }
83
115
  function createDefaultOrderRulesHooks() {
84
116
  const toUnitPriceString = (totalLike, num) => {
85
117
  const effectiveNum = Number(num) > 0 ? Number(num) : 1;
@@ -87,7 +119,7 @@ function createDefaultOrderRulesHooks() {
87
119
  };
88
120
  return {
89
121
  getProduct: (product) => {
90
- var _a, _b, _c, _d, _e, _f;
122
+ var _a, _b, _c, _d, _e;
91
123
  const metadataAny = product.metadata || {};
92
124
  const optionSum = sumOptionUnitPrice(product.product_option_item);
93
125
  let sourcePrice;
@@ -135,9 +167,11 @@ function createDefaultOrderRulesHooks() {
135
167
  bundle: product.product_bundle || [],
136
168
  booking_id: ((_b = product.metadata) == null ? void 0 : _b.booking_id) || null,
137
169
  isClient: false,
138
- isManualDiscount: ((_c = product.metadata) == null ? void 0 : _c.is_manual_discount) || false,
139
- holder_id: (_d = product.metadata) == null ? void 0 : _d.holder_id,
140
- startDate: ((_e = product.metadata) == null ? void 0 : _e.start_date) || ((_f = product.metadata) == null ? void 0 : _f.startDate)
170
+ // 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
171
+ // 无券时会把 bundle 价还原成 original_price(手动改价套餐会从 20 回到 30)。
172
+ isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
173
+ holder_id: (_c = product.metadata) == null ? void 0 : _c.holder_id,
174
+ startDate: ((_d = product.metadata) == null ? void 0 : _d.start_date) || ((_e = product.metadata) == null ? void 0 : _e.startDate)
141
175
  };
142
176
  },
143
177
  setProduct: (product, values) => {
@@ -160,10 +194,14 @@ function createDefaultOrderRulesHooks() {
160
194
  bundle: nextBundle,
161
195
  useOriginalBundle: true
162
196
  });
197
+ const finalOriginalPrice = resolveManualOverrideLineOriginalPrice(
198
+ { num: nextNum, metadata: metadataAny },
199
+ composedOriginalPrice
200
+ );
163
201
  return {
164
202
  ...product,
165
203
  selling_price: composedSellingPrice,
166
- original_price: composedOriginalPrice,
204
+ original_price: finalOriginalPrice,
167
205
  discount_list: values.discount_list ?? product.discount_list,
168
206
  num: values.quantity ?? product.num,
169
207
  product_bundle: nextBundle,
@@ -428,8 +466,8 @@ function createDefaultTempOrder(params) {
428
466
  order_number: null,
429
467
  shop_order_number: null,
430
468
  shop_full_order_number: null,
431
- type: "appointment_booking",
432
- business_code: "appointment_booking",
469
+ type: "",
470
+ business_code: void 0,
433
471
  platform: "h5",
434
472
  sales_channel: "my_pisel",
435
473
  order_sales_channel: "online_store",
@@ -471,6 +509,7 @@ function createDefaultTempOrder(params) {
471
509
  };
472
510
  }
473
511
  function buildSubmitPayload(params) {
512
+ var _a;
474
513
  const {
475
514
  tempOrder,
476
515
  cacheId,
@@ -503,6 +542,14 @@ function buildSubmitPayload(params) {
503
542
  holder_id: _holderId,
504
543
  ...tempOrderRest
505
544
  } = tempOrder;
545
+ let submitType = type ?? tempOrder.type;
546
+ if (!submitType) {
547
+ if ((_a = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _a.length) {
548
+ submitType = "appointment_booking";
549
+ } else {
550
+ submitType = "virtual";
551
+ }
552
+ }
506
553
  const payload = {
507
554
  ...tempOrderRest,
508
555
  order_number: null,
@@ -510,8 +557,8 @@ function buildSubmitPayload(params) {
510
557
  shop_full_order_number: null,
511
558
  platform: normalizeSubmitPlatform(platform),
512
559
  request_unique_idempotency_token: tempOrder.request_unique_idempotency_token || `${tempOrder.external_sale_number}_${now.getTime()}`,
513
- type: type ?? tempOrder.type ?? "table-order",
514
- business_code: businessCode ?? tempOrder.business_code ?? "table-order",
560
+ type: submitType,
561
+ business_code: businessCode ?? tempOrder.business_code,
515
562
  sales_channel: tempOrder.sales_channel || "my_pisel",
516
563
  order_sales_channel: channel ?? tempOrder.order_sales_channel ?? "online_store",
517
564
  status: tempOrder.status || "normal",
@@ -632,6 +679,8 @@ function formatV1Product(products) {
632
679
  normalizeBookingSubType,
633
680
  normalizeSubmitBooking,
634
681
  normalizeSubmitCollectPaxValue,
682
+ resolveManualOverrideLineOriginalPrice,
683
+ resolveRulesManualDiscountFlag,
635
684
  resolveSubmitCollectPax,
636
685
  sumOptionUnitPrice
637
686
  });
@@ -1870,6 +1870,7 @@ var Server = class {
1870
1870
  return;
1871
1871
  searchParams.append("with[]", String(field));
1872
1872
  });
1873
+ searchParams.append("lookup_mode", "multi");
1873
1874
  const query = searchParams.toString();
1874
1875
  return `/shop/order/sales/${encodeURIComponent(orderId)}${query ? `?${query}` : ""}`;
1875
1876
  }
@@ -1,6 +1,6 @@
1
1
  import { Module, ModuleOptions, PisellCore } from '../../types';
2
2
  import { BaseModule } from '../../modules/BaseModule';
3
- import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentStatus, BaseSalesCalculateProductBookingPriceParams, BaseSalesProductBookingPriceResult, BaseSalesScanCodeResult } from './types';
3
+ import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentStatus, BaseSalesUpdateOrderProductQuantityParams, BaseSalesCalculateProductBookingPriceParams, BaseSalesProductBookingPriceResult, BaseSalesScanCodeResult } from './types';
4
4
  import { OrderModule } from '../../modules/Order';
5
5
  import type { AddProductBookingInput, LoadSalesDetailParams, OrderPaymentData, OrderPaymentSource, SendCustomerPayLinkParams, SyncPaymentsToOrderParams, SyncPaymentsToOrderResult, UpdateTempOrderCustomerInput, UpdateOrderBookingParams, UpdateOrderProductParams, OrderTempOrder } from '../../modules/Order/types';
6
6
  import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
@@ -110,15 +110,22 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
110
110
  updateTempOrderNote(note: string): string;
111
111
  updateTempOrderNote(note: string, sync: true): Promise<string>;
112
112
  updateTempOrderNote(note: string, sync: boolean): string | Promise<string>;
113
+ updateRemoteOrderNote(orderId: number | string, note: string): void;
113
114
  updateTempOrderShopDiscount(amount: string | number): string;
114
115
  updateTempOrderContactsInfo(contactsInfo: Record<string, any> | null): Record<string, any> | null;
115
116
  private ensureTempOrder;
116
117
  addNewOrder(): Promise<OrderTempOrder>;
117
118
  saveDraft(): Promise<void>;
118
119
  restoreOrder(): Promise<OrderTempOrder>;
120
+ /**
121
+ * 仅清空 tempOrder 购物车行(products / bookings / discount_list)。
122
+ * 同步清空内存中的 salesDetail 商品/预约视图,避免编辑态仍读到旧 bookings。
123
+ */
124
+ clearOrderCartLines(): Promise<OrderTempOrder>;
119
125
  getOrderProducts(): import("../../modules/Order/types").OrderProduct[];
120
126
  getSummary(): Promise<import("../../modules/Order/types").OrderSummary>;
121
127
  private getHistoricalProductDiscountList;
128
+ private isPersistedOrderProduct;
122
129
  private mergeHistoricalDiscountList;
123
130
  loadDiscountConfig(params?: {
124
131
  customerId?: number;
@@ -215,6 +222,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
215
222
  calculateProductBookingPrice(params: BaseSalesCalculateProductBookingPriceParams): Promise<BaseSalesProductBookingPriceResult>;
216
223
  addProductToOrder(product: Partial<BaseSalesOrderProduct> & BaseSalesOrderProductIdentity, booking?: AddProductBookingInput): Promise<import("../../modules/Order/types").OrderProduct[]>;
217
224
  updateOrderProduct(params: UpdateOrderProductParams): Promise<import("../../modules/Order/types").OrderProduct[]>;
225
+ updateOrderProductQuantity(params: BaseSalesUpdateOrderProductQuantityParams): Promise<import("../../modules/Order/types").OrderProduct[]>;
218
226
  updateOrderBooking(params: UpdateOrderBookingParams): any[];
219
227
  /**
220
228
  * 设置单行商品备注(与整单 `updateTempOrderNote` 区分)。
@@ -401,6 +401,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
401
401
  throw error;
402
402
  }
403
403
  }
404
+ updateRemoteOrderNote(orderId, note) {
405
+ if (!this.store.order)
406
+ throw new Error("order 模块未初始化");
407
+ this.store.order.syncTempOrderNoteToRemote(orderId, note);
408
+ }
404
409
  updateTempOrderShopDiscount(amount) {
405
410
  if (!this.store.order)
406
411
  throw new Error("order 模块未初始化");
@@ -444,6 +449,37 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
444
449
  throw new Error("scanOrder 解决方案需要 order 模块支持");
445
450
  }
446
451
  const tempOrder = this.store.order.restoreOrder();
452
+ this.currentSalesDetail = null;
453
+ await this.effectsEmit("onTempOrderReplaced", { tempOrder });
454
+ if (this.syncAppDataToTempOrder(tempOrder)) {
455
+ this.store.order.persistTempOrder();
456
+ await this.store.order.saveDraft();
457
+ }
458
+ return tempOrder;
459
+ } catch (error) {
460
+ throw error;
461
+ }
462
+ }
463
+ /**
464
+ * 仅清空 tempOrder 购物车行(products / bookings / discount_list)。
465
+ * 同步清空内存中的 salesDetail 商品/预约视图,避免编辑态仍读到旧 bookings。
466
+ */
467
+ async clearOrderCartLines() {
468
+ try {
469
+ if (!this.store.order)
470
+ throw new Error("order 模块未初始化");
471
+ const tempOrder = await this.store.order.clearOrderCartLines();
472
+ if (this.currentSalesDetail) {
473
+ this.currentSalesDetail = {
474
+ ...this.currentSalesDetail,
475
+ products: [],
476
+ bookings: [],
477
+ rootBooking: null,
478
+ bookingsByProductUid: {},
479
+ discount_list: []
480
+ };
481
+ }
482
+ await this.effectsEmit("onTempOrderReplaced", { tempOrder });
447
483
  if (this.syncAppDataToTempOrder(tempOrder)) {
448
484
  this.store.order.persistTempOrder();
449
485
  await this.store.order.saveDraft();
@@ -472,6 +508,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
472
508
  getHistoricalProductDiscountList(products) {
473
509
  const historyDiscountList = [];
474
510
  products.forEach((item) => {
511
+ if (!this.isPersistedOrderProduct(item))
512
+ return;
475
513
  (item.discount_list || []).forEach((discount) => {
476
514
  var _a, _b, _c, _d, _e, _f;
477
515
  const discountId = ((_a = discount.discount) == null ? void 0 : _a.resource_id) || discount.id;
@@ -506,6 +544,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
506
544
  });
507
545
  return historyDiscountList;
508
546
  }
547
+ isPersistedOrderProduct(product) {
548
+ const orderDetailId = product.order_detail_id ?? product.orderDetailId;
549
+ if (orderDetailId !== void 0 && orderDetailId !== null && orderDetailId !== "") {
550
+ return true;
551
+ }
552
+ const bookingId = product.booking_id ?? product.bookingId;
553
+ return bookingId !== void 0 && bookingId !== null && bookingId !== "";
554
+ }
509
555
  mergeHistoricalDiscountList(discountList, products) {
510
556
  const historyDiscountList = this.getHistoricalProductDiscountList(products);
511
557
  const historyIds = new Set(historyDiscountList.map((discount) => discount.id));
@@ -791,7 +837,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
791
837
  async syncPaymentsToOrder(params) {
792
838
  if (!this.store.order)
793
839
  throw new Error("order 模块未初始化");
794
- return this.store.order.syncPaymentsToOrder(params);
840
+ const channel = params.channel ?? this.getSubmitOrderSalesChannel();
841
+ return this.store.order.syncPaymentsToOrder({
842
+ ...params,
843
+ ...channel !== void 0 ? { channel } : {}
844
+ });
795
845
  }
796
846
  /** 读取当前 BaseSales 订单上下文中的 Sales 协议支付项。 */
797
847
  getOrderPayments() {
@@ -858,8 +908,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
858
908
  const bundleMetadata = bundle.metadata || {};
859
909
  return {
860
910
  is_price_include_tax: tempOrder.is_price_include_tax,
861
- bundle_id: bundle.bundle_id,
862
- bundle_product_id: bundle.bundle_product_id,
911
+ // 套餐子项在 tempOrder 上常为 id(如 1718),prepare/deduction 协议要求 bundle_id
912
+ bundle_id: bundle.bundle_id ?? bundle.id,
913
+ bundle_product_id: bundle.bundle_product_id ?? bundle._bundle_product_id,
914
+ bundle_group_id: bundle.bundle_group_id ?? bundle.group_id,
863
915
  bundle_variant_id: bundle.bundle_variant_id,
864
916
  price_type: bundle.price_type,
865
917
  price_type_ext: bundle.price_type_ext,
@@ -1032,6 +1084,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1032
1084
  throw error;
1033
1085
  }
1034
1086
  }
1087
+ async updateOrderProductQuantity(params) {
1088
+ try {
1089
+ if (!this.store.order)
1090
+ throw new Error("order 模块未初始化");
1091
+ const products = await this.store.order.updateOrderProductQuantity(params);
1092
+ return products;
1093
+ } catch (error) {
1094
+ throw error;
1095
+ }
1096
+ }
1035
1097
  updateOrderBooking(params) {
1036
1098
  try {
1037
1099
  if (!this.store.order)
@@ -42,6 +42,9 @@ export interface BaseSalesOrderProductIdentity {
42
42
  product_option_item?: any[];
43
43
  product_bundle?: any[];
44
44
  }
45
+ export interface BaseSalesUpdateOrderProductQuantityParams extends BaseSalesOrderProductIdentity {
46
+ num: number;
47
+ }
45
48
  export interface BaseSalesOrderProduct extends BaseSalesOrderProductIdentity {
46
49
  order_detail_id: number | null;
47
50
  num: number;
@@ -62,13 +62,23 @@ function normalizeOptionItems(optionItems) {
62
62
  };
63
63
  });
64
64
  }
65
- function normalizeBundleItems(bundleItems) {
65
+ function normalizeBundleItems(bundleItems, preferPriceField = false) {
66
66
  if (!Array.isArray(bundleItems))
67
67
  return [];
68
- return bundleItems.map((bundleItem) => ({
69
- ...bundleItem,
70
- option: normalizeOptionItems(bundleItem == null ? void 0 : bundleItem.option)
71
- }));
68
+ return bundleItems.map((bundleItem) => {
69
+ const unitSelling = preferPriceField ? bundleItem.price ?? bundleItem.bundle_selling_price ?? bundleItem.custom_price ?? bundleItem.product_price ?? "0" : bundleItem.bundle_selling_price ?? bundleItem.price ?? bundleItem.custom_price ?? bundleItem.product_price ?? "0";
70
+ const unitStr = toPriceString(unitSelling, "0.00");
71
+ const num = toSafePositiveInt((bundleItem == null ? void 0 : bundleItem.num) ?? (bundleItem == null ? void 0 : bundleItem.quantity), 1);
72
+ return {
73
+ ...bundleItem,
74
+ num,
75
+ quantity: (bundleItem == null ? void 0 : bundleItem.quantity) ?? num,
76
+ price: bundleItem.price ?? unitStr,
77
+ bundle_selling_price: unitStr,
78
+ original_price: bundleItem.original_price ?? bundleItem.product_price ?? bundleItem.price ?? unitStr,
79
+ option: normalizeOptionItems(bundleItem == null ? void 0 : bundleItem.option)
80
+ };
81
+ });
72
82
  }
73
83
  function findVariantById(origin, variantId) {
74
84
  if (!origin || !variantId || variantId <= 0)
@@ -77,7 +87,7 @@ function findVariantById(origin, variantId) {
77
87
  return variants.find((variant) => Number(variant == null ? void 0 : variant.id) === variantId) || null;
78
88
  }
79
89
  function transformBaseProductToOrderProduct(params) {
80
- var _a, _b;
90
+ var _a, _b, _c;
81
91
  const { payload, fallbackProductId = null } = params;
82
92
  if (!payload || typeof payload !== "object")
83
93
  return null;
@@ -101,11 +111,17 @@ function transformBaseProductToOrderProduct(params) {
101
111
  payload.price ?? payload.selling_price ?? (matchedVariant == null ? void 0 : matchedVariant.price) ?? (matchedVariant == null ? void 0 : matchedVariant.base_price) ?? (origin == null ? void 0 : origin.price) ?? (origin == null ? void 0 : origin.base_price) ?? (sourceProduct == null ? void 0 : sourceProduct.price) ?? (sourceProduct == null ? void 0 : sourceProduct.selling_price) ?? (sourceProduct == null ? void 0 : sourceProduct.base_price),
102
112
  "0.00"
103
113
  );
114
+ const lineCompositeTotal = toPriceString(
115
+ payload.line_total ?? payload.total ?? ((_c = payload._extend) == null ? void 0 : _c.total),
116
+ sourceProductPrice
117
+ );
118
+ const hasPriceOverride = payload.price_override !== void 0 && payload.price_override !== null && payload.price_override !== "";
104
119
  const productOptionItem = normalizeOptionItems(
105
120
  payload.option ?? payload.options ?? payload.product_option_item
106
121
  );
107
122
  const productBundle = normalizeBundleItems(
108
- payload.bundle ?? payload.product_bundle
123
+ payload.bundle ?? payload.product_bundle,
124
+ hasPriceOverride
109
125
  );
110
126
  const uniqueIdentificationNumber = payload.unique_identification_number ?? payload.unique;
111
127
  const metadata = {
@@ -119,7 +135,11 @@ function transformBaseProductToOrderProduct(params) {
119
135
  policy_id: payload.policy_id,
120
136
  source_shop_id: payload.source_shop_id,
121
137
  origin,
122
- source_product_price: sourceProductPrice
138
+ source_product_price: sourceProductPrice,
139
+ main_product_selling_price: sourceProductPrice,
140
+ main_product_original_price: sourceProductPrice,
141
+ ...hasPriceOverride ? { price_override: String(payload.price_override) } : {},
142
+ ...payload.bundle_edit !== void 0 ? { bundle_edit: payload.bundle_edit } : {}
123
143
  };
124
144
  if (uniqueIdentificationNumber) {
125
145
  metadata.unique_identification_number = String(uniqueIdentificationNumber);
@@ -131,8 +151,9 @@ function transformBaseProductToOrderProduct(params) {
131
151
  num: toSafePositiveInt(payload.quantity ?? payload.num, 1),
132
152
  product_option_item: productOptionItem,
133
153
  product_bundle: productBundle,
134
- selling_price: sourceProductPrice,
135
- original_price: sourceProductPrice,
154
+ // 折后行价由 normalizeOrderProduct 按 main + bundle 合成;手动改价时 bundle 已为分摊后单价
155
+ selling_price: lineCompositeTotal,
156
+ original_price: lineCompositeTotal,
136
157
  tax_fee: toPriceString(
137
158
  payload.tax_fee ?? (matchedVariant == null ? void 0 : matchedVariant.tax_fee) ?? (origin == null ? void 0 : origin.tax_fee) ?? (sourceProduct == null ? void 0 : sourceProduct.tax_fee),
138
159
  "0.00"
@@ -102,12 +102,40 @@ function isSkuOnlyDeleteIdentity(x) {
102
102
  return !("product_option_item" in x) && !("product_bundle" in x);
103
103
  }
104
104
  function normalizeOrderProduct(product) {
105
- var _a, _b, _c;
105
+ var _a, _b, _c, _d, _e, _f;
106
106
  const metadata = { ...product.metadata || {} };
107
107
  const resolvedIdentityKey = ((_a = product.metadata) == null ? void 0 : _a.unique_identification_number) ? String(product.metadata.unique_identification_number) : product.unique_identification_number && String(product.unique_identification_number).length > 0 ? String(product.unique_identification_number) : product.identity_key && String(product.identity_key).length > 0 ? String(product.identity_key) : (0, import_utils.createUuidV4)();
108
108
  metadata.unique_identification_number = resolvedIdentityKey;
109
- const normalizedBundle = (product.product_bundle || []).map((item) => ({
109
+ const priceOverride = metadata.price_override;
110
+ const originOtherBundle = (_d = (_c = (_b = metadata.origin) == null ? void 0 : _b._extend) == null ? void 0 : _c.other) == null ? void 0 : _d.bundle;
111
+ let bundleInput = product.product_bundle || [];
112
+ if (priceOverride !== void 0 && priceOverride !== null && priceOverride !== "" && Array.isArray(originOtherBundle) && originOtherBundle.length > 0) {
113
+ const priceById = /* @__PURE__ */ new Map();
114
+ originOtherBundle.forEach((item) => {
115
+ if ((item == null ? void 0 : item.id) == null)
116
+ return;
117
+ const unit = item.price ?? item.bundle_selling_price;
118
+ if (unit === void 0 || unit === null)
119
+ return;
120
+ priceById.set(String(item.id), String(unit));
121
+ });
122
+ const base = Array.isArray(bundleInput) && bundleInput.length > 0 ? bundleInput : originOtherBundle;
123
+ bundleInput = base.map((item) => {
124
+ const unit = priceById.get(String(item == null ? void 0 : item.id));
125
+ if (unit === void 0)
126
+ return item;
127
+ return {
128
+ ...item,
129
+ price: unit,
130
+ bundle_selling_price: unit
131
+ };
132
+ });
133
+ }
134
+ const normalizedBundle = bundleInput.map((item) => ({
110
135
  ...item,
136
+ bundle_id: item.bundle_id ?? item.id,
137
+ bundle_product_id: item.bundle_product_id ?? item._bundle_product_id,
138
+ bundle_group_id: item.bundle_group_id ?? item.group_id,
111
139
  bundle_selling_price: item.bundle_selling_price ?? item.price ?? "0.00",
112
140
  price: item.price ?? item.custom_price ?? item.bundle_selling_price ?? "0.00",
113
141
  price_type: item.price_type ?? item.custom_price_type ?? "",
@@ -117,8 +145,8 @@ function normalizeOrderProduct(product) {
117
145
  const optionSum = (0, import_utils.sumOptionUnitPrice)(normalizedOptions);
118
146
  const isV2 = metadata.price_schema_version === 2 || metadata.price_schema_version === "2";
119
147
  const variantId = Number(product.product_variant_id || 0);
120
- const variantList = variantId ? (_b = metadata == null ? void 0 : metadata.origin) == null ? void 0 : _b.variant : null;
121
- const variantPrice = Array.isArray(variantList) ? (_c = variantList.find((v) => Number(v == null ? void 0 : v.id) === variantId)) == null ? void 0 : _c.price : void 0;
148
+ const variantList = variantId ? (_e = metadata == null ? void 0 : metadata.origin) == null ? void 0 : _e.variant : null;
149
+ const variantPrice = Array.isArray(variantList) ? (_f = variantList.find((v) => Number(v == null ? void 0 : v.id) === variantId)) == null ? void 0 : _f.price : void 0;
122
150
  const resolvedSource = (() => {
123
151
  var _a2, _b2;
124
152
  if (metadata.source_product_price !== void 0) {
@@ -174,6 +202,10 @@ function normalizeOrderProduct(product) {
174
202
  bundle: normalizedBundle,
175
203
  useOriginalBundle: true
176
204
  });
205
+ const finalOriginalPrice = (0, import_utils.resolveManualOverrideLineOriginalPrice)(
206
+ { num: product.num, metadata },
207
+ composedOriginalPrice
208
+ );
177
209
  return {
178
210
  order_detail_id: product.order_detail_id || null,
179
211
  product_id: product.product_id,
@@ -181,7 +213,7 @@ function normalizeOrderProduct(product) {
181
213
  product_variant_id: product.product_variant_id,
182
214
  product_option_item: normalizedOptions,
183
215
  selling_price: composedSellingPrice,
184
- original_price: composedOriginalPrice,
216
+ original_price: finalOriginalPrice,
185
217
  tax_fee: product.tax_fee || "0.00",
186
218
  is_charge_tax: product.is_charge_tax ?? 0,
187
219
  discount_list: product.discount_list || [],
@@ -21,6 +21,8 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
21
21
  private platform;
22
22
  private scan;
23
23
  private productCatalog;
24
+ private orderCustomerDiscountRefreshInFlight;
25
+ private orderCustomerDiscountRefreshCustomerId;
24
26
  /**
25
27
  * 在 BaseSales 默认模块清单(products/order/salesSummary/schedule)基础上追加 customer + bookingContext。
26
28
  * bookingContext 是 SalesSdk 加车下沉所需的「预约 UI 上下文」(bookingConfig / resourcesOrigin / date)。
@@ -205,6 +207,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
205
207
  restoreOrder(): Promise<import("../../modules/Order/types").OrderTempOrder>;
206
208
  /** 内部:基于 OrderModule 当前状态构造一份 OrderCustomerChangePayload。 */
207
209
  private buildOrderCustomerPayload;
210
+ private refreshDiscountConfigAfterOrderCustomerChange;
208
211
  /**
209
212
  * 获取客户分页信息
210
213
  * @returns 分页信息
@@ -58,6 +58,8 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
58
58
  */
59
59
  this.store = {};
60
60
  this.productCatalog = [];
61
+ this.orderCustomerDiscountRefreshInFlight = null;
62
+ this.orderCustomerDiscountRefreshCustomerId = null;
61
63
  }
62
64
  /**
63
65
  * 在 BaseSales 默认模块清单(products/order/salesSummary/schedule)基础上追加 customer + bookingContext。
@@ -104,19 +106,30 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
104
106
  console.log(sales, "1234sales");
105
107
  const customerModule = this.store.customer;
106
108
  const detailCustomer = sales == null ? void 0 : sales.customer;
107
- if (customerModule && detailCustomer) {
108
- const { id: detailCustomerId, ...detailCustomerRest } = detailCustomer ?? {};
109
+ const orderCustomerSnapshot = this.store.order.getOrderCustomerSnapshot();
110
+ const protocolCustomerId = sales == null ? void 0 : sales.customer_id;
111
+ const protocolCustomer = protocolCustomerId !== void 0 && protocolCustomerId !== null ? {
112
+ id: protocolCustomerId,
113
+ name: String((sales == null ? void 0 : sales.customer_name) || ""),
114
+ phone: sales == null ? void 0 : sales.phone,
115
+ email: sales == null ? void 0 : sales.email,
116
+ country_calling_code: sales == null ? void 0 : sales.country_calling_code
117
+ } : null;
118
+ const selectedCustomer = detailCustomer ?? orderCustomerSnapshot ?? protocolCustomer;
119
+ if (customerModule && selectedCustomer) {
120
+ const { id: detailCustomerId, ...detailCustomerRest } = selectedCustomer ?? {};
109
121
  const rawId = detailCustomerId ?? "";
110
122
  const customer = {
111
123
  ...detailCustomerRest,
112
124
  id: rawId == null ? "" : rawId,
113
- name: (detailCustomer == null ? void 0 : detailCustomer.name) ?? "",
114
- phone: detailCustomer == null ? void 0 : detailCustomer.phone,
115
- email: detailCustomer == null ? void 0 : detailCustomer.email,
116
- country_calling_code: detailCustomer == null ? void 0 : detailCustomer.country_calling_code
125
+ name: (selectedCustomer == null ? void 0 : selectedCustomer.name) ?? "",
126
+ phone: selectedCustomer == null ? void 0 : selectedCustomer.phone,
127
+ email: selectedCustomer == null ? void 0 : selectedCustomer.email,
128
+ country_calling_code: selectedCustomer == null ? void 0 : selectedCustomer.country_calling_code
117
129
  };
118
130
  customerModule.setSelectedCustomer(customer);
119
131
  this.setOrderCustomer(customer);
132
+ await this.store.order.saveDraft();
120
133
  }
121
134
  return sales;
122
135
  }
@@ -400,6 +413,7 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
400
413
  this.store.order.setOrderCustomer(patch, customer);
401
414
  const next = this.buildOrderCustomerPayload();
402
415
  this.core.effects.emit(`${this.name}:onOrderCustomerChange`, next);
416
+ this.refreshDiscountConfigAfterOrderCustomerChange(patch.customer_id);
403
417
  }
404
418
  /**
405
419
  * 读取 tempOrder 上的下单客户协议字段;customer_id 缺失时返回 null。
@@ -446,6 +460,34 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
446
460
  snapshot: this.store.order.getOrderCustomerSnapshot()
447
461
  };
448
462
  }
463
+ refreshDiscountConfigAfterOrderCustomerChange(customerId) {
464
+ if (!customerId || customerId === 1)
465
+ return;
466
+ if (this.orderCustomerDiscountRefreshInFlight && this.orderCustomerDiscountRefreshCustomerId === customerId) {
467
+ return;
468
+ }
469
+ const previousRefresh = this.orderCustomerDiscountRefreshInFlight;
470
+ const refreshTask = (async () => {
471
+ if (previousRefresh) {
472
+ await previousRefresh.catch(() => void 0);
473
+ }
474
+ const currentCustomer = this.store.order.getOrderCustomer();
475
+ if (!currentCustomer || Number(currentCustomer.customer_id) !== customerId) {
476
+ return;
477
+ }
478
+ await this.loadDiscountConfig({ customerId });
479
+ })();
480
+ this.orderCustomerDiscountRefreshInFlight = refreshTask;
481
+ this.orderCustomerDiscountRefreshCustomerId = customerId;
482
+ refreshTask.catch((error) => {
483
+ console.error("Failed to load discount config after customer change:", error);
484
+ }).finally(() => {
485
+ if (this.orderCustomerDiscountRefreshInFlight !== refreshTask)
486
+ return;
487
+ this.orderCustomerDiscountRefreshInFlight = null;
488
+ this.orderCustomerDiscountRefreshCustomerId = null;
489
+ });
490
+ }
449
491
  /**
450
492
  * 获取客户分页信息
451
493
  * @returns 分页信息
@@ -200,7 +200,8 @@ function buildCacheItemFromCartDetail(item, ctx) {
200
200
  item,
201
201
  {
202
202
  start_date: (ctx == null ? void 0 : ctx.date) || void 0,
203
- quantity: (cartDetailValue == null ? void 0 : cartDetailValue.quantity) || (ctx == null ? void 0 : ctx.quantity) || 1,
203
+ /** 列表连点 / 防抖合并时以 ctx.quantity 为准,避免 cartDetailValue 默认 1 盖掉合并数量 */
204
+ quantity: (ctx == null ? void 0 : ctx.quantity) ?? (cartDetailValue == null ? void 0 : cartDetailValue.quantity) ?? 1,
204
205
  product_name: item.title,
205
206
  other,
206
207
  isNormalProduct: !(0, import_BookingContext.isBookingProduct)(item),
@@ -229,7 +230,7 @@ function buildCacheItemFromDetail(item, detailResult, ctx) {
229
230
  mergedItem,
230
231
  {
231
232
  start_date: (ctx == null ? void 0 : ctx.date) || void 0,
232
- quantity: ((_b = detailResult.e) == null ? void 0 : _b.quantity) || (ctx == null ? void 0 : ctx.quantity) || 1,
233
+ quantity: (ctx == null ? void 0 : ctx.quantity) ?? ((_b = detailResult.e) == null ? void 0 : _b.quantity) ?? 1,
233
234
  price: _detail == null ? void 0 : _detail.price,
234
235
  product_name: _currentItem.title,
235
236
  other,
@@ -267,22 +268,29 @@ function transformDetailToProductAndBooking(cacheItem, ctx) {
267
268
  return { product: productInput, booking, cacheItem: preparedCacheItem };
268
269
  }
269
270
  function buildBasePayloadFromCacheItem(cacheItem, ctx) {
270
- var _a, _b, _c, _d, _e;
271
+ var _a, _b, _c, _d;
271
272
  const other = ((_a = cacheItem == null ? void 0 : cacheItem._extend) == null ? void 0 : _a.other) || {};
272
- const quantity = ((_b = cacheItem == null ? void 0 : cacheItem._extend) == null ? void 0 : _b.quantity) ?? (ctx == null ? void 0 : ctx.quantity) ?? 1;
273
+ const quantity = (ctx == null ? void 0 : ctx.quantity) != null && ctx.quantity > 0 ? ctx.quantity : ((_b = cacheItem == null ? void 0 : cacheItem._extend) == null ? void 0 : _b.quantity) ?? 1;
273
274
  const resolvedPid = (cacheItem == null ? void 0 : cacheItem.product_id) ?? (cacheItem == null ? void 0 : cacheItem.id);
275
+ const extend = (cacheItem == null ? void 0 : cacheItem._extend) || {};
274
276
  return {
275
277
  id: (cacheItem == null ? void 0 : cacheItem.id) ?? (cacheItem == null ? void 0 : cacheItem.product_id),
276
278
  product_id: resolvedPid,
277
279
  variant_id: (other == null ? void 0 : other.product_variant_id) ?? (other == null ? void 0 : other.variant_id) ?? 0,
278
280
  quantity,
279
281
  option: (other == null ? void 0 : other.option) || [],
280
- bundle: (other == null ? void 0 : other.bundle) || [],
282
+ bundle: (other == null ? void 0 : other.bundle) || ((_c = extend == null ? void 0 : extend.skuValue) == null ? void 0 : _c.bundle) || ((_d = extend == null ? void 0 : extend._skuValue) == null ? void 0 : _d.bundle) || [],
281
283
  unique: other == null ? void 0 : other.unique,
282
284
  session: other == null ? void 0 : other.session,
283
- note: (_c = cacheItem == null ? void 0 : cacheItem._extend) == null ? void 0 : _c.note,
284
- price: ((_d = cacheItem == null ? void 0 : cacheItem._extend) == null ? void 0 : _d.price) ?? (cacheItem == null ? void 0 : cacheItem.price),
285
- selling_price: ((_e = cacheItem == null ? void 0 : cacheItem._extend) == null ? void 0 : _e.price) ?? (cacheItem == null ? void 0 : cacheItem.price)
285
+ note: extend == null ? void 0 : extend.note,
286
+ price: (extend == null ? void 0 : extend.price) ?? (cacheItem == null ? void 0 : cacheItem.price),
287
+ selling_price: (extend == null ? void 0 : extend.price) ?? (cacheItem == null ? void 0 : cacheItem.price),
288
+ line_total: extend == null ? void 0 : extend.total,
289
+ total: extend == null ? void 0 : extend.total,
290
+ origin_total: extend == null ? void 0 : extend.origin_total,
291
+ price_override: extend == null ? void 0 : extend.priceOverride,
292
+ bundle_edit: extend == null ? void 0 : extend.bundle_edit,
293
+ _extend: extend
286
294
  };
287
295
  }
288
296
  // Annotate the CommonJS export names for ESM import in node: