@pisell/pisellos 2.2.302 → 2.2.304
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/itemRule/adapter.d.ts +4 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +135 -35
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +25 -1
- package/dist/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/dist/model/strategy/adapter/itemRule/type.js +19 -1
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +10 -7
- package/dist/modules/Discount/index.d.ts +2 -0
- package/dist/modules/Discount/index.js +41 -5
- package/dist/modules/Discount/types.d.ts +21 -0
- package/dist/modules/OpenData/index.d.ts +15 -2
- package/dist/modules/OpenData/index.js +307 -19
- package/dist/modules/OpenData/types.d.ts +55 -0
- package/dist/modules/OpenData/types.js +7 -1
- package/dist/modules/OpenData/utils.d.ts +21 -1
- package/dist/modules/OpenData/utils.js +138 -0
- package/dist/modules/Order/index.d.ts +50 -7
- package/dist/modules/Order/index.js +1690 -815
- package/dist/modules/Order/salesNotes.d.ts +31 -0
- package/dist/modules/Order/salesNotes.js +492 -0
- package/dist/modules/Order/types.d.ts +117 -10
- package/dist/modules/Order/types.js +6 -1
- 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 +5 -1
- package/dist/modules/Order/utils.js +138 -33
- package/dist/modules/Payment/cashRecommendationAlgorithm.d.ts +4 -5
- package/dist/modules/Payment/cashRecommendationAlgorithm.js +17 -367
- package/dist/modules/Payment/walletpass.js +20 -21
- package/dist/modules/Product/types.d.ts +23 -0
- package/dist/modules/ProductList/index.d.ts +2 -1
- package/dist/modules/ProductList/index.js +100 -20
- package/dist/modules/ProductList/types.d.ts +10 -0
- package/dist/modules/Rules/index.d.ts +5 -0
- package/dist/modules/Rules/index.js +30 -14
- 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/plugins/request.d.ts +2 -1
- package/dist/plugins/request.js +4 -2
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.js +1774 -1285
- package/dist/server/modules/order/types.d.ts +50 -0
- package/dist/server/modules/order/types.js +2 -0
- package/dist/server/utils/small-ticket.d.ts +4 -1
- package/dist/server/utils/small-ticket.js +461 -96
- package/dist/solution/BaseSales/index.d.ts +24 -3
- package/dist/solution/BaseSales/index.js +1484 -873
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +2 -0
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +1 -1
- 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 +1 -1
- package/dist/solution/BookingTicket/index.d.ts +22 -5
- package/dist/solution/BookingTicket/index.js +558 -443
- package/dist/solution/BookingTicket/utils/addProductDecision.js +2 -1
- package/dist/solution/BookingTicket/utils/orderCustomer.js +3 -2
- package/dist/solution/RegisterAndLogin/config.d.ts +9 -3
- package/dist/solution/RegisterAndLogin/config.js +95 -40
- package/dist/solution/RegisterAndLogin/index.js +4 -1
- package/dist/solution/Sales/index.d.ts +16 -1
- package/dist/solution/Sales/index.js +338 -63
- package/dist/solution/Sales/types.d.ts +10 -0
- package/dist/solution/ScanOrder/index.d.ts +1 -0
- package/dist/solution/ScanOrder/index.js +31 -27
- package/dist/solution/ScanOrder/utils.d.ts +1 -0
- package/dist/solution/ScanOrder/utils.js +2 -0
- package/dist/solution/UnifiedBookingSales/index.d.ts +20 -6
- package/dist/solution/UnifiedBookingSales/index.js +874 -527
- package/dist/solution/UnifiedBookingSales/types.d.ts +21 -2
- package/dist/solution/VenueBooking/index.d.ts +1 -0
- package/dist/solution/VenueBooking/index.js +8 -4
- 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/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +73 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +23 -1
- package/lib/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/lib/model/strategy/adapter/itemRule/type.js +19 -1
- package/lib/model/strategy/adapter/promotion/index.js +1 -46
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +4 -0
- package/lib/modules/Discount/index.d.ts +2 -0
- package/lib/modules/Discount/index.js +34 -2
- package/lib/modules/Discount/types.d.ts +21 -0
- package/lib/modules/OpenData/index.d.ts +15 -2
- package/lib/modules/OpenData/index.js +230 -3
- package/lib/modules/OpenData/types.d.ts +55 -0
- package/lib/modules/OpenData/types.js +9 -1
- package/lib/modules/OpenData/utils.d.ts +21 -1
- package/lib/modules/OpenData/utils.js +126 -0
- package/lib/modules/Order/index.d.ts +50 -7
- package/lib/modules/Order/index.js +704 -64
- package/lib/modules/Order/salesNotes.d.ts +31 -0
- package/lib/modules/Order/salesNotes.js +382 -0
- package/lib/modules/Order/types.d.ts +117 -10
- package/lib/modules/Order/types.js +5 -1
- 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 +5 -1
- package/lib/modules/Order/utils.js +127 -21
- package/lib/modules/Payment/cashRecommendationAlgorithm.d.ts +4 -5
- package/lib/modules/Payment/cashRecommendationAlgorithm.js +9 -354
- package/lib/modules/Payment/walletpass.js +14 -11
- package/lib/modules/Product/types.d.ts +23 -0
- package/lib/modules/ProductList/index.d.ts +2 -1
- package/lib/modules/ProductList/index.js +47 -2
- package/lib/modules/ProductList/types.d.ts +10 -0
- package/lib/modules/Rules/index.d.ts +5 -0
- package/lib/modules/Rules/index.js +22 -12
- 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/plugins/request.d.ts +2 -1
- package/lib/plugins/request.js +3 -2
- package/lib/server/index.d.ts +21 -0
- package/lib/server/index.js +492 -108
- package/lib/server/modules/order/types.d.ts +50 -0
- package/lib/server/modules/order/types.js +1 -0
- package/lib/server/utils/small-ticket.d.ts +4 -1
- package/lib/server/utils/small-ticket.js +427 -72
- package/lib/solution/BaseSales/index.d.ts +24 -3
- package/lib/solution/BaseSales/index.js +433 -30
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +2 -0
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +1 -1
- 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 +1 -1
- package/lib/solution/BookingTicket/index.d.ts +22 -5
- package/lib/solution/BookingTicket/index.js +60 -15
- package/lib/solution/BookingTicket/utils/addProductDecision.js +1 -0
- package/lib/solution/BookingTicket/utils/orderCustomer.js +2 -1
- package/lib/solution/RegisterAndLogin/config.d.ts +9 -3
- package/lib/solution/RegisterAndLogin/config.js +49 -8
- package/lib/solution/RegisterAndLogin/index.js +4 -1
- package/lib/solution/Sales/index.d.ts +16 -1
- package/lib/solution/Sales/index.js +168 -1
- package/lib/solution/Sales/types.d.ts +10 -0
- package/lib/solution/ScanOrder/index.d.ts +1 -0
- package/lib/solution/ScanOrder/index.js +5 -1
- package/lib/solution/ScanOrder/utils.d.ts +1 -0
- package/lib/solution/ScanOrder/utils.js +1 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +20 -6
- package/lib/solution/UnifiedBookingSales/index.js +169 -16
- package/lib/solution/UnifiedBookingSales/types.d.ts +21 -2
- package/lib/solution/VenueBooking/index.d.ts +1 -0
- package/lib/solution/VenueBooking/index.js +5 -1
- package/package.json +1 -1
|
@@ -27,6 +27,7 @@ const LABELS = {
|
|
|
27
27
|
eftpos: 'Eftpos',
|
|
28
28
|
wallet: 'Wallet',
|
|
29
29
|
giftCard: 'Gift card',
|
|
30
|
+
balance: 'Balance',
|
|
30
31
|
remainingAmount: 'Remaining amount',
|
|
31
32
|
redeemPoints: 'Redeem points',
|
|
32
33
|
remainingPoints: 'Remaining points',
|
|
@@ -37,7 +38,9 @@ const LABELS = {
|
|
|
37
38
|
surchargeIncluded: 'Surcharge(Included)',
|
|
38
39
|
rounding: 'Rounding',
|
|
39
40
|
gross: 'Gross',
|
|
40
|
-
tare: 'Tare'
|
|
41
|
+
tare: 'Tare',
|
|
42
|
+
handoverTime: 'Handover time',
|
|
43
|
+
refund: 'Refund'
|
|
41
44
|
},
|
|
42
45
|
zh_CN: {
|
|
43
46
|
contactName: '联系人姓名',
|
|
@@ -56,6 +59,7 @@ const LABELS = {
|
|
|
56
59
|
eftpos: '刷卡支付',
|
|
57
60
|
wallet: '钱包支付',
|
|
58
61
|
giftCard: '礼品卡',
|
|
62
|
+
balance: '余额',
|
|
59
63
|
remainingAmount: '剩余金额',
|
|
60
64
|
redeemPoints: '本次使用积分',
|
|
61
65
|
remainingPoints: '剩余积分',
|
|
@@ -66,7 +70,9 @@ const LABELS = {
|
|
|
66
70
|
surchargeIncluded: '手续费(已含)',
|
|
67
71
|
rounding: '抹零',
|
|
68
72
|
gross: '重量',
|
|
69
|
-
tare: '去皮'
|
|
73
|
+
tare: '去皮',
|
|
74
|
+
handoverTime: '交付时间',
|
|
75
|
+
refund: '退款'
|
|
70
76
|
},
|
|
71
77
|
zh_HK: {
|
|
72
78
|
contactName: '聯絡人姓名',
|
|
@@ -85,6 +91,7 @@ const LABELS = {
|
|
|
85
91
|
eftpos: '刷卡支付',
|
|
86
92
|
wallet: '錢包支付',
|
|
87
93
|
giftCard: '禮品卡',
|
|
94
|
+
balance: '餘額',
|
|
88
95
|
remainingAmount: '剩餘金額',
|
|
89
96
|
redeemPoints: '本次使用積分',
|
|
90
97
|
remainingPoints: '剩餘積分',
|
|
@@ -95,13 +102,69 @@ const LABELS = {
|
|
|
95
102
|
surchargeIncluded: '手續費(已含)',
|
|
96
103
|
rounding: '抹零',
|
|
97
104
|
gross: '重量',
|
|
98
|
-
tare: '去皮'
|
|
105
|
+
tare: '去皮',
|
|
106
|
+
handoverTime: '交付時間',
|
|
107
|
+
refund: '退款'
|
|
99
108
|
},
|
|
100
109
|
ja: {
|
|
110
|
+
contactName: '連絡先名',
|
|
111
|
+
contactMobile: '連絡先電話',
|
|
112
|
+
email: 'メール',
|
|
113
|
+
dineIn: '店内飲食',
|
|
114
|
+
takeAway: 'テイクアウト',
|
|
115
|
+
delivery: '配達',
|
|
116
|
+
pickUp: '受け取り',
|
|
117
|
+
shopService: '店内飲食',
|
|
118
|
+
pickUpTime: '受取時間',
|
|
119
|
+
asap: 'できるだけ早く',
|
|
120
|
+
cash: '現金',
|
|
121
|
+
eftpos: 'カード',
|
|
122
|
+
wallet: 'ウォレット',
|
|
123
|
+
giftCard: 'ギフトカード',
|
|
124
|
+
balance: '残高',
|
|
125
|
+
remainingAmount: '残高',
|
|
126
|
+
redeemPoints: '利用ポイント',
|
|
127
|
+
remainingPoints: '残りポイント',
|
|
128
|
+
table: 'テーブル',
|
|
129
|
+
orderDiscount: '注文割引',
|
|
130
|
+
manualDiscount: '手動割引',
|
|
131
|
+
payProcessingFee: '決済手数料',
|
|
132
|
+
rounding: '端数調整',
|
|
133
|
+
gross: '総重量',
|
|
134
|
+
tare: '風袋',
|
|
135
|
+
handoverTime: '受け渡し時間',
|
|
136
|
+
refund: '返金',
|
|
101
137
|
cashReceived: 'お預かり',
|
|
102
138
|
changeDue: 'お釣り'
|
|
103
139
|
},
|
|
104
140
|
pt: {
|
|
141
|
+
contactName: 'Nome de contato',
|
|
142
|
+
contactMobile: 'Celular de contato',
|
|
143
|
+
email: 'e-mail',
|
|
144
|
+
dineIn: 'Consumo no local',
|
|
145
|
+
takeAway: 'Para levar',
|
|
146
|
+
delivery: 'Entrega',
|
|
147
|
+
pickUp: 'Recolha',
|
|
148
|
+
shopService: 'Consumo no local',
|
|
149
|
+
pickUpTime: 'Hora de recolha',
|
|
150
|
+
asap: 'Assim que possível',
|
|
151
|
+
cash: 'Dinheiro',
|
|
152
|
+
eftpos: 'Cartão',
|
|
153
|
+
wallet: 'Carteira',
|
|
154
|
+
giftCard: 'Cartão-presente',
|
|
155
|
+
balance: 'Saldo',
|
|
156
|
+
remainingAmount: 'Saldo restante',
|
|
157
|
+
redeemPoints: 'Pontos utilizados',
|
|
158
|
+
remainingPoints: 'Pontos restantes',
|
|
159
|
+
table: 'Mesa',
|
|
160
|
+
orderDiscount: 'Desconto do pedido',
|
|
161
|
+
manualDiscount: 'Desconto manual',
|
|
162
|
+
payProcessingFee: 'Taxa de processamento',
|
|
163
|
+
rounding: 'Arredondamento',
|
|
164
|
+
gross: 'Peso bruto',
|
|
165
|
+
tare: 'Tara',
|
|
166
|
+
handoverTime: 'Hora de entrega',
|
|
167
|
+
refund: 'Reembolso',
|
|
105
168
|
cashReceived: 'Dinheiro recebido',
|
|
106
169
|
changeDue: 'Troco'
|
|
107
170
|
}
|
|
@@ -134,11 +197,15 @@ function buildLocaleData(params) {
|
|
|
134
197
|
const products = buildProducts(order, locale, productMap);
|
|
135
198
|
const summary = getSummary(order);
|
|
136
199
|
const currencySymbol = getCurrencySymbol(order, shopInfo);
|
|
200
|
+
const financials = resolveReceiptFinancials(order, summary);
|
|
201
|
+
const delivery = buildDelivery(order, locale);
|
|
137
202
|
return {
|
|
138
203
|
base_data: buildBaseData({
|
|
139
204
|
order,
|
|
140
205
|
shopInfo,
|
|
141
|
-
locale
|
|
206
|
+
locale,
|
|
207
|
+
currencySymbol,
|
|
208
|
+
financials
|
|
142
209
|
}),
|
|
143
210
|
products,
|
|
144
211
|
fees: buildFees({
|
|
@@ -147,11 +214,14 @@ function buildLocaleData(params) {
|
|
|
147
214
|
locale,
|
|
148
215
|
products,
|
|
149
216
|
summary,
|
|
150
|
-
currencySymbol
|
|
217
|
+
currencySymbol,
|
|
218
|
+
financials
|
|
151
219
|
}),
|
|
152
220
|
customer: buildCustomer(order, locale),
|
|
153
221
|
appointment: buildAppointment(order, locale),
|
|
154
|
-
|
|
222
|
+
...(delivery.length ? {
|
|
223
|
+
delivery
|
|
224
|
+
} : {}),
|
|
155
225
|
resources: buildResources(order, locale),
|
|
156
226
|
payment_data: buildPaymentData({
|
|
157
227
|
order,
|
|
@@ -165,7 +235,11 @@ function buildLocaleData(params) {
|
|
|
165
235
|
}),
|
|
166
236
|
tickets: Array.isArray(order.tickets) ? order.tickets : [],
|
|
167
237
|
source_shop: [],
|
|
168
|
-
refund_data:
|
|
238
|
+
refund_data: buildRefundData({
|
|
239
|
+
order,
|
|
240
|
+
locale,
|
|
241
|
+
currencySymbol
|
|
242
|
+
}),
|
|
169
243
|
expend_data: []
|
|
170
244
|
};
|
|
171
245
|
}
|
|
@@ -173,7 +247,9 @@ function buildBaseData(params) {
|
|
|
173
247
|
const {
|
|
174
248
|
order,
|
|
175
249
|
shopInfo,
|
|
176
|
-
locale
|
|
250
|
+
locale,
|
|
251
|
+
currencySymbol,
|
|
252
|
+
financials
|
|
177
253
|
} = params;
|
|
178
254
|
const orderNumber = stringify(order.buzzer || order.shop_full_order_number);
|
|
179
255
|
return {
|
|
@@ -184,7 +260,13 @@ function buildBaseData(params) {
|
|
|
184
260
|
shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
|
|
185
261
|
shop_phone: stringify(shopInfo.phone || order.shop_phone),
|
|
186
262
|
shop_address: stringify(shopInfo.receipt_address || shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
|
|
187
|
-
original_payment_status:
|
|
263
|
+
original_payment_status: financials.paymentStatus,
|
|
264
|
+
payment_status: financials.paymentStatus,
|
|
265
|
+
total_amount: formatMoney(financials.totalAmount, currencySymbol),
|
|
266
|
+
has_pay: formatMoney(financials.netPaymentApplied, currencySymbol),
|
|
267
|
+
...(isPresentId(financials.amountGap) ? {
|
|
268
|
+
amount_gap: formatMoney(financials.amountGap, currencySymbol)
|
|
269
|
+
} : {}),
|
|
188
270
|
is_repeat: 0,
|
|
189
271
|
buzzer: stringify(order.buzzer || order.pickup_number || order.metadata?.buzzer),
|
|
190
272
|
order_no: orderNumber,
|
|
@@ -234,11 +316,16 @@ function buildProducts(order, locale, productMap) {
|
|
|
234
316
|
quantity,
|
|
235
317
|
originalPrice
|
|
236
318
|
});
|
|
319
|
+
const productNote = resolveProductNote(product, locale);
|
|
320
|
+
const basePrice = resolveProductBasePrice(product);
|
|
237
321
|
return {
|
|
238
322
|
product_title: productTitle,
|
|
239
323
|
product_quantity: quantity,
|
|
240
324
|
selling_price: formatMoney(sellingPrice, currencySymbol),
|
|
241
325
|
original_price: formatMoney(originalPrice, currencySymbol),
|
|
326
|
+
...(isPresentId(basePrice) ? {
|
|
327
|
+
base_price: formatMoney(basePrice, currencySymbol)
|
|
328
|
+
} : {}),
|
|
242
329
|
total_original_price: formatMoney(new _decimal.default(toMoneyNumber(originalPrice)).mul(quantity), currencySymbol),
|
|
243
330
|
extension_list: extensionList,
|
|
244
331
|
...(isPresentId(productUid) ? {
|
|
@@ -247,20 +334,31 @@ function buildProducts(order, locale, productMap) {
|
|
|
247
334
|
...(isPresentId(bookingUid) ? {
|
|
248
335
|
booking_uid: bookingUid
|
|
249
336
|
} : {}),
|
|
337
|
+
...(productNote ? {
|
|
338
|
+
product_note: productNote
|
|
339
|
+
} : {}),
|
|
250
340
|
...(options.length ? {
|
|
251
341
|
options
|
|
252
342
|
} : {}),
|
|
253
343
|
...(resolvedVariant ? {
|
|
254
344
|
variant: resolvedVariant
|
|
255
345
|
} : {}),
|
|
256
|
-
...(Array.isArray(product.combinations) ? {
|
|
257
|
-
combinations: product.combinations
|
|
346
|
+
...(Array.isArray(product.combinations) && product.combinations.length ? {
|
|
347
|
+
combinations: normalizeExistingCombinations(product.combinations, locale)
|
|
258
348
|
} : combinations.length ? {
|
|
259
349
|
combinations
|
|
260
350
|
} : {})
|
|
261
351
|
};
|
|
262
352
|
});
|
|
263
353
|
}
|
|
354
|
+
function resolveProductBasePrice(product) {
|
|
355
|
+
const metadata = product.metadata || {};
|
|
356
|
+
const origin = product._origin || metadata.origin || {};
|
|
357
|
+
const variantId = product.product_variant_id ?? product.variant_id;
|
|
358
|
+
const variant = Array.isArray(origin.variant) && isPresentId(variantId) ? origin.variant.find(item => isSameId(item?.id, variantId)) : undefined;
|
|
359
|
+
const isV2 = metadata.price_schema_version === 2 || metadata.price_schema_version === '2';
|
|
360
|
+
return firstPresentValue(metadata.source_product_price, variant?.price, product._origin?.price, product._origin?.base_price, !isV2 ? metadata.main_product_original_price : undefined, product.base_price, product.price);
|
|
361
|
+
}
|
|
264
362
|
function normalizeProductDiscounts(params) {
|
|
265
363
|
const {
|
|
266
364
|
product,
|
|
@@ -428,15 +526,50 @@ function normalizeProductCombinations(params) {
|
|
|
428
526
|
locale,
|
|
429
527
|
parentProduct
|
|
430
528
|
});
|
|
431
|
-
const
|
|
529
|
+
const productNote = resolveProductNote(bundle, locale);
|
|
530
|
+
const nestedCombinations = Array.isArray(bundle.combinations) ? normalizeExistingCombinations(bundle.combinations, locale) : [];
|
|
432
531
|
return {
|
|
433
|
-
product_title:
|
|
532
|
+
product_title: baseTitle,
|
|
434
533
|
product_quantity: toNumber(bundle.num ?? bundle.quantity ?? 1, 1),
|
|
435
534
|
price: formatBundlePrice(bundle, currencySymbol),
|
|
436
|
-
combinations_options: combinationsOptions
|
|
535
|
+
combinations_options: combinationsOptions,
|
|
536
|
+
...(productNote ? {
|
|
537
|
+
product_note: productNote
|
|
538
|
+
} : {}),
|
|
539
|
+
...(nestedCombinations.length ? {
|
|
540
|
+
combinations: nestedCombinations
|
|
541
|
+
} : {})
|
|
437
542
|
};
|
|
438
543
|
});
|
|
439
544
|
}
|
|
545
|
+
function normalizeExistingCombinations(combinations, locale) {
|
|
546
|
+
return combinations.map(combination => {
|
|
547
|
+
if (!combination || typeof combination !== 'object' || Array.isArray(combination)) {
|
|
548
|
+
return combination;
|
|
549
|
+
}
|
|
550
|
+
const productNote = resolveProductNote(combination, locale);
|
|
551
|
+
const nestedCombinations = Array.isArray(combination.combinations) ? normalizeExistingCombinations(combination.combinations, locale) : undefined;
|
|
552
|
+
const snapshot = {
|
|
553
|
+
...combination
|
|
554
|
+
};
|
|
555
|
+
delete snapshot.product_note;
|
|
556
|
+
delete snapshot.note;
|
|
557
|
+
return {
|
|
558
|
+
...snapshot,
|
|
559
|
+
...(productNote ? {
|
|
560
|
+
product_note: productNote
|
|
561
|
+
} : {}),
|
|
562
|
+
...(nestedCombinations ? {
|
|
563
|
+
combinations: nestedCombinations
|
|
564
|
+
} : {})
|
|
565
|
+
};
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
function resolveProductNote(product, locale) {
|
|
569
|
+
const productNote = getLocalizedValue(product.product_note, locale).trim();
|
|
570
|
+
if (productNote) return productNote;
|
|
571
|
+
return getLocalizedValue(product.note, locale).trim();
|
|
572
|
+
}
|
|
440
573
|
function resolveBundleProductTitle(params) {
|
|
441
574
|
const {
|
|
442
575
|
bundle,
|
|
@@ -619,15 +752,6 @@ function isSameId(left, right) {
|
|
|
619
752
|
if (!isPresentId(left) || !isPresentId(right)) return false;
|
|
620
753
|
return String(left) === String(right);
|
|
621
754
|
}
|
|
622
|
-
function buildOptionTitleSuffix(options) {
|
|
623
|
-
const text = options.map(option => {
|
|
624
|
-
const name = stringify(option.name).trim();
|
|
625
|
-
if (!name) return '';
|
|
626
|
-
const quantity = option.num ?? 1;
|
|
627
|
-
return `${name} x ${quantity}`;
|
|
628
|
-
}).filter(Boolean).join(', ');
|
|
629
|
-
return text ? `(${text})` : '';
|
|
630
|
-
}
|
|
631
755
|
function formatBundlePrice(bundle, currencySymbol) {
|
|
632
756
|
const value = bundle.bundle_selling_price ?? bundle.bundle_sum_price ?? bundle.price ?? 0;
|
|
633
757
|
const amount = new _decimal.default(toMoneyNumber(value));
|
|
@@ -643,7 +767,8 @@ function buildFees(params) {
|
|
|
643
767
|
locale,
|
|
644
768
|
products,
|
|
645
769
|
summary,
|
|
646
|
-
currencySymbol
|
|
770
|
+
currencySymbol,
|
|
771
|
+
financials
|
|
647
772
|
} = params;
|
|
648
773
|
const fees = [];
|
|
649
774
|
for (const surcharge of normalizeArray(order.surcharges || summary.surcharges)) {
|
|
@@ -654,64 +779,101 @@ function buildFees(params) {
|
|
|
654
779
|
value: formatMoney(value, currencySymbol)
|
|
655
780
|
});
|
|
656
781
|
}
|
|
657
|
-
const discountAmount = order.shop_discount
|
|
782
|
+
const discountAmount = firstPresentValue(order.shop_discount, summary.discount_amount, order.discount_amount);
|
|
658
783
|
if (isNonZero(discountAmount)) {
|
|
659
784
|
fees.push({
|
|
660
785
|
item: label(locale, 'orderDiscount'),
|
|
661
786
|
value: formatNegativeMoney(discountAmount, currencySymbol)
|
|
662
787
|
});
|
|
663
788
|
}
|
|
664
|
-
const taxFee = summary.tax_fee
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
}
|
|
671
|
-
const
|
|
789
|
+
const taxFee = firstPresentValue(summary.tax_fee, order.tax_fee);
|
|
790
|
+
const taxTitle = resolveTaxTitle({
|
|
791
|
+
summary,
|
|
792
|
+
order,
|
|
793
|
+
shopInfo,
|
|
794
|
+
locale
|
|
795
|
+
});
|
|
796
|
+
const isPriceIncludeTax = firstPresentValue(summary.is_price_include_tax, order.is_price_include_tax, shopInfo.is_price_include_tax);
|
|
797
|
+
const roundingAmount = firstPresentValue(summary.rounding_amount, order.rounding_amount);
|
|
672
798
|
if (isNonZero(roundingAmount)) {
|
|
673
799
|
fees.push({
|
|
674
800
|
item: label(locale, 'rounding'),
|
|
675
801
|
value: formatMoney(roundingAmount, currencySymbol)
|
|
676
802
|
});
|
|
677
803
|
}
|
|
678
|
-
const payProcessingFee =
|
|
804
|
+
const payProcessingFee = financials.payProcessingFee;
|
|
679
805
|
if (isNonZero(payProcessingFee)) {
|
|
680
806
|
fees.push({
|
|
681
807
|
item: label(locale, 'payProcessingFee'),
|
|
682
808
|
value: formatMoney(payProcessingFee, currencySymbol)
|
|
683
809
|
});
|
|
684
810
|
}
|
|
685
|
-
const productExpectAmount = summary.product_expect_amount
|
|
811
|
+
const productExpectAmount = firstPresentValue(summary.product_expect_amount, summary.product_amount, order.product_expect_amount);
|
|
686
812
|
const productOriginalAmount = firstPresentValue(summary.product_original_amount, order.product_original_amount) ?? calculateProductOriginalAmount(order);
|
|
687
813
|
const totalSavingsAmount = new _decimal.default(toMoneyNumber(productOriginalAmount)).minus(toMoneyNumber(productExpectAmount)).plus(toMoneyNumber(discountAmount));
|
|
688
814
|
return {
|
|
689
815
|
fees,
|
|
690
816
|
countFee: {
|
|
691
|
-
total_amount: formatMoney(summary.total_amount
|
|
817
|
+
total_amount: formatMoney(firstPresentValue(summary.total_amount, order.total_amount) ?? 0, currencySymbol),
|
|
692
818
|
original_item_amount: formatMoney(productOriginalAmount, currencySymbol),
|
|
693
|
-
product_expect_amount: formatMoney(productExpectAmount, currencySymbol),
|
|
694
|
-
expect_amount: formatMoney(
|
|
695
|
-
product_quantity: toNumber(summary.product_quantity
|
|
696
|
-
has_pay: formatMoney(
|
|
819
|
+
product_expect_amount: formatMoney(productExpectAmount ?? 0, currencySymbol),
|
|
820
|
+
expect_amount: formatMoney(financials.totalAmount, currencySymbol),
|
|
821
|
+
product_quantity: toNumber(firstPresentValue(summary.product_quantity, products.reduce((sum, product) => sum + product.product_quantity, 0)), 0),
|
|
822
|
+
has_pay: formatMoney(financials.orderPaidAmount, currencySymbol),
|
|
697
823
|
payment_method: '',
|
|
698
|
-
tax_title:
|
|
699
|
-
total_refund_amount: formatMoney(
|
|
700
|
-
|
|
824
|
+
tax_title: taxTitle,
|
|
825
|
+
total_refund_amount: formatMoney(financials.totalRefundAmount, currencySymbol),
|
|
826
|
+
customer_paid_amount: formatMoney(financials.customerPaidAmount, currencySymbol),
|
|
827
|
+
net_payment_applied: formatMoney(financials.netPaymentApplied, currencySymbol),
|
|
828
|
+
...(isPresentId(roundingAmount) ? {
|
|
701
829
|
rounding_amount: formatMoney(roundingAmount, currencySymbol)
|
|
702
830
|
} : {}),
|
|
703
831
|
...(isNonZero(totalSavingsAmount) ? {
|
|
704
832
|
order_total_discount: formatMoney(totalSavingsAmount, currencySymbol)
|
|
705
833
|
} : {}),
|
|
706
|
-
...(
|
|
834
|
+
...(financials.hasPayProcessingFee ? {
|
|
707
835
|
pay_processing_fee: formatMoney(payProcessingFee, currencySymbol)
|
|
708
836
|
} : {}),
|
|
709
|
-
...(
|
|
837
|
+
...(isPresentId(taxFee) ? {
|
|
710
838
|
tax_fee: formatMoney(taxFee, currencySymbol)
|
|
839
|
+
} : {}),
|
|
840
|
+
...(isPresentId(isPriceIncludeTax) ? {
|
|
841
|
+
is_price_include_tax: normalizeBooleanFlag(isPriceIncludeTax)
|
|
711
842
|
} : {})
|
|
712
843
|
}
|
|
713
844
|
};
|
|
714
845
|
}
|
|
846
|
+
function resolveReceiptFinancials(order, summary) {
|
|
847
|
+
const totalAmount = firstPresentValue(summary.expect_amount, order.expect_amount, summary.total_amount, order.total_amount) ?? 0;
|
|
848
|
+
const rawPayProcessingFee = firstPresentValue(summary.pay_service_charge_amount, order.pay_service_charge_amount);
|
|
849
|
+
const payProcessingFee = rawPayProcessingFee ?? 0;
|
|
850
|
+
const orderPaidAmount = firstPresentValue(summary.order_paid_amount, order.order_paid_amount, sumAppliedPayments(order.payments)) ?? 0;
|
|
851
|
+
const totalRefundAmount = firstPresentValue(summary.total_refund_amount, order.total_refund_amount) ?? 0;
|
|
852
|
+
const netPaymentApplied = _decimal.default.max(new _decimal.default(toMoneyNumber(orderPaidAmount)).minus(toMoneyNumber(totalRefundAmount)), 0);
|
|
853
|
+
const fallbackCustomerPaidAmount = _decimal.default.max(sumCustomerPaidPayments(order.payments), new _decimal.default(toMoneyNumber(orderPaidAmount)).plus(toMoneyNumber(payProcessingFee)));
|
|
854
|
+
const customerPaidAmount = firstPresentValue(summary.customer_paid_amount, order.customer_paid_amount, fallbackCustomerPaidAmount) ?? 0;
|
|
855
|
+
const amountGap = firstPresentValue(summary.amount_gap, order.amount_gap);
|
|
856
|
+
return {
|
|
857
|
+
totalAmount,
|
|
858
|
+
orderPaidAmount,
|
|
859
|
+
payProcessingFee,
|
|
860
|
+
customerPaidAmount,
|
|
861
|
+
totalRefundAmount,
|
|
862
|
+
netPaymentApplied,
|
|
863
|
+
amountGap,
|
|
864
|
+
paymentStatus: resolveReceiptPaymentStatus({
|
|
865
|
+
order,
|
|
866
|
+
summary
|
|
867
|
+
}),
|
|
868
|
+
hasPayProcessingFee: isPresentId(rawPayProcessingFee)
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
function resolveReceiptPaymentStatus(params) {
|
|
872
|
+
return [params.order.payment_status, params.summary.payment_status, params.order.original_payment_status].map(status => stringify(status).trim()).find(Boolean) || '';
|
|
873
|
+
}
|
|
874
|
+
function resolveTaxTitle(params) {
|
|
875
|
+
return [params.summary.tax_title, params.order.tax_title, params.shopInfo.tax_title].map(title => getLocalizedValue(title, params.locale).trim()).find(Boolean) || 'Tax';
|
|
876
|
+
}
|
|
715
877
|
function calculateProductOriginalAmount(order) {
|
|
716
878
|
return normalizeArray(order.products).reduce((total, product) => {
|
|
717
879
|
const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
|
|
@@ -738,25 +900,27 @@ function normalizeCustomerDisplayValue(value) {
|
|
|
738
900
|
return text;
|
|
739
901
|
}
|
|
740
902
|
function buildDelivery(order, locale) {
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
const serviceTypeLabelKey =
|
|
903
|
+
const deliveryType = stringify(order.delivery_type).trim();
|
|
904
|
+
const serviceType = deliveryType || stringify(firstPresentValue(order.metadata?.service_type, order.service_type)).trim();
|
|
905
|
+
const serviceTypeLabelKey = resolveServiceTypeLabelKey(serviceType, order);
|
|
906
|
+
if (!serviceTypeLabelKey) return [];
|
|
744
907
|
const items = [{
|
|
745
908
|
item: '',
|
|
746
909
|
value: label(locale, serviceTypeLabelKey),
|
|
747
910
|
size: 2,
|
|
748
911
|
align: 'left'
|
|
749
912
|
}];
|
|
750
|
-
|
|
913
|
+
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);
|
|
914
|
+
if (isPresentId(handoverTime)) {
|
|
751
915
|
items.push({
|
|
752
|
-
item: label(locale, '
|
|
753
|
-
value:
|
|
916
|
+
item: label(locale, 'handoverTime'),
|
|
917
|
+
value: formatDateTime(handoverTime, locale)
|
|
754
918
|
});
|
|
755
919
|
}
|
|
756
920
|
return items;
|
|
757
921
|
}
|
|
758
922
|
function buildAppointment(order, locale) {
|
|
759
|
-
const bookings = normalizeArray(order.bookings);
|
|
923
|
+
const bookings = sortBookings(normalizeArray(order.bookings));
|
|
760
924
|
if (bookings.length) {
|
|
761
925
|
return bookings.map(booking => {
|
|
762
926
|
const snapshot = {
|
|
@@ -784,6 +948,43 @@ function buildAppointment(order, locale) {
|
|
|
784
948
|
value: getLocalizedValue(tableName, locale)
|
|
785
949
|
}];
|
|
786
950
|
}
|
|
951
|
+
function sortBookings(bookings) {
|
|
952
|
+
return bookings.map((booking, index) => ({
|
|
953
|
+
booking,
|
|
954
|
+
index
|
|
955
|
+
})).sort((left, right) => {
|
|
956
|
+
const leftStart = bookingStartTimestamp(left.booking);
|
|
957
|
+
const rightStart = bookingStartTimestamp(right.booking);
|
|
958
|
+
if (leftStart !== rightStart) return leftStart < rightStart ? -1 : 1;
|
|
959
|
+
for (const field of ['booking_id', 'schedule_event_id']) {
|
|
960
|
+
const fieldOrder = compareOptionalValues(left.booking?.[field], right.booking?.[field]);
|
|
961
|
+
if (fieldOrder !== 0) return fieldOrder;
|
|
962
|
+
}
|
|
963
|
+
const bookingUidOrder = compareOptionalValues(firstPresentValue(left.booking?.metadata?.unique_identification_number, left.booking?.booking_uid), firstPresentValue(right.booking?.metadata?.unique_identification_number, right.booking?.booking_uid));
|
|
964
|
+
return bookingUidOrder || left.index - right.index;
|
|
965
|
+
}).map(({
|
|
966
|
+
booking
|
|
967
|
+
}) => booking);
|
|
968
|
+
}
|
|
969
|
+
function bookingStartTimestamp(booking) {
|
|
970
|
+
const startValues = [booking?.start_at, booking?.start_datetime, booking?.booking_time, isPresentId(booking?.start_date) ? `${booking.start_date} ${stringify(booking.start_time)}`.trim() : undefined];
|
|
971
|
+
for (const startValue of startValues) {
|
|
972
|
+
if (!isPresentId(startValue)) continue;
|
|
973
|
+
const timestamp = (0, _dayjs.default)(startValue).valueOf();
|
|
974
|
+
if (Number.isFinite(timestamp)) return timestamp;
|
|
975
|
+
}
|
|
976
|
+
return Number.POSITIVE_INFINITY;
|
|
977
|
+
}
|
|
978
|
+
function compareOptionalValues(left, right) {
|
|
979
|
+
const hasLeft = isPresentId(left);
|
|
980
|
+
const hasRight = isPresentId(right);
|
|
981
|
+
if (!hasLeft && !hasRight) return 0;
|
|
982
|
+
if (!hasLeft) return 1;
|
|
983
|
+
if (!hasRight) return -1;
|
|
984
|
+
return String(left).localeCompare(String(right), undefined, {
|
|
985
|
+
numeric: true
|
|
986
|
+
});
|
|
987
|
+
}
|
|
787
988
|
function buildResources(order, locale) {
|
|
788
989
|
return normalizeArray(order.resources || order.resource_list).map(resource => ({
|
|
789
990
|
id: resource.id || resource.resource_id || '',
|
|
@@ -801,13 +1002,151 @@ function buildPaymentData(params) {
|
|
|
801
1002
|
includeFundRecordBalance: false
|
|
802
1003
|
}));
|
|
803
1004
|
}
|
|
1005
|
+
function buildRefundData(params) {
|
|
1006
|
+
const payments = normalizeArray(params.order.payments);
|
|
1007
|
+
const refunds = Array.from(normalizeArray(params.order.refunds).reduce((result, refund, index) => {
|
|
1008
|
+
const identity = refundIdentity(refund, index);
|
|
1009
|
+
const candidate = {
|
|
1010
|
+
refund,
|
|
1011
|
+
index
|
|
1012
|
+
};
|
|
1013
|
+
const existing = result.get(identity);
|
|
1014
|
+
if (!existing || shouldPreferRefundCandidate(candidate, existing)) {
|
|
1015
|
+
result.set(identity, candidate);
|
|
1016
|
+
}
|
|
1017
|
+
return result;
|
|
1018
|
+
}, new Map()).values()).filter(({
|
|
1019
|
+
refund
|
|
1020
|
+
}) => isPrintableRefund(refund)).sort((left, right) => {
|
|
1021
|
+
const leftTime = refundTimestamp(left.refund);
|
|
1022
|
+
const rightTime = refundTimestamp(right.refund);
|
|
1023
|
+
if (leftTime !== rightTime) return leftTime < rightTime ? -1 : 1;
|
|
1024
|
+
return left.index - right.index;
|
|
1025
|
+
});
|
|
1026
|
+
return refunds.map(({
|
|
1027
|
+
refund
|
|
1028
|
+
}) => {
|
|
1029
|
+
const payment = resolveRefundPayment(refund, payments);
|
|
1030
|
+
const methodName = paymentMethodName(payment, params.locale) || label(params.locale, 'refund');
|
|
1031
|
+
const amount = firstPresentValue(refund.amount, refund.refund_amount, refund.total_amount) ?? 0;
|
|
1032
|
+
const items = [{
|
|
1033
|
+
item: methodName,
|
|
1034
|
+
value: formatNegativeMoney(amount, params.currencySymbol)
|
|
1035
|
+
}];
|
|
1036
|
+
const occurredAt = firstPresentValue(refund.refund_time, refund.refunded_at, refund.created_at, refund.updated_at);
|
|
1037
|
+
if (isPresentId(occurredAt)) {
|
|
1038
|
+
items.push({
|
|
1039
|
+
item: formatDateTime(occurredAt, params.locale),
|
|
1040
|
+
value: ''
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
return items;
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
function refundIdentity(refund, index) {
|
|
1047
|
+
if (isPresentId(refund.order_refund_id)) return `refund-id:${refund.order_refund_id}`;
|
|
1048
|
+
if (isPresentId(refund.refund_number)) return `refund-number:${refund.refund_number}`;
|
|
1049
|
+
return `refund-index:${index}`;
|
|
1050
|
+
}
|
|
1051
|
+
function shouldPreferRefundCandidate(candidate, existing) {
|
|
1052
|
+
const candidatePrintable = isPrintableRefund(candidate.refund);
|
|
1053
|
+
const existingPrintable = isPrintableRefund(existing.refund);
|
|
1054
|
+
if (candidatePrintable !== existingPrintable) return candidatePrintable;
|
|
1055
|
+
const candidateTime = refundFreshnessTimestamp(candidate.refund);
|
|
1056
|
+
const existingTime = refundFreshnessTimestamp(existing.refund);
|
|
1057
|
+
if (candidateTime !== existingTime) return candidateTime > existingTime;
|
|
1058
|
+
return candidate.index > existing.index;
|
|
1059
|
+
}
|
|
1060
|
+
function refundFreshnessTimestamp(refund) {
|
|
1061
|
+
const timestampValue = firstPresentValue(refund.updated_at, refund.refunded_at, refund.refund_time, refund.created_at);
|
|
1062
|
+
if (!isPresentId(timestampValue)) return Number.NEGATIVE_INFINITY;
|
|
1063
|
+
const timestamp = (0, _dayjs.default)(timestampValue).valueOf();
|
|
1064
|
+
return Number.isFinite(timestamp) ? timestamp : Number.NEGATIVE_INFINITY;
|
|
1065
|
+
}
|
|
1066
|
+
function refundTimestamp(refund) {
|
|
1067
|
+
const occurredAt = firstPresentValue(refund.refund_time, refund.refunded_at, refund.created_at, refund.updated_at);
|
|
1068
|
+
if (!isPresentId(occurredAt)) return Number.POSITIVE_INFINITY;
|
|
1069
|
+
const timestamp = (0, _dayjs.default)(occurredAt).valueOf();
|
|
1070
|
+
return Number.isFinite(timestamp) ? timestamp : Number.POSITIVE_INFINITY;
|
|
1071
|
+
}
|
|
1072
|
+
function isPrintableRefund(refund) {
|
|
1073
|
+
const status = stringify(refund.status).trim().toLowerCase();
|
|
1074
|
+
if (!status) return true;
|
|
1075
|
+
return !['pending', 'payment_pending', 'payment_processing', 'refund_processing', 'processing', 'failed', 'error', 'cancelled', 'canceled', 'voided'].includes(status);
|
|
1076
|
+
}
|
|
1077
|
+
function resolveRefundPayment(refund, payments) {
|
|
1078
|
+
if (refund.payment && typeof refund.payment === 'object' && !Array.isArray(refund.payment)) {
|
|
1079
|
+
return refund.payment;
|
|
1080
|
+
}
|
|
1081
|
+
const orderPaymentId = firstPresentValue(refund.order_payment_id, refund.payment_id);
|
|
1082
|
+
const matchedPayment = payments.find(payment => isSameId(firstPresentValue(payment.order_payment_id, payment.id), orderPaymentId));
|
|
1083
|
+
return matchedPayment || refund;
|
|
1084
|
+
}
|
|
804
1085
|
function buildWallets(params) {
|
|
805
|
-
|
|
1086
|
+
const paymentWallets = normalizeArray(params.order.payments).filter(payment => isPrintablePayment(payment) && !!getFundRecord(payment)).map(payment => buildPaymentItems({
|
|
806
1087
|
payment,
|
|
807
1088
|
locale: params.locale,
|
|
808
1089
|
currencySymbol: params.currencySymbol,
|
|
809
1090
|
includeFundRecordBalance: true
|
|
810
1091
|
}));
|
|
1092
|
+
return [...paymentWallets, ...buildVoucherAssets(params)];
|
|
1093
|
+
}
|
|
1094
|
+
function buildVoucherAssets(params) {
|
|
1095
|
+
const seenVoucherKeys = new Set();
|
|
1096
|
+
return normalizeArray(params.order.vouchers).flatMap((voucher, index) => {
|
|
1097
|
+
if (!voucher || typeof voucher !== 'object' || Array.isArray(voucher)) return [];
|
|
1098
|
+
const voucherKey = getVoucherAssetKey(voucher, index);
|
|
1099
|
+
if (seenVoucherKeys.has(voucherKey)) return [];
|
|
1100
|
+
seenVoucherKeys.add(voucherKey);
|
|
1101
|
+
const name = getVoucherAssetName(voucher, params.locale);
|
|
1102
|
+
const percent = getVoucherDiscountPercent(voucher);
|
|
1103
|
+
if (percent) {
|
|
1104
|
+
return [[{
|
|
1105
|
+
item: appendPercentToVoucherName(name, percent),
|
|
1106
|
+
value: formatVoucherDiscount(percent, params.locale)
|
|
1107
|
+
}]];
|
|
1108
|
+
}
|
|
1109
|
+
const balance = getVoucherBalance(voucher);
|
|
1110
|
+
return [[{
|
|
1111
|
+
item: name,
|
|
1112
|
+
value: ''
|
|
1113
|
+
}, {
|
|
1114
|
+
item: label(params.locale, 'balance'),
|
|
1115
|
+
value: formatMoney(balance, params.currencySymbol)
|
|
1116
|
+
}]];
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
function getVoucherAssetKey(voucher, index) {
|
|
1120
|
+
const identity = firstPresentValue(voucher.voucher_id, voucher.id, voucher.code, voucher.encoded);
|
|
1121
|
+
return identity === undefined ? `voucher-index:${index}` : `voucher:${String(identity)}`;
|
|
1122
|
+
}
|
|
1123
|
+
function getVoucherAssetName(voucher, locale) {
|
|
1124
|
+
return getLocalizedValue(voucher.product_name || voucher.name || voucher.title, locale) || stringify(voucher.encoded || voucher.code || label(locale, 'giftCard'));
|
|
1125
|
+
}
|
|
1126
|
+
function getVoucherDiscountPercent(voucher) {
|
|
1127
|
+
const discountType = stringify(voucher.metadata?.discount_card_type || voucher.discount_card_type).toLowerCase();
|
|
1128
|
+
if (discountType !== 'percent' && discountType !== 'percentage') return null;
|
|
1129
|
+
const percent = new _decimal.default(toMoneyNumber(voucher.par_value));
|
|
1130
|
+
if (!percent.isFinite() || percent.lte(0) || percent.gt(100)) return null;
|
|
1131
|
+
return percent;
|
|
1132
|
+
}
|
|
1133
|
+
function appendPercentToVoucherName(name, percent) {
|
|
1134
|
+
if (/\d+(?:\.\d+)?\s*(?:%|折)|\boff\b/i.test(name)) return name;
|
|
1135
|
+
const separator = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(name) ? '' : ' ';
|
|
1136
|
+
return `${trimDecimal(percent)}%${separator}${name}`;
|
|
1137
|
+
}
|
|
1138
|
+
function formatVoucherDiscount(percent, locale) {
|
|
1139
|
+
const normalizedLocale = normalizeLocaleKey(locale);
|
|
1140
|
+
if (normalizedLocale === 'zh_CN' || normalizedLocale === 'zh_HK') {
|
|
1141
|
+
return `${trimDecimal(percent)}% OFF`;
|
|
1142
|
+
}
|
|
1143
|
+
if (normalizedLocale === 'pt') return `Desconto ${trimDecimal(percent)}%`;
|
|
1144
|
+
return normalizedLocale === 'en' ? `Discount ${trimDecimal(percent)}% OFF` : `${trimDecimal(percent)}% OFF`;
|
|
1145
|
+
}
|
|
1146
|
+
function getVoucherBalance(voucher) {
|
|
1147
|
+
const parValue = new _decimal.default(toMoneyNumber(voucher.par_value));
|
|
1148
|
+
const usedParValue = new _decimal.default(toMoneyNumber(voucher.used_par_value));
|
|
1149
|
+
return _decimal.default.max(parValue.minus(usedParValue), 0);
|
|
811
1150
|
}
|
|
812
1151
|
function buildPaymentItems(params) {
|
|
813
1152
|
const {
|
|
@@ -999,13 +1338,29 @@ function getLocalizedValue(value, locale) {
|
|
|
999
1338
|
const underscoredLocale = locale.replace('-', '_');
|
|
1000
1339
|
return stringify(value[locale] ?? value[dashedLocale] ?? value[underscoredLocale] ?? value.original ?? value.auto ?? value.default ?? value.en ?? '');
|
|
1001
1340
|
}
|
|
1002
|
-
function
|
|
1003
|
-
const normalized = serviceType.toLowerCase();
|
|
1004
|
-
if (
|
|
1005
|
-
if (
|
|
1006
|
-
if (
|
|
1007
|
-
if (
|
|
1008
|
-
return 'dineIn';
|
|
1341
|
+
function resolveServiceTypeLabelKey(serviceType, order) {
|
|
1342
|
+
const normalized = serviceType.trim().toLowerCase().replace(/[\s-]+/g, '_');
|
|
1343
|
+
if (['', 'nil', 'none', 'unknown'].includes(normalized)) return null;
|
|
1344
|
+
if (['pickup', 'pick_up', 'self_pickup'].includes(normalized)) return 'pickUp';
|
|
1345
|
+
if (['delivery', 'shipping', 'local_delivery'].includes(normalized)) return 'delivery';
|
|
1346
|
+
if (['takeaway', 'take_away'].includes(normalized)) return 'takeAway';
|
|
1347
|
+
if (['dine_in', 'dinein'].includes(normalized)) return 'dineIn';
|
|
1348
|
+
if (['shop_service', 'shop_server'].includes(normalized)) {
|
|
1349
|
+
return resolveShopServiceLabelKey(order);
|
|
1350
|
+
}
|
|
1351
|
+
return null;
|
|
1352
|
+
}
|
|
1353
|
+
function resolveShopServiceLabelKey(order) {
|
|
1354
|
+
const rawShopServiceType = firstPresentValue(order.metadata?.shop_service_type?.server_type, order.shop_service_type?.server_type, typeof order.shop_service_type === 'string' ? order.shop_service_type : undefined);
|
|
1355
|
+
if (!isPresentId(rawShopServiceType)) return 'dineIn';
|
|
1356
|
+
const normalized = stringify(rawShopServiceType).trim().toLowerCase().replace(/[\s-]+/g, '_');
|
|
1357
|
+
if (['takeaway', 'take_away'].includes(normalized)) return 'takeAway';
|
|
1358
|
+
if (['dine_in', 'dinein'].includes(normalized)) return 'dineIn';
|
|
1359
|
+
return null;
|
|
1360
|
+
}
|
|
1361
|
+
function normalizeBooleanFlag(value) {
|
|
1362
|
+
if (value === true || value === 1 || stringify(value).trim() === '1') return 1;
|
|
1363
|
+
return 0;
|
|
1009
1364
|
}
|
|
1010
1365
|
function buildShopAddress(shopInfo) {
|
|
1011
1366
|
return [shopInfo.address_street, shopInfo.address_detail, shopInfo.city, shopInfo.province, shopInfo.country, shopInfo.zip].filter(Boolean).join(', ');
|
|
@@ -1026,17 +1381,17 @@ function formatNegativeMoney(value, currencySymbol) {
|
|
|
1026
1381
|
const amount = new _decimal.default(toMoneyNumber(value)).abs();
|
|
1027
1382
|
return `-${currencySymbol}${amount.toFixed(2)}`;
|
|
1028
1383
|
}
|
|
1029
|
-
function
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
}
|
|
1039
|
-
function
|
|
1384
|
+
function sumAppliedPayments(payments) {
|
|
1385
|
+
return normalizeArray(payments).filter(payment => isPrintablePayment(payment)).reduce((sum, payment) => {
|
|
1386
|
+
if (isPresentId(payment.origin_amount)) {
|
|
1387
|
+
return sum.plus(toMoneyNumber(payment.origin_amount));
|
|
1388
|
+
}
|
|
1389
|
+
const amount = new _decimal.default(toMoneyNumber(payment.amount));
|
|
1390
|
+
const serviceFee = _decimal.default.max(toMoneyNumber(payment.service_fee), 0);
|
|
1391
|
+
return sum.plus(_decimal.default.max(amount.minus(serviceFee), 0));
|
|
1392
|
+
}, new _decimal.default(0));
|
|
1393
|
+
}
|
|
1394
|
+
function sumCustomerPaidPayments(payments) {
|
|
1040
1395
|
return normalizeArray(payments).filter(payment => isPrintablePayment(payment)).reduce((sum, payment) => {
|
|
1041
1396
|
return sum.plus(toMoneyNumber(payment.amount ?? payment.origin_amount));
|
|
1042
1397
|
}, new _decimal.default(0));
|
|
@@ -1044,7 +1399,7 @@ function sumPayments(payments) {
|
|
|
1044
1399
|
function isPrintablePayment(payment) {
|
|
1045
1400
|
const status = stringify(payment.status).toLowerCase();
|
|
1046
1401
|
if (!status) return true;
|
|
1047
|
-
return ['paid', 'success', 'succeeded', 'completed'].includes(status);
|
|
1402
|
+
return ['paid', 'success', 'succeeded', 'completed', 'partially_refunded', 'refunded'].includes(status);
|
|
1048
1403
|
}
|
|
1049
1404
|
function normalizeArray(value) {
|
|
1050
1405
|
return Array.isArray(value) ? value : [];
|