@pisell/pisellos 2.3.95 → 2.3.96
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.js +13 -2
- package/dist/modules/Order/index.d.ts +2 -0
- package/dist/modules/Order/index.js +51 -28
- package/dist/modules/SalesSummary/index.js +6 -4
- package/dist/server/index.js +14 -8
- package/dist/server/modules/products/index.d.ts +2 -2
- package/dist/server/modules/products/index.js +10 -9
- package/dist/server/utils/product.d.ts +1 -1
- package/dist/server/utils/product.js +186 -22
- package/dist/server/utils/small-ticket.js +23 -2
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +12 -2
- package/lib/modules/Order/index.d.ts +2 -0
- package/lib/modules/Order/index.js +33 -14
- package/lib/modules/SalesSummary/index.js +3 -1
- package/lib/server/index.js +10 -6
- package/lib/server/modules/products/index.d.ts +2 -2
- package/lib/server/modules/products/index.js +5 -4
- package/lib/server/utils/product.d.ts +1 -1
- package/lib/server/utils/product.js +163 -3
- package/lib/server/utils/small-ticket.js +22 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +3 -2
- package/package.json +1 -1
|
@@ -194,9 +194,139 @@ const I18N_FIELD_MAP = {
|
|
|
194
194
|
description_i18n: 'description',
|
|
195
195
|
cover_i18n: 'cover'
|
|
196
196
|
};
|
|
197
|
+
/**
|
|
198
|
+
* 按当前语言读取 i18n 文案;当前语言为空时回退到商家原始文案。
|
|
199
|
+
*/
|
|
200
|
+
function resolveI18nValue(i18nDict, locale) {
|
|
201
|
+
if (!i18nDict) return undefined;
|
|
202
|
+
return i18nDict[locale] || i18nDict.original || undefined;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 递归格式化商品分类名称,同时保留未变化节点的引用。
|
|
207
|
+
*/
|
|
208
|
+
function applyI18nToCategory(category, locale) {
|
|
209
|
+
if (!category || typeof category !== 'object') return category;
|
|
210
|
+
const localizedName = resolveI18nValue(category.name_i18n, locale);
|
|
211
|
+
const localizedParent = applyI18nToCategory(category.parent_category, locale);
|
|
212
|
+
const nameChanged = localizedName !== undefined && localizedName !== category.name;
|
|
213
|
+
const parentChanged = localizedParent !== category.parent_category;
|
|
214
|
+
if (!nameChanged && !parentChanged) return category;
|
|
215
|
+
return {
|
|
216
|
+
...category,
|
|
217
|
+
...(nameChanged ? {
|
|
218
|
+
name: localizedName
|
|
219
|
+
} : {}),
|
|
220
|
+
...(parentChanged ? {
|
|
221
|
+
parent_category: localizedParent
|
|
222
|
+
} : {})
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function applyI18nToCategories(categories, locale) {
|
|
226
|
+
if (!Array.isArray(categories)) return categories;
|
|
227
|
+
let changed = false;
|
|
228
|
+
const localizedCategories = categories.map(category => {
|
|
229
|
+
const localizedCategory = applyI18nToCategory(category, locale);
|
|
230
|
+
if (localizedCategory !== category) changed = true;
|
|
231
|
+
return localizedCategory;
|
|
232
|
+
});
|
|
233
|
+
return changed ? localizedCategories : categories;
|
|
234
|
+
}
|
|
235
|
+
function applyI18nToNamedItems(items, locale) {
|
|
236
|
+
if (!Array.isArray(items)) return items;
|
|
237
|
+
let changed = false;
|
|
238
|
+
const localizedItems = items.map(item => {
|
|
239
|
+
if (!item || typeof item !== 'object') return item;
|
|
240
|
+
const localizedName = resolveI18nValue(item.name_i18n, locale);
|
|
241
|
+
if (localizedName === undefined || localizedName === item.name) return item;
|
|
242
|
+
changed = true;
|
|
243
|
+
return {
|
|
244
|
+
...item,
|
|
245
|
+
name: localizedName
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
return changed ? localizedItems : items;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* 格式化选项组、规格组及其子项名称,同时保留未变化节点的引用。
|
|
253
|
+
*/
|
|
254
|
+
function applyI18nToNamedGroups(groups, itemKey, locale) {
|
|
255
|
+
if (!Array.isArray(groups)) return groups;
|
|
256
|
+
let changed = false;
|
|
257
|
+
const localizedGroups = groups.map(group => {
|
|
258
|
+
if (!group || typeof group !== 'object') return group;
|
|
259
|
+
const localizedName = resolveI18nValue(group.name_i18n, locale);
|
|
260
|
+
const localizedItems = applyI18nToNamedItems(group[itemKey], locale);
|
|
261
|
+
const nameChanged = localizedName !== undefined && localizedName !== group.name;
|
|
262
|
+
const itemsChanged = localizedItems !== group[itemKey];
|
|
263
|
+
if (!nameChanged && !itemsChanged) return group;
|
|
264
|
+
changed = true;
|
|
265
|
+
return {
|
|
266
|
+
...group,
|
|
267
|
+
...(nameChanged ? {
|
|
268
|
+
name: localizedName
|
|
269
|
+
} : {}),
|
|
270
|
+
...(itemsChanged ? {
|
|
271
|
+
[itemKey]: localizedItems
|
|
272
|
+
} : {})
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
return changed ? localizedGroups : groups;
|
|
276
|
+
}
|
|
277
|
+
function applyI18nToBundleItems(items, locale) {
|
|
278
|
+
if (!Array.isArray(items)) return items;
|
|
279
|
+
let changed = false;
|
|
280
|
+
const localizedItems = items.map(item => {
|
|
281
|
+
if (!item || typeof item !== 'object') return item;
|
|
282
|
+
const localizedTitle = resolveI18nValue(item.trans_title, locale);
|
|
283
|
+
const localizedOptionGroups = applyI18nToNamedGroups(item.option_group, 'option_item', locale);
|
|
284
|
+
const titleChanged = localizedTitle !== undefined && localizedTitle !== item.title;
|
|
285
|
+
const optionGroupsChanged = localizedOptionGroups !== item.option_group;
|
|
286
|
+
if (!titleChanged && !optionGroupsChanged) return item;
|
|
287
|
+
changed = true;
|
|
288
|
+
return {
|
|
289
|
+
...item,
|
|
290
|
+
...(titleChanged ? {
|
|
291
|
+
title: localizedTitle
|
|
292
|
+
} : {}),
|
|
293
|
+
...(optionGroupsChanged ? {
|
|
294
|
+
option_group: localizedOptionGroups
|
|
295
|
+
} : {})
|
|
296
|
+
};
|
|
297
|
+
});
|
|
298
|
+
return changed ? localizedItems : items;
|
|
299
|
+
}
|
|
197
300
|
|
|
198
301
|
/**
|
|
199
|
-
*
|
|
302
|
+
* 格式化套餐组名称、套餐子商品标题及子商品选项,同时保留未变化节点的引用。
|
|
303
|
+
*/
|
|
304
|
+
function applyI18nToBundleGroups(groups, locale) {
|
|
305
|
+
if (!Array.isArray(groups)) return groups;
|
|
306
|
+
let changed = false;
|
|
307
|
+
const localizedGroups = groups.map(group => {
|
|
308
|
+
if (!group || typeof group !== 'object') return group;
|
|
309
|
+
const localizedName = resolveI18nValue(group.name_i18n, locale);
|
|
310
|
+
const localizedItems = applyI18nToBundleItems(group.bundle_item, locale);
|
|
311
|
+
const nameChanged = localizedName !== undefined && localizedName !== group.name;
|
|
312
|
+
const itemsChanged = localizedItems !== group.bundle_item;
|
|
313
|
+
if (!nameChanged && !itemsChanged) return group;
|
|
314
|
+
changed = true;
|
|
315
|
+
return {
|
|
316
|
+
...group,
|
|
317
|
+
...(nameChanged ? {
|
|
318
|
+
name: localizedName
|
|
319
|
+
} : {}),
|
|
320
|
+
...(itemsChanged ? {
|
|
321
|
+
bundle_item: localizedItems
|
|
322
|
+
} : {})
|
|
323
|
+
};
|
|
324
|
+
});
|
|
325
|
+
return changed ? localizedGroups : groups;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* 根据 locale 格式化商品、分类、规格及套餐文案,缺少对应语言时回退 original。
|
|
200
330
|
*/
|
|
201
331
|
function applyI18nToProducts(products, locale) {
|
|
202
332
|
if (!locale) return products;
|
|
@@ -205,14 +335,44 @@ function applyI18nToProducts(products, locale) {
|
|
|
205
335
|
for (const [i18nKey, originalKey] of Object.entries(I18N_FIELD_MAP)) {
|
|
206
336
|
const i18nDict = product[i18nKey];
|
|
207
337
|
if (!i18nDict) continue;
|
|
208
|
-
const localizedValue = i18nDict
|
|
209
|
-
if (localizedValue) {
|
|
338
|
+
const localizedValue = resolveI18nValue(i18nDict, locale);
|
|
339
|
+
if (localizedValue !== undefined && localizedValue !== product[originalKey]) {
|
|
210
340
|
if (!patched) patched = {
|
|
211
341
|
...product
|
|
212
342
|
};
|
|
213
343
|
patched[originalKey] = localizedValue;
|
|
214
344
|
}
|
|
215
345
|
}
|
|
346
|
+
for (const categoryKey of ['category', 'categories']) {
|
|
347
|
+
const categories = product[categoryKey];
|
|
348
|
+
const localizedCategories = applyI18nToCategories(categories, locale);
|
|
349
|
+
if (localizedCategories !== categories) {
|
|
350
|
+
if (!patched) patched = {
|
|
351
|
+
...product
|
|
352
|
+
};
|
|
353
|
+
patched[categoryKey] = localizedCategories;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
for (const [groupKey, itemKey] of [['option_group', 'option_item'], ['variant_group', 'variant_item']]) {
|
|
357
|
+
const groups = product[groupKey];
|
|
358
|
+
const localizedGroups = applyI18nToNamedGroups(groups, itemKey, locale);
|
|
359
|
+
if (localizedGroups !== groups) {
|
|
360
|
+
if (!patched) patched = {
|
|
361
|
+
...product
|
|
362
|
+
};
|
|
363
|
+
patched[groupKey] = localizedGroups;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
for (const bundleGroupKey of ['bundle_group', 'bundle_groups']) {
|
|
367
|
+
const groups = product[bundleGroupKey];
|
|
368
|
+
const localizedGroups = applyI18nToBundleGroups(groups, locale);
|
|
369
|
+
if (localizedGroups !== groups) {
|
|
370
|
+
if (!patched) patched = {
|
|
371
|
+
...product
|
|
372
|
+
};
|
|
373
|
+
patched[bundleGroupKey] = localizedGroups;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
216
376
|
return patched ?? product;
|
|
217
377
|
});
|
|
218
378
|
}
|
|
@@ -32,6 +32,7 @@ const LABELS = {
|
|
|
32
32
|
orderDiscount: 'Order discount',
|
|
33
33
|
manualDiscount: 'Manual discount',
|
|
34
34
|
payProcessingFee: 'Pay processing fee',
|
|
35
|
+
surchargeIncluded: 'Surcharge(Included)',
|
|
35
36
|
rounding: 'Rounding',
|
|
36
37
|
gross: 'Gross',
|
|
37
38
|
tare: 'Tare'
|
|
@@ -58,6 +59,7 @@ const LABELS = {
|
|
|
58
59
|
orderDiscount: '整单折扣',
|
|
59
60
|
manualDiscount: '手动折扣',
|
|
60
61
|
payProcessingFee: '支付手续费',
|
|
62
|
+
surchargeIncluded: '手续费(已含)',
|
|
61
63
|
rounding: '抹零',
|
|
62
64
|
gross: '重量',
|
|
63
65
|
tare: '去皮'
|
|
@@ -84,6 +86,7 @@ const LABELS = {
|
|
|
84
86
|
orderDiscount: '整單折扣',
|
|
85
87
|
manualDiscount: '手動折扣',
|
|
86
88
|
payProcessingFee: '支付手續費',
|
|
89
|
+
surchargeIncluded: '手續費(已含)',
|
|
87
90
|
rounding: '抹零',
|
|
88
91
|
gross: '重量',
|
|
89
92
|
tare: '去皮'
|
|
@@ -730,10 +733,17 @@ function buildResources(order, locale) {
|
|
|
730
733
|
function buildPaymentData(params) {
|
|
731
734
|
const payments = normalizeArray(params.order.payments);
|
|
732
735
|
return payments.filter(payment => isPrintablePayment(payment)).map(payment => {
|
|
736
|
+
const serviceFee = getPaymentServiceFee(payment);
|
|
733
737
|
const items = [{
|
|
734
738
|
item: paymentMethodName(payment, params.locale),
|
|
735
|
-
value: formatMoney(payment
|
|
739
|
+
value: formatMoney(resolveReceiptPaymentAmount(payment, serviceFee), params.currencySymbol)
|
|
736
740
|
}];
|
|
741
|
+
if (serviceFee.gt(0)) {
|
|
742
|
+
items.push({
|
|
743
|
+
item: label(params.locale, 'surchargeIncluded'),
|
|
744
|
+
value: formatMoney(serviceFee, params.currencySymbol)
|
|
745
|
+
});
|
|
746
|
+
}
|
|
737
747
|
const fundRecord = getFundRecord(payment);
|
|
738
748
|
if (fundRecord) {
|
|
739
749
|
items.push(...buildFundRecordPaymentItems({
|
|
@@ -758,6 +768,17 @@ function buildPaymentData(params) {
|
|
|
758
768
|
return items;
|
|
759
769
|
});
|
|
760
770
|
}
|
|
771
|
+
function getPaymentServiceFee(payment) {
|
|
772
|
+
return new _decimal.default(toMoneyNumber(payment.service_fee));
|
|
773
|
+
}
|
|
774
|
+
function resolveReceiptPaymentAmount(payment, serviceFee) {
|
|
775
|
+
const amount = new _decimal.default(toMoneyNumber(payment.amount ?? payment.origin_amount));
|
|
776
|
+
const hasAmount = payment.amount !== undefined && payment.amount !== null && payment.amount !== '';
|
|
777
|
+
const hasOriginAmount = payment.origin_amount !== undefined && payment.origin_amount !== null && payment.origin_amount !== '';
|
|
778
|
+
if (!hasAmount || !hasOriginAmount || serviceFee.lte(0)) return amount;
|
|
779
|
+
const originAmount = new _decimal.default(toMoneyNumber(payment.origin_amount));
|
|
780
|
+
return amount.eq(originAmount) ? amount.plus(serviceFee) : amount;
|
|
781
|
+
}
|
|
761
782
|
function buildFundRecordPaymentItems(params) {
|
|
762
783
|
const {
|
|
763
784
|
payment,
|
|
@@ -191,9 +191,10 @@ function transformBaseProductToOrderProduct(params) {
|
|
|
191
191
|
metadata.unique_identification_number = String(uniqueIdentificationNumber);
|
|
192
192
|
}
|
|
193
193
|
// 从源头补充商品多语言标题
|
|
194
|
+
const productTitleI18n = sourceProduct?.title_i18n || {};
|
|
194
195
|
const productTitle = {
|
|
195
|
-
...
|
|
196
|
-
original: sourceProduct?.original_title || sourceProduct?.title || ''
|
|
196
|
+
...productTitleI18n,
|
|
197
|
+
original: productTitleI18n.original || sourceProduct?.original_title || sourceProduct?.title || ''
|
|
197
198
|
};
|
|
198
199
|
return {
|
|
199
200
|
product_id: productId,
|