@pisell/pisellos 2.3.100 → 2.3.102

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 (56) hide show
  1. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  2. package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
  3. package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  4. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  5. package/dist/modules/Discount/index.d.ts +2 -0
  6. package/dist/modules/Discount/index.js +38 -5
  7. package/dist/modules/Discount/types.d.ts +11 -0
  8. package/dist/modules/Order/index.d.ts +14 -0
  9. package/dist/modules/Order/index.js +617 -368
  10. package/dist/modules/Order/types.d.ts +11 -3
  11. package/dist/modules/Order/utils/virtualSettlement.d.ts +63 -0
  12. package/dist/modules/Order/utils/virtualSettlement.js +284 -0
  13. package/dist/modules/Order/utils.d.ts +1 -0
  14. package/dist/modules/Order/utils.js +63 -24
  15. package/dist/modules/Product/types.d.ts +23 -0
  16. package/dist/modules/Rules/index.d.ts +5 -0
  17. package/dist/modules/Rules/index.js +27 -12
  18. package/dist/modules/SalesSummary/index.d.ts +1 -0
  19. package/dist/modules/SalesSummary/index.js +4 -3
  20. package/dist/modules/SalesSummary/types.d.ts +1 -0
  21. package/dist/modules/SalesSummary/utils.d.ts +1 -0
  22. package/dist/modules/SalesSummary/utils.js +21 -1
  23. package/dist/solution/BaseSales/index.d.ts +10 -1
  24. package/dist/solution/BaseSales/index.js +1099 -784
  25. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  26. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +72 -9
  27. package/dist/solution/BookingByStep/index.d.ts +2 -2
  28. package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
  29. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
  30. package/lib/model/strategy/adapter/dataVariant/evaluator.js +137 -6
  31. package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
  32. package/lib/modules/Discount/index.d.ts +2 -0
  33. package/lib/modules/Discount/index.js +31 -2
  34. package/lib/modules/Discount/types.d.ts +11 -0
  35. package/lib/modules/Order/index.d.ts +14 -0
  36. package/lib/modules/Order/index.js +195 -15
  37. package/lib/modules/Order/types.d.ts +11 -3
  38. package/lib/modules/Order/utils/virtualSettlement.d.ts +63 -0
  39. package/lib/modules/Order/utils/virtualSettlement.js +262 -0
  40. package/lib/modules/Order/utils.d.ts +1 -0
  41. package/lib/modules/Order/utils.js +57 -20
  42. package/lib/modules/Product/types.d.ts +23 -0
  43. package/lib/modules/Rules/index.d.ts +5 -0
  44. package/lib/modules/Rules/index.js +20 -11
  45. package/lib/modules/SalesSummary/index.d.ts +1 -0
  46. package/lib/modules/SalesSummary/index.js +4 -2
  47. package/lib/modules/SalesSummary/types.d.ts +1 -0
  48. package/lib/modules/SalesSummary/utils.d.ts +1 -0
  49. package/lib/modules/SalesSummary/utils.js +17 -1
  50. package/lib/solution/BaseSales/index.d.ts +10 -1
  51. package/lib/solution/BaseSales/index.js +211 -9
  52. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  53. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +38 -0
  54. package/lib/solution/BookingByStep/index.d.ts +2 -2
  55. package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -0
  56. package/package.json +1 -1
