@pisell/pisellos 2.2.205 → 2.2.207

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.
Files changed (44) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/modules/OpenData/index.d.ts +1 -0
  3. package/dist/modules/OpenData/index.js +21 -16
  4. package/dist/modules/Order/index.d.ts +9 -0
  5. package/dist/modules/Order/index.js +230 -145
  6. package/dist/modules/Order/types.d.ts +10 -0
  7. package/dist/modules/Order/utils.js +7 -5
  8. package/dist/server/index.d.ts +136 -0
  9. package/dist/server/index.js +2055 -781
  10. package/dist/server/modules/order/index.d.ts +7 -0
  11. package/dist/server/modules/order/index.js +375 -337
  12. package/dist/server/modules/order/types.d.ts +15 -0
  13. package/dist/server/modules/order/types.js +8 -0
  14. package/dist/server/utils/small-ticket.d.ts +69 -0
  15. package/dist/server/utils/small-ticket.js +528 -0
  16. package/dist/solution/BaseSales/index.d.ts +4 -2
  17. package/dist/solution/BaseSales/index.js +248 -188
  18. package/dist/solution/BookingByStep/index.d.ts +1 -1
  19. package/dist/solution/BookingTicket/index.d.ts +8 -1
  20. package/dist/solution/BookingTicket/index.js +443 -263
  21. package/dist/solution/BookingTicket/types.d.ts +2 -1
  22. package/dist/solution/BookingTicket/types.js +3 -1
  23. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  24. package/lib/modules/OpenData/index.d.ts +1 -0
  25. package/lib/modules/OpenData/index.js +6 -4
  26. package/lib/modules/Order/index.d.ts +9 -0
  27. package/lib/modules/Order/index.js +59 -3
  28. package/lib/modules/Order/types.d.ts +10 -0
  29. package/lib/modules/Order/utils.js +4 -3
  30. package/lib/server/index.d.ts +136 -0
  31. package/lib/server/index.js +823 -50
  32. package/lib/server/modules/order/index.d.ts +7 -0
  33. package/lib/server/modules/order/index.js +21 -7
  34. package/lib/server/modules/order/types.d.ts +15 -0
  35. package/lib/server/utils/small-ticket.d.ts +69 -0
  36. package/lib/server/utils/small-ticket.js +555 -0
  37. package/lib/solution/BaseSales/index.d.ts +4 -2
  38. package/lib/solution/BaseSales/index.js +47 -1
  39. package/lib/solution/BookingByStep/index.d.ts +1 -1
  40. package/lib/solution/BookingTicket/index.d.ts +8 -1
  41. package/lib/solution/BookingTicket/index.js +108 -1
  42. package/lib/solution/BookingTicket/types.d.ts +2 -1
  43. package/lib/solution/BookingTicket/types.js +5 -0
  44. package/package.json +1 -1
