@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
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.VirtualCurrencyBalanceError = exports.VirtualCurrencyAssetNotFoundError = exports.OrderSettlementConflictError = void 0;
|
|
7
|
+
exports.applyTempOrderSettlementState = applyTempOrderSettlementState;
|
|
8
|
+
exports.buildCurrencyDisplaySnapshot = buildCurrencyDisplaySnapshot;
|
|
9
|
+
exports.getSelectedSettlementSnapshot = getSelectedSettlementSnapshot;
|
|
10
|
+
exports.getSettlementKey = getSettlementKey;
|
|
11
|
+
exports.getTempOrderSettlementKey = getTempOrderSettlementKey;
|
|
12
|
+
exports.getTempOrderSettlementSnapshot = getTempOrderSettlementSnapshot;
|
|
13
|
+
exports.isVirtualSettlementDisplayOrder = isVirtualSettlementDisplayOrder;
|
|
14
|
+
exports.isVirtualSettlementOrder = isVirtualSettlementOrder;
|
|
15
|
+
exports.isVirtualSettlementProduct = isVirtualSettlementProduct;
|
|
16
|
+
exports.normalizeVirtualSettlementOrderProduct = normalizeVirtualSettlementOrderProduct;
|
|
17
|
+
exports.normalizeVirtualSettlementProducts = normalizeVirtualSettlementProducts;
|
|
18
|
+
exports.releaseTempOrderSettlementState = releaseTempOrderSettlementState;
|
|
19
|
+
exports.resolveSettlementDisplayValue = resolveSettlementDisplayValue;
|
|
20
|
+
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
21
|
+
var _lodashEs = require("lodash-es");
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
function buildCurrencyDisplaySnapshot(snapshot) {
|
|
24
|
+
return (0, _lodashEs.cloneDeep)({
|
|
25
|
+
amount_format: String(snapshot.amount_format || '').trim(),
|
|
26
|
+
symbol: snapshot.symbol ?? {},
|
|
27
|
+
unit_label: snapshot.unit_label ?? {}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function resolveSettlementDisplayValue(value) {
|
|
31
|
+
if (value === undefined || value === null) return '';
|
|
32
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
33
|
+
return String(value);
|
|
34
|
+
}
|
|
35
|
+
const localized = value;
|
|
36
|
+
return String(localized.auto ?? localized.default ?? localized.original ?? localized.en ?? localized['zh-CN'] ?? localized['zh-HK'] ?? '');
|
|
37
|
+
}
|
|
38
|
+
class OrderSettlementConflictError extends Error {
|
|
39
|
+
code = 'ORDER_SETTLEMENT_CONFLICT';
|
|
40
|
+
constructor(currentSettlementKey, incomingSettlementKey) {
|
|
41
|
+
super('Different currencies and WalletPass units cannot be mixed in one cart.');
|
|
42
|
+
this.currentSettlementKey = currentSettlementKey;
|
|
43
|
+
this.incomingSettlementKey = incomingSettlementKey;
|
|
44
|
+
this.name = 'OrderSettlementConflictError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.OrderSettlementConflictError = OrderSettlementConflictError;
|
|
48
|
+
class VirtualCurrencyAssetNotFoundError extends Error {
|
|
49
|
+
code = 'VIRTUAL_CURRENCY_ASSET_NOT_FOUND';
|
|
50
|
+
constructor(currencyProductId) {
|
|
51
|
+
super('No matching virtual currency card is available.');
|
|
52
|
+
this.currencyProductId = currencyProductId;
|
|
53
|
+
this.name = 'VirtualCurrencyAssetNotFoundError';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.VirtualCurrencyAssetNotFoundError = VirtualCurrencyAssetNotFoundError;
|
|
57
|
+
class VirtualCurrencyBalanceError extends Error {
|
|
58
|
+
code = 'VIRTUAL_CURRENCY_BALANCE_INSUFFICIENT';
|
|
59
|
+
constructor(balance, requiredAmount) {
|
|
60
|
+
super('Insufficient virtual currency balance.');
|
|
61
|
+
this.balance = balance;
|
|
62
|
+
this.requiredAmount = requiredAmount;
|
|
63
|
+
this.name = 'VirtualCurrencyBalanceError';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.VirtualCurrencyBalanceError = VirtualCurrencyBalanceError;
|
|
67
|
+
function getSelectedSettlementSnapshot(product) {
|
|
68
|
+
const snapshot = product?.metadata?.selected_settlement_snapshot;
|
|
69
|
+
if (!snapshot || typeof snapshot !== 'object') return null;
|
|
70
|
+
if (snapshot.settlement_type !== 'legal_currency' && snapshot.settlement_type !== 'virtual_currency') {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
return snapshot;
|
|
74
|
+
}
|
|
75
|
+
function getTempOrderSettlementSnapshot(tempOrder) {
|
|
76
|
+
const snapshot = tempOrder?.metadata?.cart_settlement_snapshot;
|
|
77
|
+
if (snapshot && typeof snapshot === 'object' && (snapshot.settlement_type === 'legal_currency' || snapshot.settlement_type === 'virtual_currency')) {
|
|
78
|
+
return snapshot;
|
|
79
|
+
}
|
|
80
|
+
return getSelectedSettlementSnapshot(tempOrder?.products?.[0]);
|
|
81
|
+
}
|
|
82
|
+
function isVirtualSettlementProduct(product) {
|
|
83
|
+
return getSelectedSettlementSnapshot(product)?.settlement_type === 'virtual_currency';
|
|
84
|
+
}
|
|
85
|
+
function getSettlementKey(snapshot) {
|
|
86
|
+
if (!snapshot) return null;
|
|
87
|
+
if (snapshot.settlement_type === 'legal_currency') return 'legal_currency';
|
|
88
|
+
const currencyProductId = Number(snapshot.currency_product_id);
|
|
89
|
+
return Number.isFinite(currencyProductId) && currencyProductId > 0 ? `virtual_currency:${currencyProductId}` : null;
|
|
90
|
+
}
|
|
91
|
+
function getTempOrderSettlementKey(tempOrder) {
|
|
92
|
+
if (!tempOrder?.products?.length) return null;
|
|
93
|
+
const storedKey = tempOrder.metadata?.cart_settlement_key;
|
|
94
|
+
if (typeof storedKey === 'string' && storedKey) return storedKey;
|
|
95
|
+
return getSettlementKey(getTempOrderSettlementSnapshot(tempOrder)) || 'legal_currency';
|
|
96
|
+
}
|
|
97
|
+
function isVirtualSettlementOrder(tempOrder) {
|
|
98
|
+
return getTempOrderSettlementKey(tempOrder)?.startsWith('virtual_currency:') === true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 详情展示识别同时支持已提交订单的 currency_settlement_config。
|
|
103
|
+
* cart_settlement_* 是交易过程内部状态,服务端详情不保证返回。
|
|
104
|
+
*/
|
|
105
|
+
function isVirtualSettlementDisplayOrder(tempOrder) {
|
|
106
|
+
return tempOrder?.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency' || isVirtualSettlementOrder(tempOrder);
|
|
107
|
+
}
|
|
108
|
+
function getLegalCurrencySnapshot(tempOrder) {
|
|
109
|
+
const snapshot = tempOrder.metadata?.legal_currency_snapshot;
|
|
110
|
+
if (!snapshot || typeof snapshot !== 'object') return null;
|
|
111
|
+
return {
|
|
112
|
+
currency_code: String(snapshot.currency_code || ''),
|
|
113
|
+
currency_symbol: String(snapshot.currency_symbol || ''),
|
|
114
|
+
currency_format: String(snapshot.currency_format || 'symbol_first')
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function captureLegalCurrencySnapshot(tempOrder) {
|
|
118
|
+
tempOrder.metadata = tempOrder.metadata || {};
|
|
119
|
+
if (getLegalCurrencySnapshot(tempOrder)) return;
|
|
120
|
+
tempOrder.metadata.legal_currency_snapshot = {
|
|
121
|
+
currency_code: String(tempOrder.currency_code || ''),
|
|
122
|
+
currency_symbol: String(tempOrder.currency_symbol || ''),
|
|
123
|
+
currency_format: String(tempOrder.currency_format || 'symbol_first')
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 将购物车锁定的结算单位提升为订单级状态。
|
|
129
|
+
* 商品行快照同时负责价格归一化和生成订单级多语言展示快照;
|
|
130
|
+
* 交易中的即时展示仍统一读取 tempOrder.currency_*。
|
|
131
|
+
*/
|
|
132
|
+
function applyTempOrderSettlementState(tempOrder, snapshot) {
|
|
133
|
+
tempOrder.metadata = tempOrder.metadata || {};
|
|
134
|
+
const settlementKey = getSettlementKey(snapshot) || 'legal_currency';
|
|
135
|
+
if (snapshot.settlement_type === 'virtual_currency') {
|
|
136
|
+
captureLegalCurrencySnapshot(tempOrder);
|
|
137
|
+
const currencyProductId = Number(snapshot.currency_product_id);
|
|
138
|
+
const existingDisplaySnapshot = tempOrder.metadata.currency_settlement_config?.currency_display_snapshot;
|
|
139
|
+
tempOrder.metadata.currency_settlement_config = {
|
|
140
|
+
settlement_type: 'virtual_currency',
|
|
141
|
+
settlement_ids: Number.isFinite(currencyProductId) && currencyProductId > 0 ? [currencyProductId] : [],
|
|
142
|
+
currency_display_snapshot: existingDisplaySnapshot ? (0, _lodashEs.cloneDeep)(existingDisplaySnapshot) : buildCurrencyDisplaySnapshot(snapshot)
|
|
143
|
+
};
|
|
144
|
+
} else {
|
|
145
|
+
delete tempOrder.metadata.currency_settlement_config;
|
|
146
|
+
}
|
|
147
|
+
tempOrder.metadata.cart_settlement_key = settlementKey;
|
|
148
|
+
tempOrder.metadata.cart_settlement_snapshot = {
|
|
149
|
+
...snapshot
|
|
150
|
+
};
|
|
151
|
+
tempOrder.currency_code = resolveSettlementDisplayValue(snapshot.unit_label) || tempOrder.currency_code;
|
|
152
|
+
tempOrder.currency_symbol = resolveSettlementDisplayValue(snapshot.symbol) || tempOrder.currency_symbol;
|
|
153
|
+
tempOrder.currency_format = String(snapshot.amount_format || tempOrder.currency_format || 'symbol_first');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** 清空购物车结算锁,并恢复进入虚拟币结算前的店铺法币。 */
|
|
157
|
+
function releaseTempOrderSettlementState(tempOrder) {
|
|
158
|
+
tempOrder.metadata = tempOrder.metadata || {};
|
|
159
|
+
const legalCurrency = getLegalCurrencySnapshot(tempOrder);
|
|
160
|
+
if (legalCurrency) {
|
|
161
|
+
tempOrder.currency_code = legalCurrency.currency_code;
|
|
162
|
+
tempOrder.currency_symbol = legalCurrency.currency_symbol;
|
|
163
|
+
tempOrder.currency_format = legalCurrency.currency_format;
|
|
164
|
+
}
|
|
165
|
+
delete tempOrder.metadata.cart_settlement_key;
|
|
166
|
+
delete tempOrder.metadata.cart_settlement_snapshot;
|
|
167
|
+
delete tempOrder.metadata.currency_settlement_config;
|
|
168
|
+
}
|
|
169
|
+
function toMoney(value) {
|
|
170
|
+
try {
|
|
171
|
+
return new _decimal.default(String(value ?? 0)).toDecimalPlaces(2).toFixed(2);
|
|
172
|
+
} catch {
|
|
173
|
+
return '0.00';
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function zeroOptions(options) {
|
|
177
|
+
if (!Array.isArray(options)) return [];
|
|
178
|
+
return options.map(option => ({
|
|
179
|
+
...option,
|
|
180
|
+
add_price: 0
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
function zeroBundles(bundles) {
|
|
184
|
+
if (!Array.isArray(bundles)) return [];
|
|
185
|
+
return bundles.map(bundle => ({
|
|
186
|
+
...bundle,
|
|
187
|
+
price: 0,
|
|
188
|
+
custom_price: 0,
|
|
189
|
+
bundle_selling_price: 0,
|
|
190
|
+
bundle_payment_price: 0,
|
|
191
|
+
surcharge_fee: 0,
|
|
192
|
+
tax_fee: 0,
|
|
193
|
+
original_tax_fee: 0,
|
|
194
|
+
is_charge_tax: 0,
|
|
195
|
+
discount_list: [],
|
|
196
|
+
relation_surcharge_ids: [],
|
|
197
|
+
option: zeroOptions(bundle?.option),
|
|
198
|
+
metadata: {
|
|
199
|
+
...(bundle?.metadata || {}),
|
|
200
|
+
surcharge_fee: '0.00',
|
|
201
|
+
relation_surcharge_ids: [],
|
|
202
|
+
product_discount_difference: '',
|
|
203
|
+
tax_fee_rounding_remainder: '0.00',
|
|
204
|
+
surcharge_rounding_remainder: '0.00'
|
|
205
|
+
}
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* 将已选择虚拟币的订单商品行固化为最终价语义。
|
|
211
|
+
* 函数幂等,可安全用于加车、合并、hydrate 和提交前兜底。
|
|
212
|
+
*/
|
|
213
|
+
function normalizeVirtualSettlementOrderProduct(product) {
|
|
214
|
+
const snapshot = getSelectedSettlementSnapshot(product);
|
|
215
|
+
if (snapshot?.settlement_type !== 'virtual_currency') return product;
|
|
216
|
+
const virtualPrice = toMoney(snapshot.price);
|
|
217
|
+
const metadata = {
|
|
218
|
+
...(product.metadata || {}),
|
|
219
|
+
source_product_price: virtualPrice,
|
|
220
|
+
main_product_original_price: virtualPrice,
|
|
221
|
+
main_product_selling_price: virtualPrice,
|
|
222
|
+
main_product_attached_bundle_selling_price: virtualPrice,
|
|
223
|
+
main_product_attached_bundle_payment_price: virtualPrice,
|
|
224
|
+
main_product_attached_bundle_surcharge_fee: '0.00',
|
|
225
|
+
main_product_attached_bundle_tax_fee: '0.00',
|
|
226
|
+
surcharge_rounding_remainder: '0.00',
|
|
227
|
+
tax_fee_rounding_remainder: '0.00',
|
|
228
|
+
relation_surcharge_ids: [],
|
|
229
|
+
average_discount_amount_rate: '1',
|
|
230
|
+
product_discount_difference: '',
|
|
231
|
+
discountable_flag: 0,
|
|
232
|
+
price_schema_version: 2,
|
|
233
|
+
selected_settlement_snapshot: {
|
|
234
|
+
...snapshot,
|
|
235
|
+
price: virtualPrice
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
...product,
|
|
240
|
+
selling_price: virtualPrice,
|
|
241
|
+
original_price: virtualPrice,
|
|
242
|
+
payment_price: virtualPrice,
|
|
243
|
+
discount_list: [],
|
|
244
|
+
is_charge_tax: 0,
|
|
245
|
+
tax_fee: '0.00',
|
|
246
|
+
original_tax_fee: 0,
|
|
247
|
+
tax_fee_rounding_remainder: 0,
|
|
248
|
+
original_tax_fee_rounding_remainder: 0,
|
|
249
|
+
surcharge_fee: '0.00',
|
|
250
|
+
surcharge_rounding_remainder: 0,
|
|
251
|
+
relation_surcharge_ids: [],
|
|
252
|
+
product_sku: {
|
|
253
|
+
...(product.product_sku || {}),
|
|
254
|
+
option: zeroOptions(product.product_sku?.option)
|
|
255
|
+
},
|
|
256
|
+
product_bundle: zeroBundles(product.product_bundle),
|
|
257
|
+
metadata
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function normalizeVirtualSettlementProducts(products) {
|
|
261
|
+
return (products || []).map(product => normalizeVirtualSettlementOrderProduct(product));
|
|
262
|
+
}
|
|
@@ -232,6 +232,7 @@ export declare function buildSubmitPayload(params: {
|
|
|
232
232
|
type?: string;
|
|
233
233
|
summary?: OrderSummary | null;
|
|
234
234
|
request_unique_idempotency_token?: string;
|
|
235
|
+
includePaymentStatus?: boolean;
|
|
235
236
|
enhance?: SubmitPayloadEnhancer;
|
|
236
237
|
}): OrderSubmitPayload;
|
|
237
238
|
export declare function mapPaymentItemToOrderPayment(paymentItem: OrderPaymentSource): OrderPaymentData;
|
|
@@ -864,7 +864,7 @@ function normalizeSubmitProductionCode(value) {
|
|
|
864
864
|
}
|
|
865
865
|
|
|
866
866
|
// 后端 checkout 协议字段 option_group_item_id;tempOrder 内部也保持同一字段名。
|
|
867
|
-
function formatSubmitOptionItems(options) {
|
|
867
|
+
function formatSubmitOptionItems(options, formatOptions = {}) {
|
|
868
868
|
if (!Array.isArray(options)) return [];
|
|
869
869
|
return options.map(d => {
|
|
870
870
|
const option = {
|
|
@@ -877,7 +877,11 @@ function formatSubmitOptionItems(options) {
|
|
|
877
877
|
delete option.production_code;
|
|
878
878
|
if (productionCode !== undefined) option.production_code = productionCode;
|
|
879
879
|
const addPrice = d?.add_price ?? d?.price;
|
|
880
|
-
if (
|
|
880
|
+
if (formatOptions.virtualSettlementMode) {
|
|
881
|
+
option.add_price = 0;
|
|
882
|
+
} else if (addPrice !== undefined) {
|
|
883
|
+
option.add_price = String(addPrice);
|
|
884
|
+
}
|
|
881
885
|
delete option.price;
|
|
882
886
|
return option;
|
|
883
887
|
});
|
|
@@ -894,7 +898,7 @@ function toMoneyString(value) {
|
|
|
894
898
|
}
|
|
895
899
|
|
|
896
900
|
// 出站补齐:只输出后端 checkout 协议字段,运行时/详情展示字段不进入 bundle payload。
|
|
897
|
-
function formatSubmitBundleItems(bundle) {
|
|
901
|
+
function formatSubmitBundleItems(bundle, formatOptions = {}) {
|
|
898
902
|
if (!Array.isArray(bundle)) return [];
|
|
899
903
|
return bundle.map(b => {
|
|
900
904
|
const rawBundle = b && typeof b === 'object' ? b : {};
|
|
@@ -906,10 +910,10 @@ function formatSubmitBundleItems(bundle) {
|
|
|
906
910
|
|
|
907
911
|
// bundle_selling_price 出站存「正净额」:markdown 为 |price| − Σoptions(如 3.70),
|
|
908
912
|
// markup/原价维持原值;与后端口径一致(price 仍为毛价)。
|
|
909
|
-
const sellingPrice = getBundleSellingMagnitude(rawBundle).toFixed(2);
|
|
913
|
+
const sellingPrice = formatOptions.virtualSettlementMode ? '0.00' : getBundleSellingMagnitude(rawBundle).toFixed(2);
|
|
910
914
|
// payment 价由整单折扣均摊层产出;缺省(无折扣)时与 selling 净额同义。
|
|
911
|
-
const paymentPrice = rawBundle.bundle_payment_price !== undefined && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== '' ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
|
|
912
|
-
const priceValue = rawBundle.price ?? rawBundle.custom_price ?? rawBundle.bundle_selling_price;
|
|
915
|
+
const paymentPrice = formatOptions.virtualSettlementMode ? '0.00' : rawBundle.bundle_payment_price !== undefined && rawBundle.bundle_payment_price !== null && rawBundle.bundle_payment_price !== '' ? toMoneyString(rawBundle.bundle_payment_price) : sellingPrice;
|
|
916
|
+
const priceValue = formatOptions.virtualSettlementMode ? 0 : rawBundle.price ?? rawBundle.custom_price ?? rawBundle.bundle_selling_price;
|
|
913
917
|
const relationSurchargeIds = Array.isArray(rawBundle.relation_surcharge_ids) ? rawBundle.relation_surcharge_ids : Array.isArray(existedMetadata.relation_surcharge_ids) ? existedMetadata.relation_surcharge_ids : [];
|
|
914
918
|
const surchargeFee = toMoneyString(rawBundle.surcharge_fee ?? existedMetadata.surcharge_fee);
|
|
915
919
|
const productDiscountDifference = toBundleNumber(existedMetadata.product_discount_difference, 0);
|
|
@@ -918,7 +922,7 @@ function formatSubmitBundleItems(bundle) {
|
|
|
918
922
|
const hasSubmitBundleDiscounts = Array.isArray(rawBundle.discount_list) && rawBundle.discount_list.length > 0;
|
|
919
923
|
const productionCode = normalizeSubmitProductionCode(rawBundle.production_code);
|
|
920
924
|
return {
|
|
921
|
-
is_charge_tax: rawBundle.is_charge_tax ?? 0,
|
|
925
|
+
is_charge_tax: formatOptions.virtualSettlementMode ? 0 : rawBundle.is_charge_tax ?? 0,
|
|
922
926
|
bundle_variant_id: rawBundle.bundle_variant_id ?? 0,
|
|
923
927
|
...(productionCode !== undefined ? {
|
|
924
928
|
production_code: productionCode
|
|
@@ -932,7 +936,7 @@ function formatSubmitBundleItems(bundle) {
|
|
|
932
936
|
price_type_ext: rawBundle.price_type_ext ?? rawBundle.custom_price_type_ext ?? '',
|
|
933
937
|
bundle_selling_price: sellingPrice,
|
|
934
938
|
bundle_payment_price: paymentPrice,
|
|
935
|
-
option: formatSubmitOptionItems(rawBundle.option),
|
|
939
|
+
option: formatSubmitOptionItems(rawBundle.option, formatOptions),
|
|
936
940
|
bundle_group_id: rawBundle?.bundle_group_id ?? rawBundle?.group_id,
|
|
937
941
|
bundle_id: rawBundle?.bundle_id ?? rawBundle?.id,
|
|
938
942
|
bundle_product_id: rawBundle?.bundle_product_id ?? rawBundle?._bundle_product_id,
|
|
@@ -942,9 +946,9 @@ function formatSubmitBundleItems(bundle) {
|
|
|
942
946
|
...(hasSubmitBundleDiscounts && bundleMapId !== undefined ? {
|
|
943
947
|
custom_product_bundle_map_id: bundleMapId
|
|
944
948
|
} : {}),
|
|
945
|
-
surcharge_fee: surchargeFee,
|
|
946
|
-
relation_surcharge_ids: relationSurchargeIds,
|
|
947
|
-
product_discount_difference: productDiscountDifference
|
|
949
|
+
surcharge_fee: formatOptions.virtualSettlementMode ? '0.00' : surchargeFee,
|
|
950
|
+
relation_surcharge_ids: formatOptions.virtualSettlementMode ? [] : relationSurchargeIds,
|
|
951
|
+
product_discount_difference: formatOptions.virtualSettlementMode ? '' : productDiscountDifference
|
|
948
952
|
}
|
|
949
953
|
};
|
|
950
954
|
});
|
|
@@ -964,9 +968,9 @@ function formatSubmitBundleItems(bundle) {
|
|
|
964
968
|
* - `metadata.main_product_selling_price`:含 option、含主商品折扣。
|
|
965
969
|
* - `metadata.price_schema_version`:schema 版本号(当前 = 2),用于跨端协商价格口径。
|
|
966
970
|
*
|
|
967
|
-
*
|
|
971
|
+
* 法币仅做字段/metadata 裁剪;虚拟币在出站前再次执行零加价与固定单价断言。
|
|
968
972
|
*/
|
|
969
|
-
function normalizeSubmitProduct(product) {
|
|
973
|
+
function normalizeSubmitProduct(product, formatOptions = {}) {
|
|
970
974
|
const {
|
|
971
975
|
unique_identification_number: _runtimeUid,
|
|
972
976
|
...submitProduct
|
|
@@ -994,7 +998,7 @@ function normalizeSubmitProduct(product) {
|
|
|
994
998
|
if (rawMetadata.unique_identification_number) {
|
|
995
999
|
cleanMetadata.unique_identification_number = rawMetadata.unique_identification_number;
|
|
996
1000
|
}
|
|
997
|
-
const priceMetaKeys = ['main_product_original_price', 'main_product_selling_price', 'main_product_attached_bundle_selling_price', 'main_product_attached_bundle_payment_price', 'average_discount_amount_rate', 'source_product_price', 'main_product_attached_bundle_surcharge_fee', 'main_product_attached_bundle_tax_fee', 'surcharge_rounding_remainder', 'tax_fee_rounding_remainder', 'relation_surcharge_ids', 'discountable_flag', 'parent_unique_identification_number', 'product_add_schedule_time'];
|
|
1001
|
+
const priceMetaKeys = ['main_product_original_price', 'main_product_selling_price', 'main_product_attached_bundle_selling_price', 'main_product_attached_bundle_payment_price', 'average_discount_amount_rate', 'source_product_price', 'main_product_attached_bundle_surcharge_fee', 'main_product_attached_bundle_tax_fee', 'surcharge_rounding_remainder', 'tax_fee_rounding_remainder', 'relation_surcharge_ids', 'discountable_flag', 'price_schema_version', 'parent_unique_identification_number', 'product_add_schedule_time', 'data_variant_ids'];
|
|
998
1002
|
for (const key of priceMetaKeys) {
|
|
999
1003
|
if (rawMetadata[key] !== undefined) {
|
|
1000
1004
|
cleanMetadata[key] = rawMetadata[key];
|
|
@@ -1010,12 +1014,36 @@ function normalizeSubmitProduct(product) {
|
|
|
1010
1014
|
if (rawMetadata.holder_config !== undefined) {
|
|
1011
1015
|
cleanMetadata.holder_config = rawMetadata.holder_config;
|
|
1012
1016
|
}
|
|
1017
|
+
const virtualPrice = toMoneyString(rawMetadata.selected_settlement_snapshot?.price ?? submitProduct.selling_price);
|
|
1018
|
+
if (formatOptions.virtualSettlementMode) {
|
|
1019
|
+
Object.assign(cleanMetadata, {
|
|
1020
|
+
source_product_price: virtualPrice,
|
|
1021
|
+
main_product_original_price: virtualPrice,
|
|
1022
|
+
main_product_selling_price: virtualPrice,
|
|
1023
|
+
main_product_attached_bundle_selling_price: virtualPrice,
|
|
1024
|
+
main_product_attached_bundle_payment_price: virtualPrice,
|
|
1025
|
+
main_product_attached_bundle_surcharge_fee: '0.00',
|
|
1026
|
+
main_product_attached_bundle_tax_fee: '0.00',
|
|
1027
|
+
surcharge_rounding_remainder: '0.00',
|
|
1028
|
+
tax_fee_rounding_remainder: '0.00',
|
|
1029
|
+
relation_surcharge_ids: [],
|
|
1030
|
+
average_discount_amount_rate: '1',
|
|
1031
|
+
product_discount_difference: '',
|
|
1032
|
+
discountable_flag: 0,
|
|
1033
|
+
price_schema_version: 2
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1013
1036
|
const productSku = {
|
|
1014
1037
|
...(submitProduct.product_sku && typeof submitProduct.product_sku === 'object' ? submitProduct.product_sku : {}),
|
|
1015
|
-
option: formatSubmitOptionItems(submitProduct.product_sku?.option)
|
|
1038
|
+
option: formatSubmitOptionItems(submitProduct.product_sku?.option, formatOptions)
|
|
1016
1039
|
};
|
|
1017
1040
|
return {
|
|
1018
1041
|
...productRest,
|
|
1042
|
+
...(formatOptions.virtualSettlementMode ? {
|
|
1043
|
+
selling_price: virtualPrice,
|
|
1044
|
+
original_price: virtualPrice,
|
|
1045
|
+
is_charge_tax: 0
|
|
1046
|
+
} : {}),
|
|
1019
1047
|
...(productionCode !== undefined ? {
|
|
1020
1048
|
production_code: productionCode
|
|
1021
1049
|
} : {}),
|
|
@@ -1027,12 +1055,12 @@ function normalizeSubmitProduct(product) {
|
|
|
1027
1055
|
} : {}),
|
|
1028
1056
|
product_quantity: toBundleNumber(num ?? submitProduct.product_quantity, 1),
|
|
1029
1057
|
product_sku: productSku,
|
|
1030
|
-
discount_list: collectSubmitProductDiscountList(submitProduct),
|
|
1031
|
-
product_bundle: formatSubmitBundleItems(submitProduct.product_bundle),
|
|
1058
|
+
discount_list: formatOptions.virtualSettlementMode ? [] : collectSubmitProductDiscountList(submitProduct),
|
|
1059
|
+
product_bundle: formatSubmitBundleItems(submitProduct.product_bundle, formatOptions),
|
|
1032
1060
|
metadata: cleanMetadata,
|
|
1033
1061
|
// 出站兼容:后端消费 payment_price 字段(行 composite 已减整单折扣均摊)。
|
|
1034
1062
|
// 由整单折扣均摊层产出;缺省(无折扣)时与 selling_price 同义。
|
|
1035
|
-
payment_price: submitProduct.payment_price ?? submitProduct.selling_price
|
|
1063
|
+
payment_price: formatOptions.virtualSettlementMode ? virtualPrice : submitProduct.payment_price ?? submitProduct.selling_price
|
|
1036
1064
|
};
|
|
1037
1065
|
}
|
|
1038
1066
|
const SUBMIT_BOOKING_METADATA_WHITELIST = ['unique_identification_number', 'collect_pax', 'capacity', 'holder_id', 'resource_select_type', 'holder'];
|
|
@@ -1205,6 +1233,7 @@ function buildSubmitPayload(params) {
|
|
|
1205
1233
|
} = params;
|
|
1206
1234
|
const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
|
|
1207
1235
|
const bookingUuid = (0, _orderCollectionIdentity.createUuidV4)();
|
|
1236
|
+
const virtualSettlementMode = tempOrder.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
|
|
1208
1237
|
const {
|
|
1209
1238
|
_extend: _extend,
|
|
1210
1239
|
relation_id: _relationId,
|
|
@@ -1224,6 +1253,7 @@ function buildSubmitPayload(params) {
|
|
|
1224
1253
|
total_refund_amount: _totalRefundAmount,
|
|
1225
1254
|
create_date: _createDate,
|
|
1226
1255
|
holder_id: _holderId,
|
|
1256
|
+
payment_status: _paymentStatus,
|
|
1227
1257
|
notes: _notes,
|
|
1228
1258
|
...tempOrderRest
|
|
1229
1259
|
} = tempOrder;
|
|
@@ -1253,7 +1283,9 @@ function buildSubmitPayload(params) {
|
|
|
1253
1283
|
sales_channel: tempOrder.sales_channel || 'my_pisel',
|
|
1254
1284
|
order_sales_channel: channel ?? tempOrder.order_sales_channel ?? 'online_store',
|
|
1255
1285
|
status: tempOrder.status || 'normal',
|
|
1256
|
-
|
|
1286
|
+
...(params.includePaymentStatus !== false ? {
|
|
1287
|
+
payment_status: tempOrder.payment_status || 'payment_processing'
|
|
1288
|
+
} : {}),
|
|
1257
1289
|
// shipping_status: tempOrder.shipping_status || 'unfulfilled',
|
|
1258
1290
|
is_price_include_tax: tempOrder.is_price_include_tax ?? 1,
|
|
1259
1291
|
currency_format: tempOrder.currency_format || 'symbol_first',
|
|
@@ -1276,6 +1308,9 @@ function buildSubmitPayload(params) {
|
|
|
1276
1308
|
const {
|
|
1277
1309
|
collect_pax: _collectPax,
|
|
1278
1310
|
table_occupancy_duration: _tableOccupancyDuration,
|
|
1311
|
+
cart_settlement_key: _cartSettlementKey,
|
|
1312
|
+
cart_settlement_snapshot: _cartSettlementSnapshot,
|
|
1313
|
+
legal_currency_snapshot: _legalCurrencySnapshot,
|
|
1279
1314
|
...rest
|
|
1280
1315
|
} = tempOrder.metadata || {};
|
|
1281
1316
|
return {
|
|
@@ -1287,7 +1322,9 @@ function buildSubmitPayload(params) {
|
|
|
1287
1322
|
allowUnresolvedOrderTarget: true
|
|
1288
1323
|
})
|
|
1289
1324
|
} : {}),
|
|
1290
|
-
products: (tempOrder.products || []).map(product => normalizeSubmitProduct(product
|
|
1325
|
+
products: (tempOrder.products || []).map(product => normalizeSubmitProduct(product, {
|
|
1326
|
+
virtualSettlementMode
|
|
1327
|
+
}))
|
|
1291
1328
|
};
|
|
1292
1329
|
if (!enhance) return payload;
|
|
1293
1330
|
const enhancedPayload = enhance(payload, {
|
|
@@ -23,12 +23,25 @@ export interface ProductDataVariant {
|
|
|
23
23
|
module_data_id: number;
|
|
24
24
|
/** 关联 data_variant_rule.id */
|
|
25
25
|
data_variant_rule_id: number;
|
|
26
|
+
/** 多货币结算等业务类型 */
|
|
27
|
+
business_type?: 'multi_currency_settlement' | string;
|
|
28
|
+
/** 数据状态;多货币结算仅处理 enable 记录 */
|
|
29
|
+
status?: 'enable' | 'disable' | string;
|
|
26
30
|
/** 命中策略后覆盖到商品上的字段 */
|
|
27
31
|
data: Record<string, any>;
|
|
28
32
|
created_at: string | null;
|
|
29
33
|
updated_at: string | null;
|
|
30
34
|
deleted_at: string | null;
|
|
31
35
|
}
|
|
36
|
+
export interface ProductSettlementOption extends Record<string, any> {
|
|
37
|
+
settlement_type: 'legal_currency' | 'virtual_currency' | string;
|
|
38
|
+
currency_product_id?: number;
|
|
39
|
+
price: string;
|
|
40
|
+
data_variant_id?: number;
|
|
41
|
+
data_variant_rule_id: number | string;
|
|
42
|
+
available: boolean;
|
|
43
|
+
disabled_reason?: string;
|
|
44
|
+
}
|
|
32
45
|
/**
|
|
33
46
|
* 商品基本信息接口
|
|
34
47
|
*/
|
|
@@ -61,6 +74,8 @@ export interface ProductData {
|
|
|
61
74
|
sum_stock: number;
|
|
62
75
|
/** 商品价格 */
|
|
63
76
|
price: string;
|
|
77
|
+
/** 当前上下文解析出的可选结算货币 */
|
|
78
|
+
available_settlement_options?: ProductSettlementOption[];
|
|
64
79
|
/** 商品原价 */
|
|
65
80
|
original_price: string;
|
|
66
81
|
/** 商品成本价 */
|
|
@@ -239,6 +254,14 @@ export interface ProductData {
|
|
|
239
254
|
option_group_count: number;
|
|
240
255
|
/** 智能定价变体列表,/product/query with dataVariants 返回 */
|
|
241
256
|
data_variants?: ProductDataVariant[];
|
|
257
|
+
/**
|
|
258
|
+
* 商品接口规则计算结果;data_variant_ids 按优先级从高到低排列。
|
|
259
|
+
* 空数组表示规则已经计算完成但没有命中 Data Variant。
|
|
260
|
+
*/
|
|
261
|
+
metadata?: {
|
|
262
|
+
data_variant_ids?: Array<number | string>;
|
|
263
|
+
[key: string]: any;
|
|
264
|
+
};
|
|
242
265
|
/** 服务时长 */
|
|
243
266
|
service_times?: any;
|
|
244
267
|
}
|
|
@@ -14,6 +14,11 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
|
|
|
14
14
|
setRulesList(rulesList: Rules[]): Promise<void>;
|
|
15
15
|
getRulesList(): Rules[];
|
|
16
16
|
getWalletPassEvaluator(): import("../..").WalletPassEvaluator | undefined;
|
|
17
|
+
private normalizeHolderRecordIds;
|
|
18
|
+
/**
|
|
19
|
+
* 特定 form Holder 卡只授权给绑定同一 Holder Record 的商品行。
|
|
20
|
+
* required/isNeedHolder 仅控制是否强制选择 Holder,不参与优惠资格。
|
|
21
|
+
*/
|
|
17
22
|
private checkHolderMatch;
|
|
18
23
|
isDiscountListAvailable({ oldDiscountList, newDiscountList, productList, orderTotalAmount, holders, isFormSubject, }: {
|
|
19
24
|
oldDiscountList: Discount[];
|
|
@@ -38,21 +38,30 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
38
38
|
getWalletPassEvaluator() {
|
|
39
39
|
return this.window.getWalletPassEvaluator?.();
|
|
40
40
|
}
|
|
41
|
+
normalizeHolderRecordIds(value) {
|
|
42
|
+
const records = Array.isArray(value) ? value : [value];
|
|
43
|
+
return Array.from(new Set(records.map(record => {
|
|
44
|
+
if (record && typeof record === 'object') {
|
|
45
|
+
return record.form_record_id;
|
|
46
|
+
}
|
|
47
|
+
return record;
|
|
48
|
+
}).filter(record => record !== undefined && record !== null && record !== '' && record !== 0 && record !== '0').map(String)));
|
|
49
|
+
}
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
/**
|
|
52
|
+
* 特定 form Holder 卡只授权给绑定同一 Holder Record 的商品行。
|
|
53
|
+
* required/isNeedHolder 仅控制是否强制选择 Holder,不参与优惠资格。
|
|
54
|
+
*/
|
|
43
55
|
checkHolderMatch(discount, product, holders) {
|
|
44
56
|
// 非表单类型 holder 视为匹配
|
|
45
57
|
if (discount.holder?.holder_type !== 'form') return true;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (!orderHolderId && !productHolderId) return false;
|
|
54
|
-
// 最终直接匹配 holder 是否相同
|
|
55
|
-
return (productHolderId || orderHolderId) === discount.holder.holder_id;
|
|
58
|
+
const discountHolderIds = this.normalizeHolderRecordIds(discount.holder.holder_id);
|
|
59
|
+
if (!discountHolderIds.length) return false;
|
|
60
|
+
const productHolderIds = this.normalizeHolderRecordIds(product.holder_id);
|
|
61
|
+
const candidateHolderIds = productHolderIds.length ? productHolderIds : this.normalizeHolderRecordIds(holders);
|
|
62
|
+
if (!candidateHolderIds.length) return false;
|
|
63
|
+
const discountHolderIdSet = new Set(discountHolderIds);
|
|
64
|
+
return candidateHolderIds.some(holderId => discountHolderIdSet.has(holderId));
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
// 判断discountList 是否可以对当前productList生效
|
|
@@ -30,6 +30,7 @@ export declare class SalesSummaryModule extends BaseModule implements Module, Sa
|
|
|
30
30
|
taxRate?: number;
|
|
31
31
|
shopDiscount?: string | number;
|
|
32
32
|
channel?: string;
|
|
33
|
+
virtualSettlementMode?: boolean;
|
|
33
34
|
}): Promise<{
|
|
34
35
|
tax_title: string;
|
|
35
36
|
tax_rate: number | undefined;
|
|
@@ -126,7 +126,8 @@ class SalesSummaryModule extends _BaseModule.BaseModule {
|
|
|
126
126
|
isPriceIncludeTax,
|
|
127
127
|
taxRate,
|
|
128
128
|
shopDiscount,
|
|
129
|
-
channel
|
|
129
|
+
channel,
|
|
130
|
+
virtualSettlementMode = false
|
|
130
131
|
} = params;
|
|
131
132
|
const summaryChannel = channel || this.resolveChannel();
|
|
132
133
|
if (summaryChannel !== this.surchargeListChannel) {
|
|
@@ -151,7 +152,8 @@ class SalesSummaryModule extends _BaseModule.BaseModule {
|
|
|
151
152
|
surchargeList: this.store.surchargeList,
|
|
152
153
|
scheduleById,
|
|
153
154
|
isInScheduleByDate: _Schedule.ScheduleModule.isInScheduleByDate,
|
|
154
|
-
shopDiscount
|
|
155
|
+
shopDiscount,
|
|
156
|
+
virtualSettlementMode
|
|
155
157
|
});
|
|
156
158
|
const summaryWithTaxMeta = {
|
|
157
159
|
...summary,
|
|
@@ -837,11 +837,27 @@ function calculateSalesSummary(params) {
|
|
|
837
837
|
surchargeList,
|
|
838
838
|
scheduleById = {},
|
|
839
839
|
isInScheduleByDate,
|
|
840
|
-
shopDiscount
|
|
840
|
+
shopDiscount,
|
|
841
|
+
virtualSettlementMode = false
|
|
841
842
|
} = params;
|
|
842
843
|
if (!products?.length) return createEmptySalesSummary();
|
|
843
844
|
const summaryProducts = products.filter(product => !isGeneratedVoucherProduct(product));
|
|
844
845
|
if (!summaryProducts.length) return createEmptySalesSummary();
|
|
846
|
+
if (virtualSettlementMode) {
|
|
847
|
+
const productQuantity = summaryProducts.reduce((sum, item) => sum + getSafeNum(item.num), 0);
|
|
848
|
+
const productAmount = summaryProducts.reduce((sum, item) => sum.plus(toDecimal(item.selling_price).times(getSafeNum(item.num))), new _decimal.default(0));
|
|
849
|
+
const amount = toFixed2(productAmount);
|
|
850
|
+
return {
|
|
851
|
+
...createEmptySalesSummary(),
|
|
852
|
+
product_quantity: productQuantity,
|
|
853
|
+
product_original_amount: amount,
|
|
854
|
+
product_amount: amount,
|
|
855
|
+
product_expect_amount: amount,
|
|
856
|
+
expect_amount: amount,
|
|
857
|
+
total_amount: amount,
|
|
858
|
+
is_price_include_tax: isPriceIncludeTax
|
|
859
|
+
};
|
|
860
|
+
}
|
|
845
861
|
const productQuantity = summaryProducts.reduce((sum, item) => sum + getSafeNum(item.num), 0);
|
|
846
862
|
const productOriginalAmount = summaryProducts.reduce((sum, item) => sum.plus(getUnitOriginalTotal(item).times(getSafeNum(item.num))), new _decimal.default(0));
|
|
847
863
|
const productAmount = summaryProducts.reduce((sum, item) => sum.plus(getUnitPaymentTotal(item).times(getSafeNum(item.num))), new _decimal.default(0));
|