@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.
- package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +287 -101
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/dist/model/strategy/adapter/promotion/index.js +9 -0
- package/dist/modules/Discount/index.d.ts +2 -0
- package/dist/modules/Discount/index.js +38 -5
- package/dist/modules/Discount/types.d.ts +11 -0
- package/dist/modules/Order/index.d.ts +14 -0
- package/dist/modules/Order/index.js +617 -368
- package/dist/modules/Order/types.d.ts +11 -3
- package/dist/modules/Order/utils/virtualSettlement.d.ts +63 -0
- package/dist/modules/Order/utils/virtualSettlement.js +284 -0
- package/dist/modules/Order/utils.d.ts +1 -0
- package/dist/modules/Order/utils.js +63 -24
- package/dist/modules/Product/types.d.ts +23 -0
- package/dist/modules/Rules/index.d.ts +5 -0
- package/dist/modules/Rules/index.js +27 -12
- package/dist/modules/SalesSummary/index.d.ts +1 -0
- package/dist/modules/SalesSummary/index.js +4 -3
- package/dist/modules/SalesSummary/types.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.d.ts +1 -0
- package/dist/modules/SalesSummary/utils.js +21 -1
- package/dist/solution/BaseSales/index.d.ts +10 -1
- package/dist/solution/BaseSales/index.js +1099 -784
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +72 -9
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +18 -2
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +137 -6
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +25 -0
- package/lib/modules/Discount/index.d.ts +2 -0
- package/lib/modules/Discount/index.js +31 -2
- package/lib/modules/Discount/types.d.ts +11 -0
- package/lib/modules/Order/index.d.ts +14 -0
- package/lib/modules/Order/index.js +195 -15
- package/lib/modules/Order/types.d.ts +11 -3
- package/lib/modules/Order/utils/virtualSettlement.d.ts +63 -0
- package/lib/modules/Order/utils/virtualSettlement.js +262 -0
- package/lib/modules/Order/utils.d.ts +1 -0
- package/lib/modules/Order/utils.js +57 -20
- package/lib/modules/Product/types.d.ts +23 -0
- package/lib/modules/Rules/index.d.ts +5 -0
- package/lib/modules/Rules/index.js +20 -11
- package/lib/modules/SalesSummary/index.d.ts +1 -0
- package/lib/modules/SalesSummary/index.js +4 -2
- package/lib/modules/SalesSummary/types.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.d.ts +1 -0
- package/lib/modules/SalesSummary/utils.js +17 -1
- package/lib/solution/BaseSales/index.d.ts +10 -1
- package/lib/solution/BaseSales/index.js +211 -9
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +38 -0
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -0
- 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
|
-
|
|
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
|
-
...(
|
|
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
|
-
...(
|
|
2349
|
+
...(virtualSettlement ? {
|
|
2350
|
+
confirmPendingVoucherPayments: false
|
|
2351
|
+
} : params?.confirmPendingVoucherPayments !== undefined ? {
|
|
2170
2352
|
confirmPendingVoucherPayments: params.confirmPendingVoucherPayments
|
|
2171
2353
|
} : {}),
|
|
2172
|
-
...(
|
|
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
|
};
|
|
@@ -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 |
|
|
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: "
|
|
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
|
}
|