@@ -0,0 +1,555 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/server/utils/small-ticket.ts
30
+ var small_ticket_exports = {};
31
+ __export(small_ticket_exports, {
32
+ buildSmallTicketData: () => buildSmallTicketData,
33
+ hasSmallTicketData: () => hasSmallTicketData
34
+ });
35
+ module.exports = __toCommonJS(small_ticket_exports);
36
+ var import_dayjs = __toESM(require("dayjs"));
37
+ var import_decimal = __toESM(require("decimal.js"));
38
+ var DEFAULT_LOCALES = ["en", "zh_CN"];
39
+ var LABELS = {
40
+ en: {
41
+ contactName: "Contact name",
42
+ contactMobile: "Contact Mobile",
43
+ email: "email",
44
+ dineIn: "Dine-in",
45
+ takeAway: "Take away",
46
+ delivery: "Delivery",
47
+ pickUp: "Pick-up",
48
+ shopService: "Dine-in",
49
+ pickUpTime: "Pick-up time",
50
+ asap: "ASAP",
51
+ cash: "Cash",
52
+ eftpos: "Eftpos",
53
+ wallet: "Wallet",
54
+ giftCard: "Gift card",
55
+ remainingAmount: "Remaining amount",
56
+ redeemPoints: "Redeem points",
57
+ remainingPoints: "Remaining points",
58
+ table: "Table",
59
+ orderDiscount: "Order discount",
60
+ payProcessingFee: "Pay processing fee",
61
+ rounding: "Rounding"
62
+ },
63
+ zh_CN: {
64
+ contactName: "联系人姓名",
65
+ contactMobile: "联系电话",
66
+ email: "邮箱",
67
+ dineIn: "堂食",
68
+ takeAway: "外带",
69
+ delivery: "配送",
70
+ pickUp: "自提",
71
+ shopService: "堂食",
72
+ pickUpTime: "取餐时间",
73
+ asap: "尽快",
74
+ cash: "现金支付",
75
+ eftpos: "刷卡支付",
76
+ wallet: "钱包支付",
77
+ giftCard: "礼品卡",
78
+ remainingAmount: "剩余金额",
79
+ redeemPoints: "本次使用积分",
80
+ remainingPoints: "剩余积分",
81
+ table: "桌台",
82
+ orderDiscount: "整单折扣",
83
+ payProcessingFee: "支付手续费",
84
+ rounding: "抹零"
85
+ },
86
+ zh_HK: {
87
+ contactName: "聯絡人姓名",
88
+ contactMobile: "聯絡電話",
89
+ email: "電郵",
90
+ dineIn: "堂食",
91
+ takeAway: "外帶",
92
+ delivery: "配送",
93
+ pickUp: "自取",
94
+ shopService: "堂食",
95
+ pickUpTime: "取餐時間",
96
+ asap: "盡快",
97
+ cash: "現金支付",
98
+ eftpos: "刷卡支付",
99
+ wallet: "錢包支付",
100
+ giftCard: "禮品卡",
101
+ remainingAmount: "剩餘金額",
102
+ redeemPoints: "本次使用積分",
103
+ remainingPoints: "剩餘積分",
104
+ table: "桌台",
105
+ orderDiscount: "整單折扣",
106
+ payProcessingFee: "支付手續費",
107
+ rounding: "抹零"
108
+ }
109
+ };
110
+ function buildSmallTicketData(params) {
111
+ const order = params.order || {};
112
+ const shopInfo = params.shopInfo || {};
113
+ const locales = resolveLocales(shopInfo, params.locales);
114
+ const productMap = params.productMap || {};
115
+ return locales.reduce((data, locale) => {
116
+ data[locale] = buildLocaleData({ order, shopInfo, locale, productMap });
117
+ return data;
118
+ }, {});
119
+ }
120
+ function hasSmallTicketData(value) {
121
+ return !!value && typeof value === "object" && Object.keys(value).length > 0;
122
+ }
123
+ function buildLocaleData(params) {
124
+ const { order, shopInfo, locale, productMap } = params;
125
+ const products = buildProducts(order, locale, productMap);
126
+ const summary = getSummary(order);
127
+ const currencySymbol = getCurrencySymbol(order, shopInfo);
128
+ return {
129
+ base_data: buildBaseData({ order, shopInfo, locale }),
130
+ products,
131
+ fees: buildFees({ order, shopInfo, locale, products, summary, currencySymbol }),
132
+ customer: buildCustomer(order, locale),
133
+ appointment: buildAppointment(order, locale),
134
+ delivery: buildDelivery(order, locale),
135
+ resources: buildResources(order, locale),
136
+ payment_data: buildPaymentData({ order, locale, currencySymbol }),
137
+ tickets: Array.isArray(order.tickets) ? order.tickets : [],
138
+ source_shop: [],
139
+ refund_data: [],
140
+ expend_data: []
141
+ };
142
+ }
143
+ function buildBaseData(params) {
144
+ var _a;
145
+ const { order, shopInfo, locale } = params;
146
+ const orderNumber = stringify(
147
+ order.order_number || order.shop_full_order_number || order.shop_order_number || order.external_sale_number
148
+ );
149
+ return {
150
+ shop_name: stringify(shopInfo.name || order.shop_name),
151
+ note: stringify(order.note),
152
+ shop_order_number: stringify(order.shop_order_number),
153
+ order_number: orderNumber,
154
+ shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
155
+ shop_phone: stringify(shopInfo.phone || order.shop_phone),
156
+ shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
157
+ original_payment_status: stringify(order.payment_status),
158
+ is_repeat: 0,
159
+ buzzer: stringify(order.buzzer || order.pickup_number || ((_a = order.metadata) == null ? void 0 : _a.buzzer)),
160
+ order_no: orderNumber,
161
+ order_time: formatDateTime(order.created_at || order.sales_time || /* @__PURE__ */ new Date(), locale)
162
+ };
163
+ }
164
+ function buildProducts(order, locale, productMap) {
165
+ const products = Array.isArray(order.products) ? order.products : [];
166
+ return products.map((product) => {
167
+ const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
168
+ const originalPrice = product.original_price ?? product.selling_price ?? product.payment_price ?? product.price ?? 0;
169
+ const sellingPrice = product.selling_price ?? product.payment_price ?? product.price ?? originalPrice;
170
+ const productTitle = resolveProductTitle({ product, productMap, locale });
171
+ return {
172
+ product_title: productTitle,
173
+ product_quantity: quantity,
174
+ selling_price: formatMoney(sellingPrice, getCurrencySymbol(order, null)),
175
+ original_price: formatMoney(originalPrice, getCurrencySymbol(order, null)),
176
+ total_original_price: formatMoney(new import_decimal.default(toMoneyNumber(originalPrice)).mul(quantity), getCurrencySymbol(order, null)),
177
+ extension_list: Array.isArray(product.extension_list) ? product.extension_list : [],
178
+ ...Array.isArray(product.options) ? {
179
+ options: product.options.map((option) => ({
180
+ name: getLocalizedValue(option.name || option.title, locale),
181
+ value: getLocalizedValue(option.value || option.option || option.item, locale)
182
+ }))
183
+ } : {},
184
+ ...product.variant ? { variant: getLocalizedValue(product.variant, locale) } : {},
185
+ ...Array.isArray(product.combinations) ? { combinations: product.combinations } : {}
186
+ };
187
+ });
188
+ }
189
+ function resolveProductTitle(params) {
190
+ var _a, _b;
191
+ const { product, productMap, locale } = params;
192
+ const ownTitle = getLocalizedValue(
193
+ product.product_title || product.title || product.name || ((_a = product.product) == null ? void 0 : _a.title),
194
+ locale
195
+ );
196
+ if (ownTitle)
197
+ return ownTitle;
198
+ const productId = product.product_id ?? product.id;
199
+ const fallbackProduct = productId !== void 0 && productId !== null ? productMap[productId] || productMap[String(productId)] : null;
200
+ if (!fallbackProduct)
201
+ return "";
202
+ return getLocalizedValue(
203
+ fallbackProduct.product_title || fallbackProduct.title || fallbackProduct.name || fallbackProduct.format_title || ((_b = fallbackProduct.product) == null ? void 0 : _b.title),
204
+ locale
205
+ );
206
+ }
207
+ function buildFees(params) {
208
+ const { order, shopInfo, locale, products, summary, currencySymbol } = params;
209
+ const fees = [];
210
+ for (const surcharge of normalizeArray(order.surcharges || summary.surcharges)) {
211
+ const value = surcharge.amount ?? surcharge.value ?? surcharge.total_amount;
212
+ if (!isNonZero(value))
213
+ continue;
214
+ fees.push({
215
+ item: getLocalizedValue(surcharge.name || surcharge.title || surcharge.item, locale),
216
+ value: formatMoney(value, currencySymbol)
217
+ });
218
+ }
219
+ const discountAmount = summary.discount_amount || order.discount_amount || order.shop_discount;
220
+ if (isNonZero(discountAmount)) {
221
+ fees.push({
222
+ item: label(locale, "orderDiscount"),
223
+ value: formatMoney(new import_decimal.default(toMoneyNumber(discountAmount)).neg(), currencySymbol)
224
+ });
225
+ }
226
+ const taxFee = summary.tax_fee || order.tax_fee;
227
+ if (isNonZero(taxFee)) {
228
+ fees.push({
229
+ item: stringify(summary.tax_title || order.tax_title || shopInfo.tax_title),
230
+ value: formatMoney(taxFee, currencySymbol)
231
+ });
232
+ }
233
+ const roundingAmount = summary.rounding_amount || order.rounding_amount;
234
+ if (isNonZero(roundingAmount)) {
235
+ fees.push({
236
+ item: label(locale, "rounding"),
237
+ value: formatMoney(roundingAmount, currencySymbol)
238
+ });
239
+ }
240
+ const payProcessingFee = summary.pay_service_charge_amount || order.pay_service_charge_amount;
241
+ if (isNonZero(payProcessingFee)) {
242
+ fees.push({
243
+ item: label(locale, "payProcessingFee"),
244
+ value: formatMoney(payProcessingFee, currencySymbol)
245
+ });
246
+ }
247
+ return {
248
+ fees,
249
+ countFee: {
250
+ total_amount: formatMoney(summary.total_amount || order.total_amount, currencySymbol),
251
+ product_expect_amount: formatMoney(
252
+ summary.product_expect_amount || summary.product_amount || order.product_expect_amount,
253
+ currencySymbol
254
+ ),
255
+ expect_amount: formatMoney(summary.expect_amount || order.expect_amount || summary.total_amount || order.total_amount, currencySymbol),
256
+ product_quantity: toNumber(
257
+ summary.product_quantity || products.reduce((sum, product) => sum + product.product_quantity, 0),
258
+ 0
259
+ ),
260
+ has_pay: formatMoney(sumPayments(order.payments), currencySymbol),
261
+ payment_method: "",
262
+ tax_title: stringify(summary.tax_title || order.tax_title || shopInfo.tax_title),
263
+ total_refund_amount: formatMoney(summary.total_refund_amount || order.total_refund_amount, currencySymbol),
264
+ ...isNonZero(roundingAmount) ? { rounding_amount: formatMoney(roundingAmount, currencySymbol) } : {},
265
+ ...isNonZero(discountAmount) ? { order_total_discount: formatMoney(discountAmount, currencySymbol) } : {},
266
+ ...isNonZero(payProcessingFee) ? { pay_processing_fee: formatMoney(payProcessingFee, currencySymbol) } : {},
267
+ ...isNonZero(taxFee) ? { tax_fee: formatMoney(taxFee, currencySymbol) } : {}
268
+ }
269
+ };
270
+ }
271
+ function buildCustomer(order, locale) {
272
+ var _a, _b, _c, _d;
273
+ return [
274
+ { item: label(locale, "contactName"), value: normalizeCustomerDisplayValue(order.customer_name || ((_a = order.customer) == null ? void 0 : _a.name) || ((_b = order.customer) == null ? void 0 : _b.display_name)) },
275
+ { item: label(locale, "contactMobile"), value: stringify(order.phone || ((_c = order.customer) == null ? void 0 : _c.phone)) },
276
+ { item: label(locale, "email"), value: stringify(order.email || ((_d = order.customer) == null ? void 0 : _d.email)) }
277
+ ];
278
+ }
279
+ function normalizeCustomerDisplayValue(value) {
280
+ const text = stringify(value).trim();
281
+ if (!text)
282
+ return "";
283
+ if (text.toLowerCase() === "select a customer")
284
+ return "";
285
+ return text;
286
+ }
287
+ function buildDelivery(order, locale) {
288
+ var _a;
289
+ const serviceType = stringify(((_a = order.metadata) == null ? void 0 : _a.service_type) || order.service_type || order.delivery_type);
290
+ if (!serviceType)
291
+ return [];
292
+ const serviceTypeLabelKey = serviceTypeToLabelKey(serviceType);
293
+ const items = [
294
+ {
295
+ item: "",
296
+ value: label(locale, serviceTypeLabelKey),
297
+ size: 2,
298
+ align: "left"
299
+ }
300
+ ];
301
+ if (serviceType === "shop_server" || serviceType === "shop_service") {
302
+ items.push({
303
+ item: label(locale, "pickUpTime"),
304
+ value: label(locale, "asap")
305
+ });
306
+ }
307
+ return items;
308
+ }
309
+ function buildAppointment(order, locale) {
310
+ var _a, _b, _c, _d;
311
+ const tableName = order.table_name || ((_a = order.metadata) == null ? void 0 : _a.table_name) || ((_c = (_b = order.metadata) == null ? void 0 : _b.table) == null ? void 0 : _c.name) || ((_d = order.form_data) == null ? void 0 : _d.table_name);
312
+ if (!tableName)
313
+ return [];
314
+ return [
315
+ {
316
+ item: label(locale, "table"),
317
+ value: getLocalizedValue(tableName, locale)
318
+ }
319
+ ];
320
+ }
321
+ function buildResources(order, locale) {
322
+ return normalizeArray(order.resources || order.resource_list).map((resource) => ({
323
+ id: resource.id || resource.resource_id || "",
324
+ code: "",
325
+ title: getLocalizedValue(resource.title || resource.name, locale),
326
+ form_title: getLocalizedValue(resource.form_title || resource.type || "", locale)
327
+ }));
328
+ }
329
+ function buildPaymentData(params) {
330
+ const payments = normalizeArray(params.order.payments);
331
+ return payments.filter((payment) => isPrintablePayment(payment)).map((payment) => {
332
+ var _a;
333
+ const items = [
334
+ {
335
+ item: paymentMethodName(payment, params.locale),
336
+ value: formatMoney(payment.amount ?? payment.origin_amount, params.currencySymbol)
337
+ }
338
+ ];
339
+ const fundRecord = getFundRecord(payment);
340
+ if (fundRecord) {
341
+ items.push(...buildFundRecordPaymentItems({ payment, fundRecord, locale: params.locale, currencySymbol: params.currencySymbol }));
342
+ } else {
343
+ const remainingAmount = payment.remaining_amount ?? payment.balance ?? ((_a = payment.metadata) == null ? void 0 : _a.remaining_amount);
344
+ if (remainingAmount !== void 0 && remainingAmount !== null) {
345
+ items.push({
346
+ item: label(params.locale, "remainingAmount"),
347
+ value: formatMoney(remainingAmount, params.currencySymbol)
348
+ });
349
+ }
350
+ }
351
+ items.push({
352
+ item: formatDateTime(payment.paid_at || payment.created_at || payment.updated_at || /* @__PURE__ */ new Date(), params.locale),
353
+ value: ""
354
+ });
355
+ return items;
356
+ });
357
+ }
358
+ function buildFundRecordPaymentItems(params) {
359
+ const { payment, fundRecord, locale, currencySymbol } = params;
360
+ const items = [];
361
+ const usingBeforeValue = fundRecord.using_before_value;
362
+ const usingAfterValue = fundRecord.using_after_value;
363
+ if (isPointCardPayment(payment) && usingBeforeValue !== void 0 && usingAfterValue !== void 0) {
364
+ const usedPoints = new import_decimal.default(toMoneyNumber(usingBeforeValue)).minus(toMoneyNumber(usingAfterValue));
365
+ items.push({
366
+ item: label(locale, "redeemPoints"),
367
+ value: trimDecimal(usedPoints)
368
+ });
369
+ items.push({
370
+ item: label(locale, "remainingPoints"),
371
+ value: trimDecimal(new import_decimal.default(toMoneyNumber(usingAfterValue)))
372
+ });
373
+ return items;
374
+ }
375
+ if (usingAfterValue !== void 0 && usingAfterValue !== null) {
376
+ items.push({
377
+ item: label(locale, "remainingAmount"),
378
+ value: formatMoney(usingAfterValue, currencySymbol)
379
+ });
380
+ }
381
+ return items;
382
+ }
383
+ function getFundRecord(payment) {
384
+ const fundRecord = payment.fund_record;
385
+ if (!fundRecord || typeof fundRecord !== "object" || Array.isArray(fundRecord))
386
+ return null;
387
+ if (!fundRecord.voucher_id && !fundRecord.code)
388
+ return null;
389
+ return fundRecord;
390
+ }
391
+ function isPointCardPayment(payment) {
392
+ var _a;
393
+ const code = stringify(payment.code || payment.payment_method).toUpperCase();
394
+ const type = stringify(payment.type || ((_a = payment.fund_record) == null ? void 0 : _a.tag)).toLowerCase();
395
+ return code === "POINTCARD" || type === "point_card";
396
+ }
397
+ function maskMachineCode(code) {
398
+ const text = stringify(code);
399
+ if (text.length <= 6)
400
+ return text;
401
+ return `${text.slice(0, 2)}**${text.slice(-4)}`;
402
+ }
403
+ function trimDecimal(value) {
404
+ return value.toDecimalPlaces(2).toFixed(2).replace(/\.?0+$/, "");
405
+ }
406
+ function getFundRecordPaymentName(payment, locale) {
407
+ const fundRecord = getFundRecord(payment);
408
+ if (!fundRecord)
409
+ return "";
410
+ const name = getLocalizedValue(fundRecord.wallet_pass_name, locale);
411
+ const code = maskMachineCode(fundRecord.code);
412
+ if (!name && !code)
413
+ return "";
414
+ if (!code)
415
+ return name;
416
+ const fallbackName = getLocalizedValue(
417
+ payment.name || payment.title || payment.payment_method_name || payment.method_name || payment.code,
418
+ locale
419
+ );
420
+ return `${name || fallbackName}(${code})`;
421
+ }
422
+ function appendMachineCodeToName(name, payment) {
423
+ const fundRecord = getFundRecord(payment);
424
+ if (!(fundRecord == null ? void 0 : fundRecord.code))
425
+ return name;
426
+ return `${name}(${maskMachineCode(fundRecord.code)})`;
427
+ }
428
+ function paymentMethodName(payment, locale) {
429
+ const fundRecordName = getFundRecordPaymentName(payment, locale);
430
+ if (fundRecordName)
431
+ return fundRecordName;
432
+ const raw = payment.name || payment.title || payment.payment_method_name || payment.method_name;
433
+ if (raw)
434
+ return appendMachineCodeToName(getLocalizedValue(raw, locale), payment);
435
+ const code = stringify(payment.code || payment.type || payment.payment_method || payment.method).toLowerCase();
436
+ if (code.includes("cash"))
437
+ return label(locale, "cash");
438
+ if (code.includes("eftpos") || code.includes("card"))
439
+ return label(locale, "eftpos");
440
+ if (code.includes("wallet"))
441
+ return label(locale, "wallet");
442
+ if (code.includes("gift"))
443
+ return label(locale, "giftCard");
444
+ return stringify(payment.code || payment.type || payment.payment_method || payment.method);
445
+ }
446
+ function getSummary(order) {
447
+ return order.summary && typeof order.summary === "object" ? order.summary : order;
448
+ }
449
+ function getCurrencySymbol(order, shopInfo) {
450
+ return stringify(order.currency_symbol || (shopInfo == null ? void 0 : shopInfo.currency_symbol) || order.shop_symbol || "$") || "$";
451
+ }
452
+ function resolveLocales(shopInfo, locales) {
453
+ const preferred = [
454
+ ...locales || [],
455
+ shopInfo.primary_locale,
456
+ ...DEFAULT_LOCALES
457
+ ].filter(Boolean);
458
+ return Array.from(new Set(preferred.map(normalizeLocaleKey)));
459
+ }
460
+ function normalizeLocaleKey(locale) {
461
+ return locale.replace("-", "_");
462
+ }
463
+ function label(locale, key) {
464
+ var _a;
465
+ return ((_a = LABELS[locale]) == null ? void 0 : _a[key]) || LABELS.en[key] || key;
466
+ }
467
+ function getLocalizedValue(value, locale) {
468
+ if (value === void 0 || value === null)
469
+ return "";
470
+ if (typeof value !== "object")
471
+ return stringify(value);
472
+ const dashedLocale = locale.replace("_", "-");
473
+ return stringify(
474
+ value[locale] ?? value[dashedLocale] ?? value.default ?? value.en ?? value.zh_CN ?? value["zh-CN"] ?? Object.values(value).find((item) => typeof item === "string" || typeof item === "number") ?? ""
475
+ );
476
+ }
477
+ function serviceTypeToLabelKey(serviceType) {
478
+ const normalized = serviceType.toLowerCase();
479
+ if (normalized.includes("take"))
480
+ return "takeAway";
481
+ if (normalized.includes("delivery"))
482
+ return "delivery";
483
+ if (normalized.includes("pick"))
484
+ return "pickUp";
485
+ if (normalized.includes("shop"))
486
+ return "shopService";
487
+ return "dineIn";
488
+ }
489
+ function buildShopAddress(shopInfo) {
490
+ return [
491
+ shopInfo.address_street,
492
+ shopInfo.address_detail,
493
+ shopInfo.city,
494
+ shopInfo.province,
495
+ shopInfo.country,
496
+ shopInfo.zip
497
+ ].filter(Boolean).join(", ");
498
+ }
499
+ function formatDateTime(value, locale) {
500
+ const date = (0, import_dayjs.default)(value);
501
+ if (!date.isValid())
502
+ return stringify(value);
503
+ if (locale === "en")
504
+ return date.format("HH:mm:ss DD/MM/YYYY");
505
+ return date.format("YYYY/MM/DD HH:mm:ss");
506
+ }
507
+ function formatMoney(value, currencySymbol) {
508
+ if (value instanceof import_decimal.default)
509
+ return `${currencySymbol}${value.toFixed(2)}`;
510
+ if (typeof value === "string" && value.trim().startsWith(currencySymbol))
511
+ return value;
512
+ const amount = new import_decimal.default(toMoneyNumber(value));
513
+ return `${currencySymbol}${amount.toFixed(2)}`;
514
+ }
515
+ function sumPayments(payments) {
516
+ return normalizeArray(payments).filter((payment) => isPrintablePayment(payment)).reduce((sum, payment) => {
517
+ return sum.plus(toMoneyNumber(payment.amount ?? payment.origin_amount));
518
+ }, new import_decimal.default(0));
519
+ }
520
+ function isPrintablePayment(payment) {
521
+ const status = stringify(payment.status).toLowerCase();
522
+ if (!status)
523
+ return true;
524
+ return ["paid", "success", "succeeded", "completed"].includes(status);
525
+ }
526
+ function normalizeArray(value) {
527
+ return Array.isArray(value) ? value : [];
528
+ }
529
+ function isNonZero(value) {
530
+ return !new import_decimal.default(toMoneyNumber(value)).isZero();
531
+ }
532
+ function toMoneyNumber(value) {
533
+ if (value instanceof import_decimal.default)
534
+ return value.toString();
535
+ if (typeof value === "number")
536
+ return Number.isFinite(value) ? value : 0;
537
+ if (typeof value !== "string")
538
+ return 0;
539
+ const normalized = value.replace(/[^\d.-]/g, "");
540
+ return normalized || 0;
541
+ }
542
+ function toNumber(value, fallback) {
543
+ const numberValue = Number(value);
544
+ return Number.isFinite(numberValue) ? numberValue : fallback;
545
+ }
546
+ function stringify(value) {
547
+ if (value === void 0 || value === null)
548
+ return "";
549
+ return String(value);
550
+ }
551
+ // Annotate the CommonJS export names for ESM import in node:
552
+ 0 && (module.exports = {
553
+ buildSmallTicketData,
554
+ hasSmallTicketData
555
+ });
@@ -14,6 +14,7 @@ import type { SalesSummaryModule } from '../../modules/SalesSummary';
14
14
  import type { ScheduleModule } from '../../modules/Schedule';