@@ -4,7 +4,7 @@ import { BaseSalesOrderProduct, BaseSalesOrderProductIdentity, BaseSalesPaymentS
4
4
  import { OrderModule } from '../../modules/Order';
5
5
  import type { AddProductBookingInput, AddProductToOrderOptions, LoadSalesDetailParams, OrderPaymentData, OrderPaymentUpdateOptions, OrderPaymentUpdateResult, OrderPaymentSource, SendCustomerPayLinkParams, SyncPaymentsToOrderParams, SyncPaymentsToOrderResult, UpdateTempOrderCustomerInput, UpdateOrderBookingParams, UpdateOrderProductParams, OrderTempOrder, OrderSummary, OrderPromotionEvaluator, OrderGiftSelectResolver, OrderUnfulfilledPromotion, OrderLastGiftActions, RemoveProductsFromOrderOptions, ReplaceTempOrderOptions, SalesNote, SalesNotesMutationSnapshot, SetSalesNoteInput, PickupReferenceMode, ShopServiceData, ShopServiceType } from '../../modules/Order/types';
6
6
  import type { SubmitPayloadEnhancer } from '../../modules/Order/utils';
7
- import type { Discount } from '../../modules/Discount/types';
7
+ import type { Discount, VirtualCurrencyAsset } from '../../modules/Discount/types';
8
8
  import { RequestPlugin, WindowPlugin } from '../../plugins';
9
9
  export * from './types';
10
10
  import { ProductList } from '../../modules/ProductList';
@@ -193,6 +193,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
193
193
  protected setPaymentNumberDevicePrefix(prefix: unknown): void;
194
194
  private getPaymentNumberDevicePrefixSync;
195
195
  private getPaymentNumberDevicePrefixAsync;
196
+ private isMultiCurrencySettlementEnabled;
197
+ private isActiveVirtualSettlementOrder;
198
+ private isHistoricalVirtualSettlementOrder;
196
199
  private syncAppDataToTempOrder;
197
200
  initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
198
201
  destroy(): Promise<void>;
@@ -253,6 +256,8 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
253
256
  * 同步清空内存中的 salesDetail 商品/预约视图,避免编辑态仍读到旧 bookings。
254
257
  */
255
258
  clearOrderCartLines(): Promise<OrderTempOrder>;
259
+ /** 切换法币 / WalletPass 单位时清空商品、折扣与支付状态,保留客户。 */
260
+ clearOrderForSettlementSwitch(): Promise<OrderTempOrder>;
256
261
  getOrderProducts(): import("../../modules/Order/types").OrderProduct[];
257
262
  getSummary(): Promise<OrderSummary>;
258
263
  private getHistoricalProductDiscountList;
@@ -263,12 +268,15 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
263
268
  loadDiscountConfig(params?: {
264
269
  customerId?: number;
265
270
  action?: 'create' | 'edit';
271
+ force?: boolean;
266
272
  }): Promise<{
267
273
  productList: Record<string, any>[];
268
274
  discountList: Discount[];
269
275
  availableWalletIds: number[];
276
+ virtualCurrencyList: VirtualCurrencyAsset[];
270
277
  }>;
271
278
  getAvailableWalletIds(): number[];
279
+ getVirtualCurrencyList(): VirtualCurrencyAsset[];
272
280
  bestDiscount(cb?: (result: any) => void): Promise<{
273
281
  productList: Record<string, any>[];
274
282
  discountList: Discount[];
@@ -300,6 +308,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
300
308
  confirmPendingVoucherPayments?: boolean;
301
309
  enhancePayload?: SubmitPayloadEnhancer;
302
310
  }): Promise<T>;
