@pisell/pisellos 0.10.56 → 0.10.58
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/promotion/index.js +9 -0
- package/dist/modules/OpenData/index.js +2 -1
- package/dist/modules/Order/index.d.ts +1 -0
- package/dist/modules/Order/index.js +118 -59
- package/dist/modules/Order/utils/weighedProduct.d.ts +12 -0
- package/dist/modules/Order/utils/weighedProduct.js +94 -0
- package/dist/modules/Order/utils.d.ts +6 -4
- package/dist/modules/Order/utils.js +40 -16
- package/dist/modules/Payment/index.d.ts +0 -5
- package/dist/modules/Payment/index.js +35 -85
- package/dist/modules/ProductList/index.d.ts +3 -1
- package/dist/modules/ProductList/index.js +203 -95
- package/dist/modules/ProductList/types.d.ts +8 -0
- package/dist/modules/ProductList/types.js +2 -0
- package/dist/modules/ResourcePlanner/planner.js +10 -8
- package/dist/modules/Rules/index.js +16 -14
- package/dist/modules/Rules/types.d.ts +2 -0
- package/dist/server/index.js +122 -69
- package/dist/server/modules/floor-plan/index.js +34 -3
- package/dist/server/modules/payment/index.d.ts +25 -6
- package/dist/server/modules/payment/index.js +660 -133
- package/dist/server/test.json +1 -1
- package/dist/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/dist/shared/receipt/customerInvoiceLanguages.js +60 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.d.ts +5 -0
- package/dist/shared/receipt/loadCustomerInvoiceLayout.js +46 -4
- package/dist/shared/receipt/small-ticket.d.ts +11 -0
- package/dist/shared/receipt/small-ticket.js +430 -255
- package/dist/shared/receipt/templateVisibility.d.ts +23 -0
- package/dist/shared/receipt/templateVisibility.js +64 -0
- package/dist/solution/BaseSales/index.d.ts +4 -2
- package/dist/solution/BaseSales/index.js +1328 -1214
- package/dist/solution/BaseSales/types.d.ts +5 -1
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +40 -25
- package/dist/solution/BaseSales/utils.js +3 -2
- package/dist/solution/BookingTicket/index.d.ts +4 -1
- package/dist/solution/BookingTicket/index.js +120 -80
- package/dist/solution/OrderInvoicePreview/index.d.ts +10 -0
- package/dist/solution/OrderInvoicePreview/index.js +85 -14
- package/dist/solution/RegisterAndLogin/config.js +54 -11
- package/dist/solution/RegisterAndLogin/index.d.ts +2 -0
- package/dist/solution/RegisterAndLogin/index.js +1 -1
- package/dist/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/dist/solution/RegisterAndLogin/utils.js +36 -16
- package/dist/solution/Sales/index.d.ts +2 -0
- package/dist/solution/Sales/index.js +15 -1
- package/dist/solution/ScanOrder/utils.js +3 -2
- package/dist/solution/UnifiedBookingSales/index.d.ts +7 -1
- package/dist/solution/UnifiedBookingSales/index.js +560 -401
- package/dist/solution/VenueBooking/index.d.ts +15 -2
- package/dist/solution/VenueBooking/index.js +1062 -785
- package/dist/solution/VenueBooking/types.d.ts +2 -1
- package/dist/solution/VenueBooking/types.js +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/dist/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/dist/solution/VenueBooking/utils/smartPricing.js +273 -0
- package/dist/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/timeSlot.js +6 -3
- package/lib/modules/OpenData/index.js +2 -1
- package/lib/modules/Order/index.d.ts +1 -0
- package/lib/modules/Order/index.js +71 -11
- package/lib/modules/Order/utils/weighedProduct.d.ts +12 -0
- package/lib/modules/Order/utils/weighedProduct.js +89 -0
- package/lib/modules/Order/utils.d.ts +6 -4
- package/lib/modules/Order/utils.js +34 -13
- package/lib/modules/Payment/index.d.ts +0 -5
- package/lib/modules/Payment/index.js +3 -28
- package/lib/modules/ProductList/index.d.ts +3 -1
- package/lib/modules/ProductList/index.js +45 -6
- package/lib/modules/ProductList/types.d.ts +8 -0
- package/lib/modules/ProductList/types.js +1 -0
- package/lib/modules/ResourcePlanner/planner.js +10 -8
- package/lib/modules/Rules/index.js +16 -14
- package/lib/modules/Rules/types.d.ts +2 -0
- package/lib/server/index.js +72 -28
- package/lib/server/modules/floor-plan/index.js +29 -1
- package/lib/server/modules/payment/index.d.ts +25 -6
- package/lib/server/modules/payment/index.js +350 -78
- package/lib/server/test.json +1 -1
- package/lib/shared/receipt/customerInvoiceLanguages.d.ts +8 -0
- package/lib/shared/receipt/customerInvoiceLanguages.js +58 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.d.ts +5 -0
- package/lib/shared/receipt/loadCustomerInvoiceLayout.js +42 -4
- package/lib/shared/receipt/small-ticket.d.ts +11 -0
- package/lib/shared/receipt/small-ticket.js +234 -30
- package/lib/shared/receipt/templateVisibility.d.ts +23 -0
- package/lib/shared/receipt/templateVisibility.js +63 -0
- package/lib/solution/BaseSales/index.d.ts +4 -2
- package/lib/solution/BaseSales/index.js +79 -18
- package/lib/solution/BaseSales/types.d.ts +5 -1
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +24 -9
- package/lib/solution/BaseSales/utils.js +2 -1
- package/lib/solution/BookingTicket/index.d.ts +4 -1
- package/lib/solution/BookingTicket/index.js +14 -2
- package/lib/solution/OrderInvoicePreview/index.d.ts +10 -0
- package/lib/solution/OrderInvoicePreview/index.js +61 -7
- package/lib/solution/RegisterAndLogin/config.js +57 -11
- package/lib/solution/RegisterAndLogin/index.d.ts +2 -0
- package/lib/solution/RegisterAndLogin/index.js +9 -1
- package/lib/solution/RegisterAndLogin/utils.d.ts +12 -4
- package/lib/solution/RegisterAndLogin/utils.js +24 -17
- package/lib/solution/Sales/index.d.ts +2 -0
- package/lib/solution/Sales/index.js +10 -1
- package/lib/solution/ScanOrder/utils.js +2 -1
- package/lib/solution/UnifiedBookingSales/index.d.ts +7 -1
- package/lib/solution/UnifiedBookingSales/index.js +85 -7
- package/lib/solution/VenueBooking/index.d.ts +15 -2
- package/lib/solution/VenueBooking/index.js +243 -96
- package/lib/solution/VenueBooking/types.d.ts +2 -1
- package/lib/solution/VenueBooking/types.js +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +7 -4
- package/lib/solution/VenueBooking/utils/smartPricing.d.ts +71 -0
- package/lib/solution/VenueBooking/utils/smartPricing.js +224 -0
- package/lib/solution/VenueBooking/utils/timeSlot.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/timeSlot.js +5 -2
- package/package.json +1 -1
|
@@ -8,8 +8,49 @@ exports.hasSmallTicketData = hasSmallTicketData;
|
|
|
8
8
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
9
9
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
10
10
|
var _pickupTiming = require("../../modules/Order/pickupTiming");
|
|
11
|
+
var _templateVisibility = require("./templateVisibility");
|
|
11
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
13
|
const DEFAULT_LOCALES = ['en', 'zh_CN'];
|
|
14
|
+
|
|
15
|
+
// Attach provenance to a private copy BEFORE any locale-dependent filtering.
|
|
16
|
+
// Symbols survive the existing spread-based normalization, never enter JSON,
|
|
17
|
+
// and leave both the caller's snapshot and the default native contract intact.
|
|
18
|
+
const RECEIPT_SOURCE = Symbol('customerReceiptSource');
|
|
19
|
+
function copyReceiptSource(value, path = 'order') {
|
|
20
|
+
if (Array.isArray(value)) return value.map((item, index) => copyReceiptSource(item, `${path}/${index}`));
|
|
21
|
+
if (!value || typeof value !== 'object' || Object.getPrototypeOf(value) !== Object.prototype) return value;
|
|
22
|
+
const id = value.metadata?.unique_identification_number ?? value.product_uid ?? value.booking_uid ?? value.order_payment_id ?? value.payment_number ?? value.order_refund_id ?? value.refund_number ?? value.id;
|
|
23
|
+
const source = Object.fromEntries(Object.entries(value).map(([key, item]) => [key, copyReceiptSource(item, `${path}/${key}`)]));
|
|
24
|
+
// Retain the original occurrence even when a catalogue ID appears twice.
|
|
25
|
+
return {
|
|
26
|
+
...source,
|
|
27
|
+
[RECEIPT_SOURCE]: `${path}${id != null ? `@${encodeURIComponent(String(id))}` : ''}`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function receiptKey(source, kind, valueKind = 'shared') {
|
|
31
|
+
const key = source?.[RECEIPT_SOURCE];
|
|
32
|
+
return typeof key === 'string' ? {
|
|
33
|
+
receipt_key: `${key}#${kind}`,
|
|
34
|
+
receipt_value_kind: valueKind
|
|
35
|
+
} : {};
|
|
36
|
+
}
|
|
37
|
+
function receiptSourceIndex(source, index) {
|
|
38
|
+
return source?.[RECEIPT_SOURCE] ? {
|
|
39
|
+
receipt_source_index: index
|
|
40
|
+
} : {};
|
|
41
|
+
}
|
|
42
|
+
function removePrivateReceiptSource(value) {
|
|
43
|
+
if (!value || typeof value !== 'object') return;
|
|
44
|
+
delete value[RECEIPT_SOURCE];
|
|
45
|
+
Object.values(value).forEach(removePrivateReceiptSource);
|
|
46
|
+
}
|
|
47
|
+
function receiptTimeKey(source, kind) {
|
|
48
|
+
const identity = receiptKey(source, kind);
|
|
49
|
+
return identity.receipt_key ? {
|
|
50
|
+
...identity,
|
|
51
|
+
receipt_item_kind: 'shared'
|
|
52
|
+
} : {};
|
|
53
|
+
}
|
|
13
54
|
const SERVICE_TYPE_LABEL_KEYS = {
|
|
14
55
|
takeaway: 'takeAway',
|
|
15
56
|
pick_up: 'pickUp',
|
|
@@ -247,19 +288,23 @@ const LABELS = {
|
|
|
247
288
|
}
|
|
248
289
|
};
|
|
249
290
|
function buildSmallTicketData(params) {
|
|
250
|
-
const order = params.order || {};
|
|
291
|
+
const order = params.includeReceiptKeys ? copyReceiptSource(params.order || {}) : params.order || {};
|
|
251
292
|
const shopInfo = params.shopInfo || {};
|
|
252
293
|
const locales = resolveLocales(shopInfo, params.locales);
|
|
253
294
|
const productMap = params.productMap || {};
|
|
254
|
-
|
|
295
|
+
const visibility = (0, _templateVisibility.resolveInvoiceDataVisibility)(params.templateSettings);
|
|
296
|
+
const result = locales.reduce((data, locale) => {
|
|
255
297
|
data[locale] = buildLocaleData({
|
|
256
298
|
order,
|
|
257
299
|
shopInfo,
|
|
258
300
|
locale,
|
|
259
|
-
productMap
|
|
301
|
+
productMap,
|
|
302
|
+
visibility
|
|
260
303
|
});
|
|
261
304
|
return data;
|
|
262
305
|
}, {});
|
|
306
|
+
if (params.includeReceiptKeys) removePrivateReceiptSource(result);
|
|
307
|
+
return result;
|
|
263
308
|
}
|
|
264
309
|
function hasSmallTicketData(value) {
|
|
265
310
|
return !!value && typeof value === 'object' && Object.keys(value).length > 0;
|
|
@@ -269,13 +314,14 @@ function buildLocaleData(params) {
|
|
|
269
314
|
order,
|
|
270
315
|
shopInfo,
|
|
271
316
|
locale,
|
|
272
|
-
productMap
|
|
317
|
+
productMap,
|
|
318
|
+
visibility
|
|
273
319
|
} = params;
|
|
274
320
|
const products = buildProducts(order, locale, productMap);
|
|
275
321
|
const summary = getSummary(order);
|
|
276
322
|
const currencySymbol = getCurrencySymbol(order, shopInfo);
|
|
277
323
|
const financials = resolveReceiptFinancials(order, summary);
|
|
278
|
-
const delivery = buildDelivery(order, locale);
|
|
324
|
+
const delivery = buildDelivery(order, locale, visibility.handover);
|
|
279
325
|
return {
|
|
280
326
|
base_data: buildBaseData({
|
|
281
327
|
order,
|
|
@@ -294,7 +340,7 @@ function buildLocaleData(params) {
|
|
|
294
340
|
currencySymbol,
|
|
295
341
|
financials
|
|
296
342
|
}),
|
|
297
|
-
customer: buildCustomer(order, locale),
|
|
343
|
+
customer: buildCustomer(order, locale, visibility.customer),
|
|
298
344
|
appointment: buildAppointment(order, locale),
|
|
299
345
|
...(delivery.length ? {
|
|
300
346
|
delivery
|
|
@@ -305,12 +351,18 @@ function buildLocaleData(params) {
|
|
|
305
351
|
locale,
|
|
306
352
|
currencySymbol
|
|
307
353
|
}),
|
|
308
|
-
wallets: buildWallets({
|
|
354
|
+
wallets: visibility.card.show ? buildWallets({
|
|
309
355
|
order,
|
|
310
356
|
locale,
|
|
311
|
-
currencySymbol
|
|
312
|
-
|
|
313
|
-
|
|
357
|
+
currencySymbol,
|
|
358
|
+
passTypes: visibility.card.passTypes
|
|
359
|
+
}) : [],
|
|
360
|
+
// Native printers fall back to tickets when wallets is empty. Legacy rows
|
|
361
|
+
// have no trustworthy asset tags, so they cannot bypass a card whitelist.
|
|
362
|
+
tickets: visibility.card.show && visibility.card.passTypes === null && Array.isArray(order.tickets) ? order.tickets.map(group => Array.isArray(group) ? group.map(row => row && typeof row === 'object' ? {
|
|
363
|
+
...row,
|
|
364
|
+
...receiptKey(row, 'ticket')
|
|
365
|
+
} : row) : group) : [],
|
|
314
366
|
source_shop: [],
|
|
315
367
|
refund_data: buildRefundData({
|
|
316
368
|
order,
|
|
@@ -354,7 +406,7 @@ function buildBaseData(params) {
|
|
|
354
406
|
function buildProducts(order, locale, productMap) {
|
|
355
407
|
const products = Array.isArray(order.products) ? order.products : [];
|
|
356
408
|
const allergyByProductUid = buildProductAllergyMap(order, locale);
|
|
357
|
-
return products.map(rawProduct => {
|
|
409
|
+
return products.map((rawProduct, sourceIndex) => {
|
|
358
410
|
const product = restoreReceiptDiscountHierarchy(rawProduct);
|
|
359
411
|
const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
|
|
360
412
|
const originalPrice = product.original_price ?? product.selling_price ?? product.payment_price ?? product.price ?? 0;
|
|
@@ -399,6 +451,10 @@ function buildProducts(order, locale, productMap) {
|
|
|
399
451
|
const resolvedCombinations = Array.isArray(product.combinations) && product.combinations.length ? normalizeExistingCombinations(product.combinations, locale, currencySymbol) : combinations;
|
|
400
452
|
const shouldIncludeBasePrice = options.length > 0 || resolvedCombinations.length > 0 || hasProductDiscount(product, extensionList);
|
|
401
453
|
return {
|
|
454
|
+
...receiptKey(rawProduct, 'product'),
|
|
455
|
+
...(rawProduct[RECEIPT_SOURCE] ? {
|
|
456
|
+
receipt_source_index: sourceIndex
|
|
457
|
+
} : {}),
|
|
402
458
|
product_title: productTitle,
|
|
403
459
|
product_quantity: quantity,
|
|
404
460
|
selling_price: formatMoney(sellingPrice, currencySymbol),
|
|
@@ -542,6 +598,7 @@ function normalizeProductDiscounts(params) {
|
|
|
542
598
|
const totalAmount = new _decimal.default(toMoneyNumber(amount)).mul(isAggregatedBundleDiscount || isEntitlementPass ? 1 : quantity);
|
|
543
599
|
const formattedAmount = isMarkup ? formatMoney(totalAmount.abs(), currencySymbol) : formatNegativeMoney(totalAmount, currencySymbol);
|
|
544
600
|
return {
|
|
601
|
+
...receiptKey(discount, 'discount'),
|
|
545
602
|
item: title,
|
|
546
603
|
value: formattedAmount,
|
|
547
604
|
isMarkup
|
|
@@ -581,6 +638,7 @@ function buildProductExtensionList(params) {
|
|
|
581
638
|
locale,
|
|
582
639
|
currencySymbol
|
|
583
640
|
}), ...(quantity > 1 ? [{
|
|
641
|
+
...receiptTimeKey(product, 'quantity-price'),
|
|
584
642
|
item: buildProductQuantityPriceText({
|
|
585
643
|
quantity,
|
|
586
644
|
currencySymbol,
|
|
@@ -588,7 +646,10 @@ function buildProductExtensionList(params) {
|
|
|
588
646
|
}),
|
|
589
647
|
value: ''
|
|
590
648
|
}] : [])];
|
|
591
|
-
const productExtensionList = extensionList.length ? extensionList : normalizeArray(product.extension_list)
|
|
649
|
+
const productExtensionList = extensionList.length ? extensionList : normalizeArray(product.extension_list).map(row => ({
|
|
650
|
+
...row,
|
|
651
|
+
...receiptKey(row, 'extension')
|
|
652
|
+
}));
|
|
592
653
|
return [...productExtensionList, ...discountList];
|
|
593
654
|
}
|
|
594
655
|
function buildProductOpenWeightRows(params) {
|
|
@@ -605,10 +666,12 @@ function buildProductOpenWeightRows(params) {
|
|
|
605
666
|
const rows = [];
|
|
606
667
|
if (hasTare) {
|
|
607
668
|
rows.push({
|
|
669
|
+
...receiptKey(product, 'gross'),
|
|
608
670
|
item: `${manualFlag}${label(locale, 'gross')}: ${productSku.weight ?? 0}${unit}`,
|
|
609
671
|
value: ''
|
|
610
672
|
});
|
|
611
673
|
rows.push({
|
|
674
|
+
...receiptKey(product, 'tare'),
|
|
612
675
|
item: `${label(locale, 'tare')}: ${productSku.tare_weight}${unit}`,
|
|
613
676
|
value: ''
|
|
614
677
|
});
|
|
@@ -617,6 +680,7 @@ function buildProductOpenWeightRows(params) {
|
|
|
617
680
|
const unitPrice = productSku.unit_price ?? 0;
|
|
618
681
|
const netItem = `${netWeight} ${unit} NET @ ${currencySymbol}${unitPrice}/${unit}`;
|
|
619
682
|
rows.push({
|
|
683
|
+
...receiptTimeKey(product, 'net-weight'),
|
|
620
684
|
item: hasTare ? netItem : `${manualFlag}${netItem}`,
|
|
621
685
|
value: ''
|
|
622
686
|
});
|
|
@@ -672,7 +736,7 @@ function normalizeProductOptions(params) {
|
|
|
672
736
|
parentProduct
|
|
673
737
|
} = params;
|
|
674
738
|
const rawOptions = Array.isArray(params.options) ? params.options : Array.isArray(product.options) ? product.options : Array.isArray(product.product_sku?.option) ? product.product_sku.option : [];
|
|
675
|
-
return rawOptions.map(option => {
|
|
739
|
+
return rawOptions.map((option, sourceIndex) => {
|
|
676
740
|
const price = option.original_price ?? option.add_price ?? option.price;
|
|
677
741
|
const quantity = toNumber(option.num ?? option.quantity ?? 1, 1);
|
|
678
742
|
const value = option.value ?? option.option ?? option.item;
|
|
@@ -682,6 +746,8 @@ function normalizeProductOptions(params) {
|
|
|
682
746
|
locale
|
|
683
747
|
});
|
|
684
748
|
return {
|
|
749
|
+
...receiptKey(option, 'option'),
|
|
750
|
+
...receiptSourceIndex(option, sourceIndex),
|
|
685
751
|
name,
|
|
686
752
|
...(option.num !== undefined || option.quantity !== undefined ? {
|
|
687
753
|
num: quantity
|
|
@@ -705,7 +771,7 @@ function normalizeProductCombinations(params) {
|
|
|
705
771
|
parentProduct
|
|
706
772
|
} = params;
|
|
707
773
|
const bundles = Array.isArray(product.product_bundle) ? product.product_bundle : [];
|
|
708
|
-
return bundles.map(bundle => {
|
|
774
|
+
return bundles.map((bundle, sourceIndex) => {
|
|
709
775
|
const combinationsOptions = normalizeProductOptions({
|
|
710
776
|
product: {},
|
|
711
777
|
locale,
|
|
@@ -735,6 +801,8 @@ function normalizeProductCombinations(params) {
|
|
|
735
801
|
});
|
|
736
802
|
const shouldIncludeBasePrice = combinationsOptions.length > 0 || nestedCombinations.length > 0 || hasProductDiscount(bundle, extensionList);
|
|
737
803
|
return {
|
|
804
|
+
...receiptKey(bundle, 'combination'),
|
|
805
|
+
...receiptSourceIndex(bundle, sourceIndex),
|
|
738
806
|
product_title: baseTitle,
|
|
739
807
|
product_quantity: quantity,
|
|
740
808
|
price: formattedPrice,
|
|
@@ -762,7 +830,7 @@ function normalizeProductCombinations(params) {
|
|
|
762
830
|
});
|
|
763
831
|
}
|
|
764
832
|
function normalizeExistingCombinations(combinations, locale, currencySymbol) {
|
|
765
|
-
return combinations.map(combination => {
|
|
833
|
+
return combinations.map((combination, sourceIndex) => {
|
|
766
834
|
if (!combination || typeof combination !== 'object' || Array.isArray(combination)) {
|
|
767
835
|
return combination;
|
|
768
836
|
}
|
|
@@ -799,6 +867,8 @@ function normalizeExistingCombinations(combinations, locale, currencySymbol) {
|
|
|
799
867
|
const shouldIncludeBasePrice = normalizedOptions.length > 0 || nestedCombinations.length > 0 || hasProductDiscount(combination, extensionList);
|
|
800
868
|
return {
|
|
801
869
|
...snapshot,
|
|
870
|
+
...receiptKey(combination, 'combination'),
|
|
871
|
+
...receiptSourceIndex(combination, sourceIndex),
|
|
802
872
|
...(productTitle ? {
|
|
803
873
|
product_title: productTitle
|
|
804
874
|
} : {}),
|
|
@@ -953,7 +1023,7 @@ function resolveVariantItem(group, itemPositionId) {
|
|
|
953
1023
|
}
|
|
954
1024
|
function getProductTitleSource(source, locale) {
|
|
955
1025
|
if (!source || typeof source !== 'object') return '';
|
|
956
|
-
return resolveTitleValue(source.product_title, locale) || resolveTitleValue(source.title_i18n, locale) || resolveTitleValue(source.title, locale) || resolveTitleValue(source.name, locale);
|
|
1026
|
+
return resolveTitleValue(source.product_title, locale) || resolveTitleValue(source.title_i18n, locale) || resolveTitleValue(source.title, locale) || resolveTitleValue(source.name_i18n, locale) || resolveTitleValue(source.name, locale);
|
|
957
1027
|
}
|
|
958
1028
|
function getBundleProductTitleSource(source, locale) {
|
|
959
1029
|
if (!source || typeof source !== 'object') return '';
|
|
@@ -1072,6 +1142,7 @@ function buildFees(params) {
|
|
|
1072
1142
|
const value = surcharge.amount ?? surcharge.value ?? surcharge.total_amount;
|
|
1073
1143
|
if (!isNonZero(value)) continue;
|
|
1074
1144
|
fees.push({
|
|
1145
|
+
...receiptKey(surcharge, 'surcharge'),
|
|
1075
1146
|
item: getLocalizedValue(surcharge.name || surcharge.title || surcharge.item, locale),
|
|
1076
1147
|
value: formatMoney(value, currencySymbol)
|
|
1077
1148
|
});
|
|
@@ -1079,6 +1150,7 @@ function buildFees(params) {
|
|
|
1079
1150
|
const discountAmount = firstPresentValue(order.shop_discount, summary.discount_amount, order.discount_amount);
|
|
1080
1151
|
if (isNonZero(discountAmount)) {
|
|
1081
1152
|
fees.push({
|
|
1153
|
+
...receiptKey(order, 'order-discount'),
|
|
1082
1154
|
item: label(locale, 'orderDiscount'),
|
|
1083
1155
|
value: formatNegativeMoney(discountAmount, currencySymbol)
|
|
1084
1156
|
});
|
|
@@ -1095,6 +1167,7 @@ function buildFees(params) {
|
|
|
1095
1167
|
const payProcessingFee = financials.payProcessingFee;
|
|
1096
1168
|
if (isNonZero(payProcessingFee)) {
|
|
1097
1169
|
fees.push({
|
|
1170
|
+
...receiptKey(order, 'payment-processing-fee'),
|
|
1098
1171
|
item: label(locale, 'payProcessingFee'),
|
|
1099
1172
|
value: formatMoney(payProcessingFee, currencySymbol)
|
|
1100
1173
|
});
|
|
@@ -1174,17 +1247,22 @@ function calculateProductOriginalAmount(order) {
|
|
|
1174
1247
|
return total.plus(new _decimal.default(toMoneyNumber(originalPrice)).mul(quantity));
|
|
1175
1248
|
}, new _decimal.default(0));
|
|
1176
1249
|
}
|
|
1177
|
-
function buildCustomer(order, locale) {
|
|
1250
|
+
function buildCustomer(order, locale, visibility) {
|
|
1251
|
+
if (!visibility.show) return [];
|
|
1252
|
+
const fields = [visibility.name, visibility.phone, visibility.email];
|
|
1178
1253
|
return [{
|
|
1254
|
+
...receiptKey(order, 'customer.contactName'),
|
|
1179
1255
|
item: label(locale, 'contactName'),
|
|
1180
1256
|
value: normalizeCustomerDisplayValue(order.customer_name || order.customer?.name || order.customer?.display_name)
|
|
1181
1257
|
}, {
|
|
1258
|
+
...receiptKey(order, 'customer.contactMobile'),
|
|
1182
1259
|
item: label(locale, 'contactMobile'),
|
|
1183
1260
|
value: stringify(order.phone || order.customer?.phone)
|
|
1184
1261
|
}, {
|
|
1262
|
+
...receiptKey(order, 'customer.email'),
|
|
1185
1263
|
item: label(locale, 'email'),
|
|
1186
1264
|
value: stringify(order.email || order.customer?.email)
|
|
1187
|
-
}];
|
|
1265
|
+
}].filter((_row, index) => fields[index]);
|
|
1188
1266
|
}
|
|
1189
1267
|
function normalizeCustomerDisplayValue(value) {
|
|
1190
1268
|
const text = stringify(value).trim();
|
|
@@ -1192,19 +1270,23 @@ function normalizeCustomerDisplayValue(value) {
|
|
|
1192
1270
|
if (text.toLowerCase() === 'select a customer') return 'Walk-In';
|
|
1193
1271
|
return text;
|
|
1194
1272
|
}
|
|
1195
|
-
function buildDelivery(order, locale) {
|
|
1273
|
+
function buildDelivery(order, locale, visibility) {
|
|
1274
|
+
if (!visibility.show) return [];
|
|
1196
1275
|
const serviceType = stringify(order.metadata?.shop_service_data?.service_type).trim();
|
|
1197
1276
|
const serviceTypeLabelKey = resolveServiceTypeLabelKey(serviceType);
|
|
1198
1277
|
if (!serviceTypeLabelKey) return [];
|
|
1199
|
-
const items = [{
|
|
1278
|
+
const items = visibility.method ? [{
|
|
1279
|
+
...receiptKey(order, 'service-type'),
|
|
1200
1280
|
item: label(locale, serviceTypeLabelKey),
|
|
1201
1281
|
value: '',
|
|
1202
1282
|
size: 2
|
|
1203
|
-
}];
|
|
1283
|
+
}] : [];
|
|
1284
|
+
if (!visibility.fulfillmentTime) return items;
|
|
1204
1285
|
if (serviceType === 'pick_up') {
|
|
1205
1286
|
const pickupTime = formatPickupBookingStart(order.bookings, locale);
|
|
1206
1287
|
if (pickupTime) {
|
|
1207
1288
|
items.push({
|
|
1289
|
+
...receiptTimeKey(order, 'pickup-time'),
|
|
1208
1290
|
item: pickupTime,
|
|
1209
1291
|
value: '',
|
|
1210
1292
|
size: 2
|
|
@@ -1215,6 +1297,7 @@ function buildDelivery(order, locale) {
|
|
|
1215
1297
|
const handoverTime = firstPresentValue(order.handover_time, order.handover_at, order.pickup_time, order.pickup_at, order.scheduled_pickup_time, order.delivery_time, order.delivery_at, order.scheduled_delivery_time, order.fulfillment_time, order.fulfillment_at, order.metadata?.handover_time, order.metadata?.handover_at, order.metadata?.pickup_time, order.metadata?.pickup_at, order.metadata?.scheduled_pickup_time, order.metadata?.delivery_time, order.metadata?.delivery_at, order.metadata?.scheduled_delivery_time, order.metadata?.fulfillment_time, order.metadata?.fulfillment_at);
|
|
1216
1298
|
if (isPresentId(handoverTime)) {
|
|
1217
1299
|
items.push({
|
|
1300
|
+
...receiptKey(order, 'handover-time'),
|
|
1218
1301
|
item: label(locale, 'handoverTime'),
|
|
1219
1302
|
value: formatDateTime(handoverTime, locale)
|
|
1220
1303
|
});
|
|
@@ -1254,6 +1337,7 @@ function buildAppointment(order, locale) {
|
|
|
1254
1337
|
const tableName = order.table_name || order.metadata?.table_name || order.metadata?.table?.name || order.form_data?.table_name;
|
|
1255
1338
|
if (!tableName) return [];
|
|
1256
1339
|
return [{
|
|
1340
|
+
...receiptKey(order, 'table', 'text'),
|
|
1257
1341
|
item: label(locale, 'table'),
|
|
1258
1342
|
value: getLocalizedValue(tableName, locale)
|
|
1259
1343
|
}];
|
|
@@ -1289,18 +1373,22 @@ function buildAppointmentRows(params) {
|
|
|
1289
1373
|
const resourceText = formatBookingResources(resolveBookingResourcesForReceipt(booking, allResources, bookingCount), locale);
|
|
1290
1374
|
const holder = getLocalizedValue(booking.holder?.name ?? booking.metadata?.holder?.name, locale).trim();
|
|
1291
1375
|
return [{
|
|
1376
|
+
...receiptKey(booking, 'booking-id'),
|
|
1292
1377
|
item: label(locale, 'bookingId'),
|
|
1293
1378
|
value: bookingId,
|
|
1294
1379
|
...association
|
|
1295
1380
|
}, {
|
|
1381
|
+
...receiptKey(booking, 'booking-time', 'shared'),
|
|
1296
1382
|
item: label(locale, 'bookingDateTime'),
|
|
1297
1383
|
value: bookingTime,
|
|
1298
1384
|
...association
|
|
1299
1385
|
}, {
|
|
1386
|
+
...receiptKey(booking, 'booking-resource', 'text'),
|
|
1300
1387
|
item: label(locale, 'bookingResource'),
|
|
1301
1388
|
value: resourceText,
|
|
1302
1389
|
...association
|
|
1303
1390
|
}, {
|
|
1391
|
+
...receiptKey(booking, 'booking-holder', 'text'),
|
|
1304
1392
|
item: label(locale, 'bookingHolder'),
|
|
1305
1393
|
value: holder,
|
|
1306
1394
|
...association
|
|
@@ -1386,6 +1474,7 @@ function compareOptionalValues(left, right) {
|
|
|
1386
1474
|
}
|
|
1387
1475
|
function buildResources(order, locale) {
|
|
1388
1476
|
return normalizeArray(order.resources || order.resource_list).map(resource => ({
|
|
1477
|
+
...receiptKey(resource, 'resource', 'text'),
|
|
1389
1478
|
id: resource.id || resource.resource_id || '',
|
|
1390
1479
|
code: '',
|
|
1391
1480
|
title: getLocalizedValue(resource.title || resource.name, locale),
|
|
@@ -1431,12 +1520,14 @@ function buildRefundData(params) {
|
|
|
1431
1520
|
const methodName = paymentMethodName(payment, params.locale) || label(params.locale, 'refund');
|
|
1432
1521
|
const amount = firstPresentValue(refund.amount, refund.refund_amount, refund.total_amount) ?? 0;
|
|
1433
1522
|
const items = [{
|
|
1523
|
+
...receiptKey(refund, 'refund'),
|
|
1434
1524
|
item: methodName,
|
|
1435
1525
|
value: formatNegativeMoney(amount, params.currencySymbol)
|
|
1436
1526
|
}];
|
|
1437
1527
|
const occurredAt = firstPresentValue(refund.refund_time, refund.refunded_at, refund.created_at, refund.updated_at);
|
|
1438
1528
|
if (isPresentId(occurredAt)) {
|
|
1439
1529
|
items.push({
|
|
1530
|
+
...receiptTimeKey(refund, 'refund-time'),
|
|
1440
1531
|
item: formatDateTime(occurredAt, params.locale),
|
|
1441
1532
|
value: ''
|
|
1442
1533
|
});
|
|
@@ -1483,9 +1574,77 @@ function resolveRefundPayment(refund, payments) {
|
|
|
1483
1574
|
const matchedPayment = payments.find(payment => isSameId(firstPresentValue(payment.order_payment_id, payment.id), orderPaymentId));
|
|
1484
1575
|
return matchedPayment || refund;
|
|
1485
1576
|
}
|
|
1577
|
+
function getPaymentWalletAssetIdentity(payment) {
|
|
1578
|
+
const record = getFundRecord(payment);
|
|
1579
|
+
return {
|
|
1580
|
+
id: firstNormalizedWalletAssetId(record?.voucher_id, payment.voucher_id),
|
|
1581
|
+
codes: normalizeWalletAssetCodes(record?.code, record?.encoded)
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
function getProductWalletAssetTag(record) {
|
|
1585
|
+
// Rules normalizes product_discount_card to type=discount_card. That
|
|
1586
|
+
// ambiguous alias cannot establish the original asset tag for a whitelist.
|
|
1587
|
+
for (const tag of [record.tag, record.discount?.tag]) {
|
|
1588
|
+
if (typeof tag === 'string' && tag) return tag;
|
|
1589
|
+
}
|
|
1590
|
+
for (const type of [record.type, record.discount?.type]) {
|
|
1591
|
+
if (typeof type === 'string' && type !== 'discount_card' && PRODUCT_WALLET_DISCOUNT_TYPES.has(type)) return type;
|
|
1592
|
+
}
|
|
1593
|
+
return undefined;
|
|
1594
|
+
}
|
|
1595
|
+
function createWalletAssetFilter(order, passTypes) {
|
|
1596
|
+
if (passTypes === null) return () => true;
|
|
1597
|
+
const assets = [];
|
|
1598
|
+
const remember = (identity, tag) => {
|
|
1599
|
+
if (typeof tag === 'string' && tag && (identity.id || identity.codes.length)) assets.push({
|
|
1600
|
+
identity,
|
|
1601
|
+
tag
|
|
1602
|
+
});
|
|
1603
|
+
};
|
|
1604
|
+
for (const asset of [...normalizeArray(order.vouchers), ...normalizeArray(order.order_meta_list?.point_cards_snapshot), ...normalizeArray(order.order_meta_list?.virtual_currency_snapshot)]) {
|
|
1605
|
+
if (asset && typeof asset === 'object') remember(getVoucherAssetIdentity(asset), asset.tag);
|
|
1606
|
+
}
|
|
1607
|
+
// Some order snapshots retain the original selected assets at the root.
|
|
1608
|
+
// Only their explicit tag is authoritative; do not infer it from type.
|
|
1609
|
+
for (const record of normalizeArray(order.discount_list)) {
|
|
1610
|
+
if (!record || typeof record !== 'object') continue;
|
|
1611
|
+
remember({
|
|
1612
|
+
id: getProductWalletDiscountAssetId(record),
|
|
1613
|
+
codes: getProductWalletDiscountCodes(record)
|
|
1614
|
+
}, record.tag ?? record.discount?.tag);
|
|
1615
|
+
}
|
|
1616
|
+
const visit = product => {
|
|
1617
|
+
if (!product || typeof product !== 'object') return;
|
|
1618
|
+
for (const record of normalizeArray(product.discount_list)) {
|
|
1619
|
+
if (!record || typeof record !== 'object') continue;
|
|
1620
|
+
remember({
|
|
1621
|
+
id: getProductWalletDiscountAssetId(record),
|
|
1622
|
+
codes: getProductWalletDiscountCodes(record)
|
|
1623
|
+
}, getProductWalletAssetTag(record));
|
|
1624
|
+
}
|
|
1625
|
+
for (const key of ['combinations', 'product_bundle', 'bundle']) normalizeArray(product[key]).forEach(visit);
|
|
1626
|
+
};
|
|
1627
|
+
normalizeArray(order.products).forEach(product => {
|
|
1628
|
+
if (product && typeof product === 'object') visit(restoreReceiptDiscountHierarchy(product));
|
|
1629
|
+
});
|
|
1630
|
+
return (identity, tag, resolvePaymentSource = false) => {
|
|
1631
|
+
const directTag = typeof tag === 'string' && tag ? tag : undefined;
|
|
1632
|
+
if (directTag && !resolvePaymentSource) return passTypes.has(directTag);
|
|
1633
|
+
const exactMatches = identity.id ? assets.filter(asset => asset.identity.id === identity.id) : [];
|
|
1634
|
+
// A known asset ID is stronger than an unrelated code-only snapshot.
|
|
1635
|
+
const matches = exactMatches.length ? exactMatches : assets.filter(asset => isSameWalletAssetIdentity(asset.identity, identity));
|
|
1636
|
+
const tags = new Set(matches.map(asset => asset.tag));
|
|
1637
|
+
if (!tags.size) return !!directTag && passTypes.has(directTag);
|
|
1638
|
+
// A conflicting fund record is not reliable evidence for a payment's tag.
|
|
1639
|
+
// It must not claim the identity ahead of the original typed asset.
|
|
1640
|
+
if (tags.size !== 1 || directTag && !tags.has(directTag)) return false;
|
|
1641
|
+
return passTypes.has(matches[0].tag);
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1486
1644
|
function buildWallets(params) {
|
|
1487
|
-
const
|
|
1488
|
-
const
|
|
1645
|
+
const allowAsset = createWalletAssetFilter(params.order, params.passTypes);
|
|
1646
|
+
const virtualCurrencySnapshots = collectVirtualCurrencySnapshots(params.order, allowAsset);
|
|
1647
|
+
const displayedWalletPayments = normalizeArray(params.order.payments).filter(payment => isPrintablePayment(payment) && !!getFundRecord(payment) && allowAsset(getPaymentWalletAssetIdentity(payment), getFundRecord(payment)?.tag, true));
|
|
1489
1648
|
const paymentWallets = displayedWalletPayments.map(payment => {
|
|
1490
1649
|
const virtualCurrencySnapshot = findVirtualCurrencySnapshotForPayment(payment, virtualCurrencySnapshots.byId);
|
|
1491
1650
|
return buildPaymentItems({
|
|
@@ -1501,20 +1660,24 @@ function buildWallets(params) {
|
|
|
1501
1660
|
const displayedWalletAssetIdentities = collectDisplayedWalletAssetIdentities(displayedWalletPayments);
|
|
1502
1661
|
const voucherWallets = buildVoucherAssets({
|
|
1503
1662
|
...params,
|
|
1663
|
+
allowAsset,
|
|
1504
1664
|
displayedWalletAssetIdentities
|
|
1505
1665
|
});
|
|
1506
1666
|
const productDiscountWallets = buildProductDiscountAssets({
|
|
1507
1667
|
...params,
|
|
1668
|
+
allowAsset,
|
|
1508
1669
|
displayedWalletAssetIdentities
|
|
1509
1670
|
});
|
|
1510
1671
|
return [...paymentWallets, ...voucherWallets, ...productDiscountWallets, ...buildPointCardSnapshotAssets({
|
|
1511
1672
|
order: params.order,
|
|
1512
1673
|
locale: params.locale,
|
|
1674
|
+
allowAsset,
|
|
1513
1675
|
displayedWalletAssetIdentities
|
|
1514
1676
|
}), ...buildVirtualCurrencySnapshotAssets({
|
|
1515
1677
|
snapshots: virtualCurrencySnapshots.items,
|
|
1516
1678
|
order: params.order,
|
|
1517
1679
|
locale: params.locale,
|
|
1680
|
+
allowAsset,
|
|
1518
1681
|
displayedWalletAssetIdentities
|
|
1519
1682
|
})];
|
|
1520
1683
|
}
|
|
@@ -1543,7 +1706,7 @@ function collectDisplayedWalletAssetIdentities(payments) {
|
|
|
1543
1706
|
const PRODUCT_WALLET_DISCOUNT_TYPES = new Set(['good_pass', 'discount_card', 'product_discount_card', 'entitlement_pass']);
|
|
1544
1707
|
function buildProductDiscountAssets(params) {
|
|
1545
1708
|
const fallbackAssetTime = firstPresentValue(params.order.updated_at, params.order.created_at);
|
|
1546
|
-
return collectProductWalletDiscountAssets(params.order).flatMap(asset => {
|
|
1709
|
+
return collectProductWalletDiscountAssets(params.order, params.allowAsset).flatMap(asset => {
|
|
1547
1710
|
if (!claimWalletAssetIdentity(params.displayedWalletAssetIdentities, {
|
|
1548
1711
|
id: asset.id,
|
|
1549
1712
|
codes: asset.codes
|
|
@@ -1551,15 +1714,18 @@ function buildProductDiscountAssets(params) {
|
|
|
1551
1714
|
const name = getProductWalletDiscountName(asset, params.locale);
|
|
1552
1715
|
const assetTime = getProductWalletDiscountTime(asset) ?? fallbackAssetTime;
|
|
1553
1716
|
const timeRow = isPresentId(assetTime) ? {
|
|
1717
|
+
...receiptTimeKey(asset.records[0], 'asset-time'),
|
|
1554
1718
|
item: formatDateTime(assetTime, params.locale),
|
|
1555
1719
|
value: ''
|
|
1556
1720
|
} : null;
|
|
1557
1721
|
if (asset.type === 'entitlement_pass') {
|
|
1558
1722
|
const remaining = getProductEntitlementBalance(asset);
|
|
1559
1723
|
return [[{
|
|
1724
|
+
...receiptKey(asset.records[0], 'asset-name'),
|
|
1560
1725
|
item: name,
|
|
1561
1726
|
value: ''
|
|
1562
1727
|
}, ...(remaining ? [{
|
|
1728
|
+
...receiptKey(asset.records[0], 'entitlementRemaining'),
|
|
1563
1729
|
item: label(params.locale, 'entitlementRemaining'),
|
|
1564
1730
|
value: formatEntitlementUses(remaining, params.locale)
|
|
1565
1731
|
}] : []), ...(timeRow ? [timeRow] : [])]];
|
|
@@ -1567,30 +1733,33 @@ function buildProductDiscountAssets(params) {
|
|
|
1567
1733
|
const percent = getProductWalletDiscountPercent(asset);
|
|
1568
1734
|
if (percent) {
|
|
1569
1735
|
return [[{
|
|
1736
|
+
...receiptKey(asset.records[0], 'asset-discount'),
|
|
1570
1737
|
item: appendPercentToVoucherName(name, percent),
|
|
1571
1738
|
value: formatVoucherDiscount(percent, params.locale)
|
|
1572
1739
|
}, ...(timeRow ? [timeRow] : [])]];
|
|
1573
1740
|
}
|
|
1574
1741
|
const balance = getProductWalletMoneyBalance(asset);
|
|
1575
1742
|
return [[{
|
|
1743
|
+
...receiptKey(asset.records[0], 'asset-name'),
|
|
1576
1744
|
item: name,
|
|
1577
1745
|
value: ''
|
|
1578
1746
|
}, ...(balance ? [{
|
|
1747
|
+
...receiptKey(asset.records[0], 'balance'),
|
|
1579
1748
|
item: label(params.locale, 'balance'),
|
|
1580
1749
|
value: formatMoney(balance, params.currencySymbol)
|
|
1581
1750
|
}] : []), ...(timeRow ? [timeRow] : [])]];
|
|
1582
1751
|
});
|
|
1583
1752
|
}
|
|
1584
|
-
function collectProductWalletDiscountAssets(order) {
|
|
1753
|
+
function collectProductWalletDiscountAssets(order, allowAsset) {
|
|
1585
1754
|
const assets = [];
|
|
1586
1755
|
const assetsById = new Map();
|
|
1587
1756
|
normalizeArray(order.products).forEach(rawProduct => {
|
|
1588
1757
|
if (!rawProduct || typeof rawProduct !== 'object') return;
|
|
1589
|
-
visitProductWalletDiscounts(restoreReceiptDiscountHierarchy(rawProduct), assets, assetsById);
|
|
1758
|
+
visitProductWalletDiscounts(restoreReceiptDiscountHierarchy(rawProduct), assets, assetsById, allowAsset);
|
|
1590
1759
|
});
|
|
1591
1760
|
return assets;
|
|
1592
1761
|
}
|
|
1593
|
-
function visitProductWalletDiscounts(product, assets, assetsById) {
|
|
1762
|
+
function visitProductWalletDiscounts(product, assets, assetsById, allowAsset) {
|
|
1594
1763
|
normalizeArray(product.discount_list).forEach(record => {
|
|
1595
1764
|
if (!record || typeof record !== 'object' || Array.isArray(record)) return;
|
|
1596
1765
|
const type = getProductWalletDiscountType(record);
|
|
@@ -1598,6 +1767,10 @@ function visitProductWalletDiscounts(product, assets, assetsById) {
|
|
|
1598
1767
|
const id = getProductWalletDiscountAssetId(record);
|
|
1599
1768
|
if (!id) return;
|
|
1600
1769
|
const codes = getProductWalletDiscountCodes(record);
|
|
1770
|
+
if (allowAsset && !allowAsset({
|
|
1771
|
+
id,
|
|
1772
|
+
codes
|
|
1773
|
+
}, getProductWalletAssetTag(record))) return;
|
|
1601
1774
|
const existing = assetsById.get(id);
|
|
1602
1775
|
if (existing) {
|
|
1603
1776
|
existing.records.push(record);
|
|
@@ -1616,7 +1789,7 @@ function visitProductWalletDiscounts(product, assets, assetsById) {
|
|
|
1616
1789
|
for (const childKey of ['combinations', 'product_bundle', 'bundle']) {
|
|
1617
1790
|
normalizeArray(product[childKey]).forEach(child => {
|
|
1618
1791
|
if (!child || typeof child !== 'object' || Array.isArray(child)) return;
|
|
1619
|
-
visitProductWalletDiscounts(child, assets, assetsById);
|
|
1792
|
+
visitProductWalletDiscounts(child, assets, assetsById, allowAsset);
|
|
1620
1793
|
});
|
|
1621
1794
|
}
|
|
1622
1795
|
}
|
|
@@ -1732,23 +1905,27 @@ function buildPointCardSnapshotAssets(params) {
|
|
|
1732
1905
|
const pointCard = snapshot;
|
|
1733
1906
|
if (stringify(pointCard.tag).trim().toLowerCase() !== 'point_card') return [];
|
|
1734
1907
|
const assetId = normalizeWalletPassId(pointCard.id);
|
|
1908
|
+
if (!params.allowAsset(getVoucherAssetIdentity(pointCard), pointCard.tag)) return [];
|
|
1735
1909
|
if (!assetId || !claimWalletAssetIdentity(params.displayedWalletAssetIdentities, {
|
|
1736
1910
|
id: assetId,
|
|
1737
1911
|
codes: []
|
|
1738
1912
|
})) return [];
|
|
1739
1913
|
const rows = [{
|
|
1914
|
+
...receiptKey(pointCard, 'asset-name'),
|
|
1740
1915
|
item: appendMaskedCardCode(stringify(pointCard.product_name).trim() || label(params.locale, 'pointCard'), pointCard.code),
|
|
1741
1916
|
value: ''
|
|
1742
1917
|
}];
|
|
1743
1918
|
const remainingPoints = getPointCardSnapshotRemainingPoints(pointCard);
|
|
1744
1919
|
if (remainingPoints) {
|
|
1745
1920
|
rows.push({
|
|
1921
|
+
...receiptKey(pointCard, 'remainingPoints'),
|
|
1746
1922
|
item: label(params.locale, 'remainingPoints'),
|
|
1747
1923
|
value: trimDecimal(remainingPoints)
|
|
1748
1924
|
});
|
|
1749
1925
|
}
|
|
1750
1926
|
if (isPresentId(snapshotTime)) {
|
|
1751
1927
|
rows.push({
|
|
1928
|
+
...receiptTimeKey(pointCard, 'asset-time'),
|
|
1752
1929
|
item: formatDateTime(snapshotTime, params.locale),
|
|
1753
1930
|
value: ''
|
|
1754
1931
|
});
|
|
@@ -1756,7 +1933,7 @@ function buildPointCardSnapshotAssets(params) {
|
|
|
1756
1933
|
return [rows];
|
|
1757
1934
|
});
|
|
1758
1935
|
}
|
|
1759
|
-
function collectVirtualCurrencySnapshots(order) {
|
|
1936
|
+
function collectVirtualCurrencySnapshots(order, allowAsset) {
|
|
1760
1937
|
const items = [];
|
|
1761
1938
|
const byId = new Map();
|
|
1762
1939
|
const snapshots = order.order_meta_list?.virtual_currency_snapshot;
|
|
@@ -1768,6 +1945,7 @@ function collectVirtualCurrencySnapshots(order) {
|
|
|
1768
1945
|
if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) return;
|
|
1769
1946
|
const virtualCurrency = snapshot;
|
|
1770
1947
|
if (stringify(virtualCurrency.tag).trim().toLowerCase() !== 'virtual_currency') return;
|
|
1948
|
+
if (!allowAsset(getVoucherAssetIdentity(virtualCurrency), virtualCurrency.tag)) return;
|
|
1771
1949
|
const id = normalizeWalletPassId(virtualCurrency.id);
|
|
1772
1950
|
if (!id || byId.has(id)) return;
|
|
1773
1951
|
byId.set(id, virtualCurrency);
|
|
@@ -1792,23 +1970,27 @@ function buildVirtualCurrencySnapshotAssets(params) {
|
|
|
1792
1970
|
const snapshotTime = firstPresentValue(params.order.updated_at, params.order.created_at);
|
|
1793
1971
|
return params.snapshots.flatMap(virtualCurrency => {
|
|
1794
1972
|
const assetId = normalizeWalletPassId(virtualCurrency.id);
|
|
1973
|
+
if (!params.allowAsset(getVoucherAssetIdentity(virtualCurrency), virtualCurrency.tag)) return [];
|
|
1795
1974
|
if (!assetId || !claimWalletAssetIdentity(params.displayedWalletAssetIdentities, {
|
|
1796
1975
|
id: assetId,
|
|
1797
1976
|
codes: []
|
|
1798
1977
|
})) return [];
|
|
1799
1978
|
const rows = [{
|
|
1979
|
+
...receiptKey(virtualCurrency, 'asset-name'),
|
|
1800
1980
|
item: stringify(virtualCurrency.product_name).trim(),
|
|
1801
1981
|
value: ''
|
|
1802
1982
|
}];
|
|
1803
1983
|
const balance = getVirtualCurrencySnapshotBalance(virtualCurrency);
|
|
1804
1984
|
if (balance) {
|
|
1805
1985
|
rows.push({
|
|
1986
|
+
...receiptKey(virtualCurrency, 'balance'),
|
|
1806
1987
|
item: label(params.locale, 'balance'),
|
|
1807
1988
|
value: formatVirtualCurrencyBalance(balance, getVirtualCurrencySnapshotUnit(virtualCurrency, params.locale))
|
|
1808
1989
|
});
|
|
1809
1990
|
}
|
|
1810
1991
|
if (isPresentId(snapshotTime)) {
|
|
1811
1992
|
rows.push({
|
|
1993
|
+
...receiptTimeKey(virtualCurrency, 'asset-time'),
|
|
1812
1994
|
item: formatDateTime(snapshotTime, params.locale),
|
|
1813
1995
|
value: ''
|
|
1814
1996
|
});
|
|
@@ -1899,19 +2081,23 @@ function buildVoucherAssets(params) {
|
|
|
1899
2081
|
const fallbackAssetTime = firstPresentValue(params.order.updated_at, params.order.created_at);
|
|
1900
2082
|
return normalizeArray(params.order.vouchers).flatMap(voucher => {
|
|
1901
2083
|
if (!voucher || typeof voucher !== 'object' || Array.isArray(voucher)) return [];
|
|
2084
|
+
if (!params.allowAsset(getVoucherAssetIdentity(voucher), voucher.tag)) return [];
|
|
1902
2085
|
if (!claimWalletAssetIdentity(params.displayedWalletAssetIdentities, getVoucherAssetIdentity(voucher))) return [];
|
|
1903
2086
|
const name = getVoucherAssetName(voucher, params.locale);
|
|
1904
2087
|
const assetTime = firstPresentValue(voucher.updated_at, voucher.created_at, voucher.collection_time, fallbackAssetTime);
|
|
1905
2088
|
const timeRow = isPresentId(assetTime) ? {
|
|
2089
|
+
...receiptTimeKey(voucher, 'asset-time'),
|
|
1906
2090
|
item: formatDateTime(assetTime, params.locale),
|
|
1907
2091
|
value: ''
|
|
1908
2092
|
} : null;
|
|
1909
2093
|
if (isEntitlementVoucher(voucher)) {
|
|
1910
2094
|
const remaining = getEntitlementBalance(voucher.metadata?.balance, voucher.balance);
|
|
1911
2095
|
return [[{
|
|
2096
|
+
...receiptKey(voucher, 'asset-name'),
|
|
1912
2097
|
item: name,
|
|
1913
2098
|
value: ''
|
|
1914
2099
|
}, ...(remaining ? [{
|
|
2100
|
+
...receiptKey(voucher, 'entitlementRemaining'),
|
|
1915
2101
|
item: label(params.locale, 'entitlementRemaining'),
|
|
1916
2102
|
value: formatEntitlementUses(remaining, params.locale)
|
|
1917
2103
|
}] : []), ...(timeRow ? [timeRow] : [])]];
|
|
@@ -1919,9 +2105,11 @@ function buildVoucherAssets(params) {
|
|
|
1919
2105
|
if (isTicketVoucher(voucher)) {
|
|
1920
2106
|
const validity = getVoucherValidity(voucher, params.locale);
|
|
1921
2107
|
return [[{
|
|
2108
|
+
...receiptKey(voucher, 'asset-name'),
|
|
1922
2109
|
item: name,
|
|
1923
2110
|
value: ''
|
|
1924
2111
|
}, ...(validity ? [{
|
|
2112
|
+
...receiptKey(voucher, 'validity'),
|
|
1925
2113
|
item: label(params.locale, 'validity'),
|
|
1926
2114
|
value: validity
|
|
1927
2115
|
}] : [])]];
|
|
@@ -1929,15 +2117,18 @@ function buildVoucherAssets(params) {
|
|
|
1929
2117
|
const percent = getVoucherDiscountPercent(voucher);
|
|
1930
2118
|
if (percent) {
|
|
1931
2119
|
return [[{
|
|
2120
|
+
...receiptKey(voucher, 'asset-discount'),
|
|
1932
2121
|
item: appendPercentToVoucherName(name, percent),
|
|
1933
2122
|
value: formatVoucherDiscount(percent, params.locale)
|
|
1934
2123
|
}, ...(timeRow ? [timeRow] : [])]];
|
|
1935
2124
|
}
|
|
1936
2125
|
const balance = getVoucherBalance(voucher);
|
|
1937
2126
|
return [[{
|
|
2127
|
+
...receiptKey(voucher, 'asset-name'),
|
|
1938
2128
|
item: name,
|
|
1939
2129
|
value: ''
|
|
1940
2130
|
}, {
|
|
2131
|
+
...receiptKey(voucher, 'balance'),
|
|
1941
2132
|
item: label(params.locale, 'balance'),
|
|
1942
2133
|
value: formatMoney(balance, params.currencySymbol)
|
|
1943
2134
|
}, ...(timeRow ? [timeRow] : [])]];
|
|
@@ -2071,6 +2262,7 @@ function buildPaymentItems(params) {
|
|
|
2071
2262
|
} = params;
|
|
2072
2263
|
const serviceFee = getPaymentServiceFee(payment);
|
|
2073
2264
|
const items = [{
|
|
2265
|
+
...receiptKey(payment, 'payment'),
|
|
2074
2266
|
item: paymentMethodName(payment, locale),
|
|
2075
2267
|
value: includePaymentAmount ? formatMoney(resolveReceiptPaymentAmount(payment, serviceFee), currencySymbol) : ''
|
|
2076
2268
|
}];
|
|
@@ -2081,6 +2273,7 @@ function buildPaymentItems(params) {
|
|
|
2081
2273
|
}));
|
|
2082
2274
|
if (serviceFee.gt(0)) {
|
|
2083
2275
|
items.push({
|
|
2276
|
+
...receiptKey(payment, 'surchargeIncluded'),
|
|
2084
2277
|
item: label(locale, 'surchargeIncluded'),
|
|
2085
2278
|
value: formatMoney(serviceFee, currencySymbol)
|
|
2086
2279
|
});
|
|
@@ -2100,16 +2293,21 @@ function buildPaymentItems(params) {
|
|
|
2100
2293
|
const remainingAmount = payment.remaining_amount ?? payment.balance ?? payment.metadata?.remaining_amount;
|
|
2101
2294
|
if (remainingAmount !== undefined && remainingAmount !== null) {
|
|
2102
2295
|
items.push({
|
|
2296
|
+
...receiptKey(payment, 'remainingAmount'),
|
|
2103
2297
|
item: label(locale, 'remainingAmount'),
|
|
2104
2298
|
value: formatMoney(remainingAmount, currencySymbol)
|
|
2105
2299
|
});
|
|
2106
2300
|
}
|
|
2107
2301
|
}
|
|
2108
2302
|
items.push({
|
|
2303
|
+
...receiptTimeKey(payment, 'payment-time'),
|
|
2109
2304
|
item: formatDateTime(payment.paid_at || payment.created_at || payment.updated_at || new Date(), locale),
|
|
2110
2305
|
value: ''
|
|
2111
2306
|
});
|
|
2112
|
-
return items
|
|
2307
|
+
return items.map(item => item.receipt_key ? {
|
|
2308
|
+
...item,
|
|
2309
|
+
receipt_key: `${item.receipt_key}/${includeFundRecordBalance ? 'wallet' : 'history'}`
|
|
2310
|
+
} : item);
|
|
2113
2311
|
}
|
|
2114
2312
|
function getPaymentServiceFee(payment) {
|
|
2115
2313
|
return new _decimal.default(toMoneyNumber(payment.service_fee));
|
|
@@ -2130,9 +2328,11 @@ function buildCashChangePaymentItems(params) {
|
|
|
2130
2328
|
} = params;
|
|
2131
2329
|
if (!shouldDisplayCashChange(payment)) return [];
|
|
2132
2330
|
return [{
|
|
2331
|
+
...receiptKey(payment, 'cashReceived'),
|
|
2133
2332
|
item: label(locale, 'cashReceived'),
|
|
2134
2333
|
value: formatMoney(payment.metadata.actual_paid_amount, currencySymbol)
|
|
2135
2334
|
}, {
|
|
2335
|
+
...receiptKey(payment, 'changeDue'),
|
|
2136
2336
|
item: label(locale, 'changeDue'),
|
|
2137
2337
|
value: formatMoney(payment.metadata.change_given_amount, currencySymbol)
|
|
2138
2338
|
}];
|
|
@@ -2169,12 +2369,14 @@ function buildFundRecordPaymentItems(params) {
|
|
|
2169
2369
|
const usedPoints = new _decimal.default(toMoneyNumber(usingBeforeValue)).minus(toMoneyNumber(usingAfterValue));
|
|
2170
2370
|
if (includeUsage) {
|
|
2171
2371
|
items.push({
|
|
2372
|
+
...receiptKey(payment, 'redeemPoints'),
|
|
2172
2373
|
item: label(locale, 'redeemPoints'),
|
|
2173
2374
|
value: trimDecimal(usedPoints)
|
|
2174
2375
|
});
|
|
2175
2376
|
}
|
|
2176
2377
|
if (includeBalance) {
|
|
2177
2378
|
items.push({
|
|
2379
|
+
...receiptKey(payment, 'remainingPoints'),
|
|
2178
2380
|
item: label(locale, 'remainingPoints'),
|
|
2179
2381
|
value: trimDecimal(new _decimal.default(toMoneyNumber(usingAfterValue)))
|
|
2180
2382
|
});
|
|
@@ -2185,12 +2387,14 @@ function buildFundRecordPaymentItems(params) {
|
|
|
2185
2387
|
if (virtualCurrencyUnit !== undefined) {
|
|
2186
2388
|
if (!isNumericAmount(usingAfterValue)) return items;
|
|
2187
2389
|
items.push({
|
|
2390
|
+
...receiptKey(payment, 'balance'),
|
|
2188
2391
|
item: label(locale, 'balance'),
|
|
2189
2392
|
value: formatVirtualCurrencyBalance(new _decimal.default(usingAfterValue), virtualCurrencyUnit)
|
|
2190
2393
|
});
|
|
2191
2394
|
return items;
|
|
2192
2395
|
}
|
|
2193
2396
|
items.push({
|
|
2397
|
+
...receiptKey(payment, 'balance'),
|
|
2194
2398
|
item: label(locale, 'balance'),
|
|
2195
2399
|
value: formatMoney(usingAfterValue, currencySymbol)
|
|
2196
2400
|
});
|