15
15
  import { QuotationModule } from '../../modules/Quotation';
16
16
  import type { ISalesDetail, ISalesDetailHeader, ISalesBooking, ISalesPayment, ISalesSurcharge } from './utils/parseSalesResponse';
17
+ import { AppPlugin } from '../../plugins/app';
17
18
  import { type TransformBaseProductToOrderProductParams } from './utils/transformBaseProductToOrderProduct';
18
19
  export interface BaseSalesState {
19
20
  order?: OrderModule;
@@ -29,7 +30,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
29
30
  isSolution: boolean;
30
31
  protected initializeOptions: ModuleOptions;
31
32
  private logger;
32
- private appPlugin;
33
+ protected appPlugin: AppPlugin;
33
34
  protected store: BaseSalesState;
34
35
  protected otherParams: Record<string, any>;
35
36
  protected cacheId: string | undefined;
@@ -86,7 +87,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
86
87
  * sessionStorage 损坏时静默忽略,按空状态注册。
87
88
  */
88
89
  protected readSessionCacheData(): Record<string, any>;
89
- private getAppData;
90
+ protected getAppData<T>(key: string): T | undefined;
90
91
  private syncAppDataToTempOrder;
91
92
  initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
92
93
  destroy(): Promise<void>;
@@ -184,6 +185,7 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
184
185
  smallTicketDataFlag?: number;
185
186
  enhancePayload?: SubmitPayloadEnhancer;
186
187
  }): Promise<T>;