311
+ private buildVirtualSettlementSubmitData;
303
312
  /**
304
313
  * 提交当前 Sales 订单。
305
314
  *
@@ -25,6 +25,7 @@ var _decimal = _interopRequireDefault(require("decimal.js"));
25
25
  var _lodashEs = require("lodash-es");
26
26
  var _types2 = require("../BookingByStep/types");
27
27
  var _utils = require("../../modules/Order/utils");
28
+ var _virtualSettlement = require("../../modules/Order/utils/virtualSettlement");
28
29
  var _paymentUtils = require("../../modules/Order/payment-utils");
29
30
  var _paymentNumber = require("../../utils/payment-number");
30
31
  var _orderCollectionIdentity = require("../../modules/Order/utils/orderCollectionIdentity");
@@ -1253,11 +1254,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1253
1254
  }
1254
1255
  return (0, _paymentNumber.resolvePaymentNumberDevicePrefix)(key => this.getAppData(key));
1255
1256
  }
1257
+ isMultiCurrencySettlementEnabled() {
1258
+ return this.otherParams?.enableMultiCurrencySettlement === true;
1259
+ }
1260
+ isActiveVirtualSettlementOrder(tempOrder) {
1261
+ return this.isMultiCurrencySettlementEnabled() && (0, _virtualSettlement.isVirtualSettlementOrder)(tempOrder);
1262
+ }
1263
+ isHistoricalVirtualSettlementOrder(tempOrder) {
1264
+ return tempOrder?.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
1265
+ }
1256
1266
  syncAppDataToTempOrder(tempOrder) {
1257
1267
  const isPriceIncludeTax = this.getAppData('is_price_include_tax');
1258
1268
  const taxCountryCode = this.getAppData('tax_country_code');
1259
1269
  const currencyCode = this.getAppData('shop_currency_code');
1260
1270
  const currencySymbol = this.getAppData('shop_symbol');
1271
+ // 历史虚拟币订单不依赖交易开关;普通 POS 不从商品行残留快照推断订单币种。
1272
+ const isHistoricalVirtualSettlement = this.isHistoricalVirtualSettlementOrder(tempOrder);
1273
+ const isVirtualSettlement = this.isActiveVirtualSettlementOrder(tempOrder) || isHistoricalVirtualSettlement;
1274
+ const shouldManageLegalCurrencySnapshot = this.isMultiCurrencySettlementEnabled() || isHistoricalVirtualSettlement;
1261
1275
  let isChanged = false;
1262
1276
  if (isPriceIncludeTax !== undefined) {
1263
1277
  const nextIsPriceIncludeTax = Number(isPriceIncludeTax);
@@ -1273,14 +1287,26 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1273
1287
  isChanged = true;
1274
1288
  }
1275
1289
  }
1276
- if (currencyCode !== undefined) {
1290
+ tempOrder.metadata = tempOrder.metadata || {};
1291
+ if (shouldManageLegalCurrencySnapshot) {
1292
+ const legalCurrencySnapshot = {
1293
+ currency_code: String(currencyCode ?? tempOrder.metadata.legal_currency_snapshot?.currency_code ?? tempOrder.currency_code ?? ''),
1294
+ currency_symbol: String(currencySymbol ?? tempOrder.metadata.legal_currency_snapshot?.currency_symbol ?? tempOrder.currency_symbol ?? ''),
1295
+ currency_format: String(tempOrder.metadata.legal_currency_snapshot?.currency_format || (isVirtualSettlement ? 'symbol_first' : tempOrder.currency_format) || 'symbol_first')
1296
+ };
1297
+ if (JSON.stringify(tempOrder.metadata.legal_currency_snapshot || {}) !== JSON.stringify(legalCurrencySnapshot)) {
1298
+ tempOrder.metadata.legal_currency_snapshot = legalCurrencySnapshot;
1299
+ isChanged = true;
1300
+ }
1301
+ }
1302
+ if (!isVirtualSettlement && currencyCode !== undefined) {
1277
1303
  const nextCurrencyCode = String(currencyCode || '');
1278
1304
  if (tempOrder.currency_code !== nextCurrencyCode) {
1279
1305
  tempOrder.currency_code = nextCurrencyCode;
1280
1306
  isChanged = true;
1281
1307
  }
1282
1308
  }
1283
- if (currencySymbol !== undefined) {
1309
+ if (!isVirtualSettlement && currencySymbol !== undefined) {
1284
1310
  const nextCurrencySymbol = String(currencySymbol || '');
1285
1311
  if (tempOrder.currency_symbol !== nextCurrencySymbol) {
1286
1312
  tempOrder.currency_symbol = nextCurrencySymbol;
@@ -1654,6 +1680,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1654
1680
  throw error;
1655
1681
  }
1656
1682
  }
1683
+
1684
+ /** 切换法币 / WalletPass 单位时清空商品、折扣与支付状态,保留客户。 */
1685
+ async clearOrderForSettlementSwitch() {
1686
+ if (!this.store.order) throw new Error('order 模块未初始化');
1687
+ const tempOrder = await this.store.order.clearOrderForSettlementSwitch();
1688
+ if (this.currentSalesDetail) {
1689
+ this.currentSalesDetail = {
1690
+ ...this.currentSalesDetail,
1691
+ products: [],
1692
+ bookings: [],
1693
+ rootBooking: null,
1694
+ bookingsByProductUid: {},
1695
+ discount_list: [],
1696
+ payments: []
1697
+ };
1698
+ }
1699
+ return tempOrder;
1700
+ }
1657
1701
  getOrderProducts() {
1658
1702
  if (!this.store.order) throw new Error('order 模块未初始化');
1659
1703
  const products = this.store.order.getOrderProducts();
@@ -1781,7 +1825,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1781
1825
  const discountConfigCacheKey = [customerId, discountAction, Number(orderId) || 0].join(':');
1782
1826
  let preparedDiscountList = [];
1783
1827
  if (customerId && customerId !== 1) {
1784
- if (this.discountConfigCacheKey === discountConfigCacheKey) {
1828
+ if (!params?.force && this.discountConfigCacheKey === discountConfigCacheKey) {
1785
1829
  preparedDiscountList = originalDiscountList;
1786
1830
  } else {
1787
1831
  preparedDiscountList = await this.store.order.loadDiscountConfig({
@@ -1794,11 +1838,24 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1794
1838
  await discountModule?.setOriginalDiscountList?.(preparedDiscountList);
1795
1839
  }
1796
1840
  }
1841
+ if (this.isActiveVirtualSettlementOrder(tempOrder)) {
1842
+ await discountModule?.setOriginalDiscountList?.([]);
1843
+ await discountModule?.setDiscountList?.([]);
1844
+ tempOrder.discount_list = [];
1845
+ tempOrder.shop_discount = '0.00';
1846
+ return {
1847
+ productList: tempOrder.products || [],
1848
+ discountList: [],
1849
+ availableWalletIds: this.getAvailableWalletIds(),
1850
+ virtualCurrencyList: this.store.order.getVirtualCurrencyList()
1851
+ };
1852
+ }
1797
1853
  if (hasManualDiscountSelection && currentDiscountList.length) {
1798
1854
  return {
1799
1855
  productList: tempOrder.products || [],
1800
1856
  discountList: currentDiscountList,
1801
- availableWalletIds: this.getAvailableWalletIds()
1857
+ availableWalletIds: this.getAvailableWalletIds(),
1858
+ virtualCurrencyList: this.store.order.getVirtualCurrencyList()
1802
1859
  };
1803
1860
  }
1804
1861
  let nextDiscountList = this.mergeHistoricalDiscountList(preparedDiscountList || discountModule?.getDiscountList?.() || [], tempOrder.products || []);
@@ -1824,7 +1881,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1824
1881
  return {
1825
1882
  productList: tempOrder.products || [],
1826
1883
  discountList: nextDiscountList,
1827
- availableWalletIds: this.getAvailableWalletIds()
1884
+ availableWalletIds: this.getAvailableWalletIds(),
1885
+ virtualCurrencyList: this.store.order.getVirtualCurrencyList()
1828
1886
  };
1829
1887
  }
1830
1888
  if (rulesModule) {
@@ -1880,16 +1938,29 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1880
1938
  return {
1881
1939
  productList: tempOrder.products || [],
1882
1940
  discountList: nextDiscountList,
1883
- availableWalletIds: this.getAvailableWalletIds()
1941
+ availableWalletIds: this.getAvailableWalletIds(),
1942
+ virtualCurrencyList: this.store.order.getVirtualCurrencyList()
1884
1943
  };
1885
1944
  }
1886
1945
  getAvailableWalletIds() {
1887
1946
  if (!this.store.order?.getAvailableWalletIds) return [];
1888
1947
  return this.store.order.getAvailableWalletIds();
1889
1948
  }
1949
+ getVirtualCurrencyList() {
1950
+ if (!this.store.order?.getVirtualCurrencyList) return [];
1951
+ return this.store.order.getVirtualCurrencyList();
1952
+ }
1890
1953
  async bestDiscount(cb) {
1891
1954
  if (!this.store.order) throw new Error('order 模块未初始化');
1892
1955
  const tempOrder = this.store.order.ensureTempOrder();
1956
+ if (this.isActiveVirtualSettlementOrder(tempOrder)) {
1957
+ const result = {
1958
+ productList: tempOrder.products || [],
1959
+ discountList: []
1960
+ };
1961
+ cb?.(result);
1962
+ return result;
1963
+ }
1893
1964
  const orderStore = this.store.order.store || {};
1894
1965
  const discountModule = orderStore.discount;
1895
1966
  const rulesModule = orderStore.rules;
@@ -1997,6 +2068,17 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1997
2068
  async setDiscountSelected(params) {
1998
2069
  try {
1999
2070
  if (!this.store.order) throw new Error('order 模块未初始化');
2071
+ const currentOrder = this.store.order.ensureTempOrder();
2072
+ if (this.isActiveVirtualSettlementOrder(currentOrder)) {
2073
+ currentOrder.discount_list = [];
2074
+ currentOrder.shop_discount = '0.00';
2075
+ await this.store.order.store?.discount?.setDiscountList?.([]);
2076
+ await this.store.order.recalculateSummary({
2077
+ createIfMissing: true
2078
+ });
2079
+ this.store.order.persistTempOrder();
2080
+ return;
2081
+ }
2000
2082
  const list = this.store.order.getDiscountList();
2001
2083
  const updated = list.map(d => d.id === params.discountId && !isBaseSalesHistoricalDiscountEntry(d) ? {
2002
2084
  ...d,
@@ -2135,6 +2217,101 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
2135
2217
  // Deprecated compatibility alias. New BaseSales callers should use submitSalesOrder.
2136
2218
  return this.submitSalesOrder(params);
2137
2219
  }
2220
+ async buildVirtualSettlementSubmitData() {
2221
+ if (!this.store.order) return null;
2222
+ const tempOrder = this.store.order.getTempOrder();
2223
+ if (!this.isActiveVirtualSettlementOrder(tempOrder)) return null;
2224
+ const snapshot = (0, _virtualSettlement.getTempOrderSettlementSnapshot)(tempOrder);
2225
+ const currencyProductId = Number(tempOrder?.metadata?.currency_settlement_config?.settlement_ids?.[0] ?? snapshot?.currency_product_id);
2226
+ if (!snapshot || !Number.isFinite(currencyProductId) || currencyProductId <= 0) {
2227
+ throw new Error('Virtual currency settlement configuration is invalid.');
2228
+ }
2229
+ const summary = await this.store.order.recalculateSummary({
2230
+ createIfMissing: true
2231
+ });
2232
+ const amount = new _decimal.default(summary?.total_amount || 0).toDecimalPlaces(2);
2233
+ const customerId = Number(tempOrder?.customer_id || 0);
2234
+ if (amount.gt(0) && customerId > 0 && customerId !== 1) {
2235
+ await this.store.order.loadDiscountConfig({
2236
+ customerId,
2237
+ action: tempOrder?.order_id ? 'edit' : 'create',
2238
+ orderId: Number(tempOrder?.order_id) || undefined,
2239
+ apply: false
2240
+ });
2241
+ }
2242
+ const asset = this.store.order.getVirtualCurrencyList().find(item => Number(item?.product_id) === currencyProductId);
2243
+ const currencyCode = String(tempOrder?.currency_code || '');
2244
+ const currencySymbol = String(tempOrder?.currency_symbol || '');
2245
+ const currencyFormat = String(tempOrder?.currency_format || 'symbol_first');
2246
+ if (amount.lte(0)) {
2247
+ return {
2248
+ payments: [],
2249
+ snapshot,
2250
+ currencyProductId,
2251
+ currencyCode,
2252
+ currencySymbol,
2253
+ currencyFormat
2254
+ };
2255
+ }
2256
+ if (!asset) {
2257
+ throw new Error('No matching virtual currency card is available.');
2258
+ }
2259
+ const balance = new _decimal.default(asset.balance || 0);
2260
+ if (balance.lt(amount)) {
2261
+ throw new Error('Insufficient virtual currency balance.');
2262
+ }
2263
+ const amountText = amount.toFixed(2);
2264
+ const paymentNumber = `LOCAL_${(0, _utils.createUuidV4)()}`;
2265
+ let payment;
2266
+ if (this.store.order.isOnlineStorePlatform()) {
2267
+ payment = {
2268
+ payment_number: paymentNumber,
2269
+ amount: amount.toNumber(),
2270
+ metadata: {
2271
+ unique_payment_number: (0, _utils.createUuidV4)()
2272
+ },
2273
+ tag: asset.tag,
2274
+ voucher_id: asset.id,
2275
+ wallet_pass_usage_unit: {
2276
+ price: 1,
2277
+ points: 1
2278
+ },
2279
+ wallet_pass_use_value: amountText
2280
+ };
2281
+ } else {
2282
+ const paymentMethods = await this.getPaymentMethodsAsync();
2283
+ const paymentMethod = paymentMethods.find(method => String(method.code || '').toUpperCase() === 'PRODUCTVOUCHER');
2284
+ if (!paymentMethod) {
2285
+ throw new Error('PRODUCTVOUCHER payment method is unavailable.');
2286
+ }
2287
+ payment = {
2288
+ payment_number: paymentNumber,
2289
+ amount: amountText,
2290
+ origin_amount: amountText,
2291
+ code: paymentMethod.code,
2292
+ custom_payment_id: paymentMethod.id,
2293
+ custom_payment_type: paymentMethod.custom_payment_type ?? paymentMethod.type,
2294
+ name: paymentMethod.name,
2295
+ type: 'normal',
2296
+ voucher_id: asset.id,
2297
+ order_payment_type: 'normal',
2298
+ wallet_pass_usage_unit: {
2299
+ price: 1,
2300
+ points: 1
2301
+ },
2302
+ wallet_pass_use_value: amountText,
2303
+ metadata: {}
2304
+ };
2305
+ }
2306
+ return {
2307
+ payments: [payment],
2308
+ snapshot,
2309
+ currencyProductId,
2310
+ currencyCode,
2311
+ currencySymbol,
2312
+ currencyFormat
2313
+ };
2314
+ }
2138
2315
 
2139
2316
  /**
2140
2317
  * 提交当前 Sales 订单。
@@ -2146,6 +2323,7 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
2146
2323
  if (!this.store.order) {
2147
2324
  throw new Error('BaseSales 解决方案需要 order 模块支持');
2148
2325
  }
2326
+ const virtualSettlement = await this.buildVirtualSettlementSubmitData();
2149
2327
  // this.store.order.persistTempOrder();
2150
2328
  const inferredPaymentStatus = this.getSubmitPaymentStatus(params?.paymentStatus);
2151
2329
  const smallTicketDataFlag = params?.smallTicketDataFlag ?? this.getDefaultCheckoutSmallTicketDataFlag();
@@ -2157,7 +2335,9 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
2157
2335
  channel: this.getSubmitOrderSalesChannel(),
2158
2336
  type: this.otherParams?.type,
2159
2337
  request_unique_idempotency_token: this.store.order.generateIdempotencyToken(),
2160
- ...(params?.payments !== undefined ? {
2338
+ ...(virtualSettlement ? {
2339
+ payments: virtualSettlement.payments
2340
+ } : params?.payments !== undefined ? {
2161
2341
  payments: params.payments
2162
2342
  } : {}),
2163
2343
  ...(inferredPaymentStatus !== undefined ? {
@@ -2166,10 +2346,32 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
2166
2346
  ...(smallTicketDataFlag !== undefined ? {
2167
2347
  smallTicketDataFlag
2168
2348
  } : {}),
2169
- ...(params?.confirmPendingVoucherPayments !== undefined ? {
2349
+ ...(virtualSettlement ? {
2350
+ confirmPendingVoucherPayments: false
2351
+ } : params?.confirmPendingVoucherPayments !== undefined ? {
2170
2352
  confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
2171
2353
  } : {}),
2172
- ...(enhancePayload !== undefined ? {
2354
+ ...(virtualSettlement ? {
2355
+ enhancePayload: (payload, ctx) => {
2356
+ const callerPayload = enhancePayload ? enhancePayload(payload, ctx) : payload;
2357
+ const currencySettlementConfig = callerPayload.metadata?.currency_settlement_config || {};
2358
+ return {
2359
+ ...callerPayload,
2360
+ metadata: {
2361
+ ...(callerPayload.metadata || {}),
2362
+ currency_settlement_config: {
2363
+ ...currencySettlementConfig,
2364
+ settlement_type: 'virtual_currency',
2365
+ settlement_ids: [virtualSettlement.currencyProductId],
2366
+ currency_display_snapshot: (0, _lodashEs.cloneDeep)(currencySettlementConfig.currency_display_snapshot ?? (0, _virtualSettlement.buildCurrencyDisplaySnapshot)(virtualSettlement.snapshot))
2367
+ }
2368
+ },
2369
+ currency_code: virtualSettlement.currencyCode,
2370
+ currency_symbol: virtualSettlement.currencySymbol,
2371
+ currency_format: virtualSettlement.currencyFormat
2372
+ };
2373
+ }
2374
+ } : enhancePayload !== undefined ? {
2173
2375
  enhancePayload
2174
2376
  } : {})
2175
2377
  };
@@ -46,6 +46,7 @@ export interface BaseProductDetailPayload {
46
46
  original_price?: number | string;
47
47
  tax_fee?: number | string;
48
48
  is_charge_tax?: number;
49
+ metadata?: Record<string, any>;
49
50
  note?: string;
50
51
  [key: string]: any;
51
52
  }
@@ -37,6 +37,34 @@ function isBlankValue(value) {
37
37
  function firstNonBlank(...values) {
38
38
  return values.find(value => !isBlankValue(value));
39
39
  }
40
+
41
+ /**
42
+ * 取第一份接口权威 Data Variant 命中结果并复制数组。
43
+ * 空数组表示规则已计算但无命中,必须与字段缺失区分。
44
+ */
45
+ function cloneFirstDataVariantIds(...values) {
46
+ const ids = values.find(value => Array.isArray(value));
47
+ return Array.isArray(ids) ? [...ids] : undefined;
48
+ }
49
+
50
+ /**
51
+ * 在接口权威命中结果后追加本地应用及最终选中的 Data Variant ID。
52
+ * 以字符串身份去重,同时将新增 ID 归一为正整数。
53
+ */
54
+ function appendDataVariantIds(base, ...values) {
55
+ const result = Array.isArray(base) ? [...base] : [];
56
+ const seen = new Set(result.map(id => String(id)));
57
+ for (const value of values) {
58
+ const candidates = Array.isArray(value) ? value : [value];
59
+ for (const candidate of candidates) {
60
+ const id = Number(candidate);
61
+ if (!Number.isFinite(id) || id <= 0 || seen.has(String(id))) continue;
62
+ result.push(id);
63
+ seen.add(String(id));
64
+ }
65
+ }
66
+ return Array.isArray(base) || result.length ? result : undefined;
67
+ }
40
68
  function normalizeOptionItems(optionItems) {
41
69
  if (!Array.isArray(optionItems)) return [];
42
70
  return optionItems.map(optionItem => {
@@ -111,6 +139,10 @@ function transformBaseProductToOrderProduct(params) {
111
139
  ...(sourceProduct || {}),
112
140
  ...(callbackOrigin || {})
113
141
  };
142
+ const authoritativeDataVariantIds = cloneFirstDataVariantIds(payload.metadata?.data_variant_ids, sourceProduct?.metadata?.data_variant_ids, callbackOrigin?.metadata?.data_variant_ids, origin?.metadata?.data_variant_ids);
143
+ const selectedSettlementSnapshot = firstNonBlank(payload.selected_settlement_snapshot, payload.metadata?.selected_settlement_snapshot, payload._extend?.metadata?.selected_settlement_snapshot, sourceProduct?.metadata?.selected_settlement_snapshot, sourceProduct?._extend?.metadata?.selected_settlement_snapshot, callbackOrigin?.metadata?.selected_settlement_snapshot, callbackOrigin?._extend?.metadata?.selected_settlement_snapshot);
144
+ const locallyAppliedVariantIds = authoritativeDataVariantIds === undefined ? cloneFirstDataVariantIds(payload._dataVariant?.appliedVariantIds, sourceProduct?._dataVariant?.appliedVariantIds, callbackOrigin?._dataVariant?.appliedVariantIds, origin?._dataVariant?.appliedVariantIds) : undefined;
145
+ const dataVariantIds = appendDataVariantIds(authoritativeDataVariantIds, locallyAppliedVariantIds, selectedSettlementSnapshot?.data_variant_id);
114
146
  const matchedVariant = findVariantById(callbackOrigin, productVariantId) ?? findVariantById(sourceProduct, productVariantId) ?? findVariantById(origin, productVariantId);
115
147
  const productionCode = normalizeProductionCode(Object.prototype.hasOwnProperty.call(payload, 'production_code') ? payload.production_code : productVariantId > 0 ? matchedVariant?.production_code : origin?.production_code ?? sourceProduct?.production_code);
116
148
  const hasPriceOverride = payload.price_override !== undefined && payload.price_override !== null && payload.price_override !== '';
@@ -179,6 +211,12 @@ function transformBaseProductToOrderProduct(params) {
179
211
  main_product_original_price: mainProductOriginalPrice,
180
212
  price_schema_version: 2,
181
213
  holder_config: sourceProduct?.holder_config,
214
+ ...(dataVariantIds !== undefined ? {
215
+ data_variant_ids: dataVariantIds
216
+ } : {}),
217
+ ...(selectedSettlementSnapshot ? {
218
+ selected_settlement_snapshot: selectedSettlementSnapshot
219
+ } : {}),
182
220
  ...(hasPriceOverride ? {
183
221
  price_override: String(payload.price_override),
184
222
  is_manual_discount: 1
@@ -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 | 5 | 3 | 1 | 2 | 4 | 6;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -345,7 +345,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
345
345
  count: number;
346
346
  left: number;
347
347
  summaryCount: number;
348
- status: "sold_out" | "lots_of_space" | "filling_up_fast";
348
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
349
349
  }[];
350
350
  /**
351
351
  * 找到多个资源的公共可用时间段
@@ -358,6 +358,7 @@ function buildBasePayloadFromCacheItem(cacheItem, ctx) {
358
358
  bundle_edit: extend?.bundle_edit,
359
359
  discount_reason: extend?.discount_reason,
360
360
  discount_list: cacheItem?.discount_list,
361
+ selected_settlement_snapshot: cacheItem?.metadata?.selected_settlement_snapshot ?? extend?.metadata?.selected_settlement_snapshot,
361
362
  _extend: extend
362
363
  };
363
364
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.3.100",
4
+ "version": "2.3.102",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",