188
+ printLocalOrderReceipt<T = any>(): Promise<T>;
187
189
  private getSubmitPaymentStatus;
188
190
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
189
191
  /** 读取当前 BaseSales 订单上下文中的 Sales 协议支付项。 */
@@ -37,6 +37,7 @@ var import_BaseModule = require("../../modules/BaseModule");
37
37
  var import_types = require("./types");
38
38
  var import_Order = require("../../modules/Order");
39
39
  var import_decimal = __toESM(require("decimal.js"));
40
+ var import_lodash_es = require("lodash-es");
40
41
  var import_types2 = require("../BookingByStep/types");
41
42
  var import_utils = require("../../modules/Order/utils");
42
43
  var import_dayjs = __toESM(require("dayjs"));
@@ -69,6 +70,28 @@ function preserveManualProductDiscountProducts(previousProducts, nextProducts) {
69
70
  return previous && isBaseSalesManualProductDiscountProduct(previous) ? previous : product;
70
71
  });
71
72
  }
73
+ function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord) {
74
+ if (!currentTempOrder)
75
+ return loadedRecord;
76
+ return (0, import_lodash_es.mergeWith)(
77
+ (0, import_lodash_es.cloneDeep)(currentTempOrder),
78
+ (0, import_lodash_es.cloneDeep)(loadedRecord || {}),
79
+ (currentValue, loadedValue) => {
80
+ if (Array.isArray(currentValue) && Array.isArray(loadedValue)) {
81
+ return [
82
+ ...(0, import_lodash_es.cloneDeep)(currentValue),
83
+ ...(0, import_lodash_es.cloneDeep)(loadedValue)
84
+ ];
85
+ }
86
+ if (Array.isArray(loadedValue))
87
+ return (0, import_lodash_es.cloneDeep)(loadedValue);
88
+ if (Array.isArray(currentValue) && loadedValue === void 0) {
89
+ return (0, import_lodash_es.cloneDeep)(currentValue);
90
+ }
91
+ return void 0;
92
+ }
93
+ );
94
+ }
72
95
  var BaseSalesImpl = class extends import_BaseModule.BaseModule {
73
96
  constructor(name, version) {
74
97
  super(name, version);
@@ -507,7 +530,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
507
530
  const message = res && (res.message || res.msg) || `加载销售详情失败: ${lookup}`;
508
531
  throw new Error(message);
509
532
  }
510
- const sales = await this.store.order.hydrateTempOrderFromRecord(res.data, { recalcOnHydrate: false });
533
+ const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
534
+ const record = params.merge ? mergeSalesDetailRecordWithTempOrder(currentTempOrder, res.data) : res.data;
535
+ const sales = await this.store.order.hydrateTempOrderFromRecord(record, { recalcOnHydrate: false });
511
536
  this.currentSalesDetail = sales;
512
537
  await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, { sales });
513
538
  return sales;
@@ -1195,6 +1220,26 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1195
1220
  };
1196
1221
  return this.store.order.submitTempOrder(submitParams);
1197
1222
  }
1223
+ async printLocalOrderReceipt() {
1224
+ var _a, _b, _c, _d, _e, _f, _g;
1225
+ if (!this.store.order) {
1226
+ throw new Error("BaseSales 解决方案需要 order 模块支持");
1227
+ }
1228
+ const payload = this.store.order.buildCurrentSubmitPayloadForLocalPrint({
1229
+ cacheId: this.cacheId,
1230
+ platform: (_a = this.otherParams) == null ? void 0 : _a.platform,
1231
+ businessCode: ((_b = this.otherParams) == null ? void 0 : _b.businessCode) || ((_c = this.otherParams) == null ? void 0 : _c.business_code),
1232
+ channel: this.getSubmitOrderSalesChannel(),
1233
+ type: (_d = this.otherParams) == null ? void 0 : _d.type
1234
+ });
1235
+ const response = await this.request.post("/local/print-order", payload, {
1236
+ osServer: true,
1237
+ customToast: () => {
1238
+ }
1239
+ });
1240
+ await ((_g = (_f = this.store.order).applyLocalPrintOrderNumbers) == null ? void 0 : _g.call(_f, (_e = response == null ? void 0 : response.data) == null ? void 0 : _e.order));
1241
+ return response;
1242
+ }
1198
1243
  getSubmitPaymentStatus(paymentStatus) {
1199
1244
  var _a, _b;
1200
1245
  if (paymentStatus !== void 0)
@@ -1305,6 +1350,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1305
1350
  error: error instanceof Error ? error.message : String(error)
1306
1351
  });
1307
1352
  });
1353
+ } else {
1308
1354
  }
1309
1355
  return payments;
1310
1356
  }
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 2 | 1 | 5 | 3 | 4 | 6;
314
+ weekNum: 0 | 1 | 2 | 5 | 3 | 6 | 4;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;