@pisell/pisellos 0.10.35 → 0.10.37

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.
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 5 | 3 | 1 | 2 | 4 | 6;
329
+ weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -1 +1,46 @@
1
- "use strict";
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _examples.BUY_X_GET_Y_FREE_STRATEGY;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _examples.ITEM_REWARD_STRATEGY;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "PromotionAdapter", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _adapter.PromotionAdapter;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "PromotionEvaluator", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _evaluator.PromotionEvaluator;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "default", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _adapter.default;
40
+ }
41
+ });
42
+ var _evaluator = require("./evaluator");
43
+ var _adapter = _interopRequireWildcard(require("./adapter"));
44
+ var _examples = require("./examples");
45
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
46
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -72,13 +72,6 @@ function getVoucherPaymentLifecycleKey(payment) {
72
72
  if (!isVoucherPaymentRecord(payment)) return null;
73
73
  return `${String(payment.voucher_id)}::${String(payment.status || '')}`;
74
74
  }
75
- function hasPersistedOrderId(orderId) {
76
- if (orderId === undefined || orderId === null || orderId === '') return false;
77
- if (typeof orderId === 'string' && orderId.startsWith('LOCAL_')) return false;
78
- const normalizedOrderId = Number(orderId);
79
- if (Number.isFinite(normalizedOrderId)) return normalizedOrderId > 0;
80
- return String(orderId).trim() !== '';
81
- }
82
75
  class OrderModule extends _BaseModule.BaseModule {
83
76
  defaultName = 'order';
84
77
  defaultVersion = '1.0.0';
@@ -480,7 +473,6 @@ class OrderModule extends _BaseModule.BaseModule {
480
473
  this.store.virtualCurrencyList = prepareConfigResult?.virtualCurrencyList || [];
481
474
  if (prepareConfigResult) {
482
475
  this.writePointCardSnapshotFromPrepareConfig({
483
- orderId,
484
476
  customerId: params.customerId,
485
477
  availableWalletPassList: prepareConfigResult.availableWalletPassList || []
486
478
  });
@@ -986,8 +978,6 @@ class OrderModule extends _BaseModule.BaseModule {
986
978
  const tempOrder = this.store.tempOrder;
987
979
  if (!tempOrder) return;
988
980
  if (String(tempOrder.customer_id ?? '') !== String(params.customerId)) return;
989
- const effectiveOrderId = params.orderId ?? tempOrder.order_id;
990
- if (hasPersistedOrderId(effectiveOrderId)) return;
991
981
  tempOrder.order_meta_list = {
992
982
  ...((0, _utils.normalizeOrderMetaList)(tempOrder.order_meta_list) || {}),
993
983
  point_cards_snapshot: (0, _utils.buildPointCardSnapshotFromWalletPassList)(params.availableWalletPassList)
@@ -2465,7 +2455,7 @@ class OrderModule extends _BaseModule.BaseModule {
2465
2455
  email: tempOrder.email
2466
2456
  });
2467
2457
  const nextCustomerId = tempOrder.customer_id ?? null;
2468
- if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '') && !hasPersistedOrderId(tempOrder.order_id)) {
2458
+ if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')) {
2469
2459
  this.store.availableWalletIds = [];
2470
2460
  this.clearTempOrderPointCardSnapshot(tempOrder);
2471
2461
  }
@@ -2505,9 +2495,7 @@ class OrderModule extends _BaseModule.BaseModule {
2505
2495
  if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')) {
2506
2496
  this.store.availableWalletIds = [];
2507
2497
  this.store.virtualCurrencyList = [];
2508
- if (!hasPersistedOrderId(tempOrder.order_id)) {
2509
- this.clearTempOrderPointCardSnapshot(tempOrder);
2510
- }
2498
+ this.clearTempOrderPointCardSnapshot(tempOrder);
2511
2499
  (0, _utils.clearTempOrderHolderAssignments)(tempOrder);
2512
2500
  this.clearCustomerBoundDiscounts(tempOrder);
2513
2501
  this.applyDiscount();
@@ -2547,9 +2535,7 @@ class OrderModule extends _BaseModule.BaseModule {
2547
2535
  if (tempOrder._extend) delete tempOrder._extend.customerSnapshot;
2548
2536
  this.store.availableWalletIds = [];
2549
2537
  this.store.virtualCurrencyList = [];
2550
- if (!hasPersistedOrderId(tempOrder.order_id)) {
2551
- this.clearTempOrderPointCardSnapshot(tempOrder);
2552
- }
2538
+ this.clearTempOrderPointCardSnapshot(tempOrder);
2553
2539
  this.clearCustomerBoundDiscounts(tempOrder);
2554
2540
  this.applyDiscount();
2555
2541
  this.persistTempOrder();
@@ -28,6 +28,8 @@ export interface SmallTicketItem {
28
28
  value: string;
29
29
  size?: number;
30
30
  align?: string;
31
+ product_uid?: string | number;
32
+ booking_uid?: string | number;
31
33
  }
32
34
  export interface SmallTicketProduct {
33
35
  product_title: string;
@@ -35,7 +37,7 @@ export interface SmallTicketProduct {
35
37
  selling_price: string;
36
38
  total_selling_price: string;
37
39
  original_price: string;
38
- base_price: string;
40
+ base_price?: string;
39
41
  total_original_price: string;
40
42
  options_total_price?: string;
41
43
  package_items_total_price?: string;
@@ -53,11 +55,7 @@ export interface SmallTicketProduct {
53
55
  variant?: string;
54
56
  combinations?: any[];
55
57
  }
56
- export interface SmallTicketBookingSnapshot extends Record<string, any> {
57
- product_uid?: string | number;
58
- booking_uid?: string | number;
59
- }
60
- export type SmallTicketAppointment = SmallTicketItem[] | SmallTicketBookingSnapshot[];
58
+ export type SmallTicketAppointment = SmallTicketItem[];
61
59
  export interface SmallTicketLocaleData {
62
60
  base_data: Record<string, any>;
63
61
  products: SmallTicketProduct[];
@@ -33,8 +33,13 @@ const LABELS = {
33
33
  redeemPoints: 'Redeem points',
34
34
  remainingPoints: 'Points balance',
35
35
  table: 'Table',
36
+ bookingId: 'Booking ID',
37
+ bookingDateTime: 'Date & time',
38
+ bookingResource: 'Resource',
39
+ bookingHolder: 'Holder',
36
40
  orderDiscount: 'Order discount',
37
41
  manualDiscount: 'Manual discount',
42
+ manualMarkup: 'Manual markup',
38
43
  payProcessingFee: 'Pay processing fee',
39
44
  surchargeIncluded: 'Surcharge(Included)',
40
45
  rounding: 'Rounding',
@@ -66,8 +71,13 @@ const LABELS = {
66
71
  redeemPoints: '本次使用积分',
67
72
  remainingPoints: '积分余额',
68
73
  table: '桌台',
74
+ bookingId: '预约编号',
75
+ bookingDateTime: '日期和时间',
76
+ bookingResource: '资源',
77
+ bookingHolder: '预约人',
69
78
  orderDiscount: '整单折扣',
70
79
  manualDiscount: '手动折扣',
80
+ manualMarkup: '手动加价',
71
81
  payProcessingFee: '支付手续费',
72
82
  surchargeIncluded: '手续费(已含)',
73
83
  rounding: '抹零',
@@ -99,8 +109,13 @@ const LABELS = {
99
109
  redeemPoints: '本次使用積分',
100
110
  remainingPoints: '積分餘額',
101
111
  table: '桌台',
112
+ bookingId: '預約編號',
113
+ bookingDateTime: '日期和時間',
114
+ bookingResource: '資源',
115
+ bookingHolder: '預約人',
102
116
  orderDiscount: '整單折扣',
103
117
  manualDiscount: '手動折扣',
118
+ manualMarkup: '手動加價',
104
119
  payProcessingFee: '支付手續費',
105
120
  surchargeIncluded: '手續費(已含)',
106
121
  rounding: '抹零',
@@ -130,8 +145,13 @@ const LABELS = {
130
145
  redeemPoints: '利用ポイント',
131
146
  remainingPoints: 'ポイント残高',
132
147
  table: 'テーブル',
148
+ bookingId: '予約ID',
149
+ bookingDateTime: '日時',
150
+ bookingResource: 'リソース',
151
+ bookingHolder: '予約者',
133
152
  orderDiscount: '注文割引',
134
153
  manualDiscount: '手動割引',
154
+ manualMarkup: '手動値上げ',
135
155
  payProcessingFee: '決済手数料',
136
156
  rounding: '端数調整',
137
157
  gross: '総重量',
@@ -162,8 +182,13 @@ const LABELS = {
162
182
  redeemPoints: 'Pontos utilizados',
163
183
  remainingPoints: 'Saldo de pontos',
164
184
  table: 'Mesa',
185
+ bookingId: 'ID da reserva',
186
+ bookingDateTime: 'Data e hora',
187
+ bookingResource: 'Recurso',
188
+ bookingHolder: 'Titular',
165
189
  orderDiscount: 'Desconto do pedido',
166
190
  manualDiscount: 'Desconto manual',
191
+ manualMarkup: 'Acréscimo manual',
167
192
  payProcessingFee: 'Taxa de processamento',
168
193
  rounding: 'Arredondamento',
169
194
  gross: 'Peso bruto',
@@ -281,7 +306,8 @@ function buildBaseData(params) {
281
306
  }
282
307
  function buildProducts(order, locale, productMap) {
283
308
  const products = Array.isArray(order.products) ? order.products : [];
284
- return products.map(product => {
309
+ return products.map(rawProduct => {
310
+ const product = restoreReceiptDiscountHierarchy(rawProduct);
285
311
  const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
286
312
  const originalPrice = product.original_price ?? product.selling_price ?? product.payment_price ?? product.price ?? 0;
287
313
  const sellingPrice = product.selling_price ?? product.payment_price ?? product.price ?? originalPrice;
@@ -322,13 +348,16 @@ function buildProducts(order, locale, productMap) {
322
348
  const productNote = resolveProductNote(product, locale);
323
349
  const basePrice = resolveProductBasePrice(product);
324
350
  const resolvedCombinations = Array.isArray(product.combinations) && product.combinations.length ? normalizeExistingCombinations(product.combinations, locale, currencySymbol) : combinations;
351
+ const shouldIncludeBasePrice = options.length > 0 || resolvedCombinations.length > 0 || hasProductDiscount(product, extensionList);
325
352
  return {
326
353
  product_title: productTitle,
327
354
  product_quantity: quantity,
328
355
  selling_price: formatMoney(sellingPrice, currencySymbol),
329
356
  total_selling_price: formatCalculatedMoney(new _decimal.default(toMoneyNumber(sellingPrice)).mul(quantity), currencySymbol),
330
357
  original_price: formatMoney(originalPrice, currencySymbol),
331
- base_price: formatCalculatedMoney(basePrice ?? 0, currencySymbol),
358
+ ...(shouldIncludeBasePrice ? {
359
+ base_price: formatCalculatedMoney(basePrice ?? 0, currencySymbol)
360
+ } : {}),
332
361
  total_original_price: formatMoney(new _decimal.default(toMoneyNumber(originalPrice)).mul(quantity), currencySymbol),
333
362
  ...(options.length ? {
334
363
  options_total_price: sumNormalizedOptionTotals(options, currencySymbol)
@@ -358,6 +387,73 @@ function buildProducts(order, locale, productMap) {
358
387
  };
359
388
  });
360
389
  }
390
+ const RECEIPT_BUNDLE_MAP_ID_KEY = 'custom_product_bundle_map_id';
391
+ function restoreReceiptDiscountHierarchy(source) {
392
+ if (!source || typeof source !== 'object' || Array.isArray(source)) {
393
+ return source;
394
+ }
395
+ const childKey = Array.isArray(source.combinations) && source.combinations.length ? 'combinations' : Array.isArray(source.product_bundle) && source.product_bundle.length ? 'product_bundle' : null;
396
+ if (!childKey) return {
397
+ ...source
398
+ };
399
+ const children = source[childKey].map(child => child && typeof child === 'object' && !Array.isArray(child) ? restoreReceiptDiscountHierarchy(child) : child);
400
+ const restored = {
401
+ ...source,
402
+ [childKey]: children
403
+ };
404
+ if (!Array.isArray(source.discount_list) || !source.discount_list.length) {
405
+ return restored;
406
+ }
407
+ const descendantsByMapId = new Map();
408
+ indexReceiptDiscountTargets(children, descendantsByMapId);
409
+ if (!descendantsByMapId.size) return restored;
410
+ const ownDiscounts = [];
411
+ for (const discount of source.discount_list) {
412
+ const mapId = getReceiptDiscountBundleMapId(discount);
413
+ const target = mapId ? descendantsByMapId.get(mapId) : undefined;
414
+ if (!target) {
415
+ ownDiscounts.push(discount);
416
+ continue;
417
+ }
418
+ const targetDiscounts = Array.isArray(target.discount_list) ? target.discount_list : [];
419
+ if (!targetDiscounts.some(item => isSameReceiptDiscount(item, discount))) {
420
+ target.discount_list = [...targetDiscounts, discount];
421
+ }
422
+ }
423
+ restored.discount_list = ownDiscounts;
424
+ return restored;
425
+ }
426
+ function indexReceiptDiscountTargets(nodes, targets) {
427
+ for (const node of nodes) {
428
+ if (!node || typeof node !== 'object' || Array.isArray(node)) continue;
429
+ const mapId = getReceiptBundleMapId(node);
430
+ if (mapId && !targets.has(mapId)) targets.set(mapId, node);
431
+ const children = Array.isArray(node.combinations) && node.combinations.length ? node.combinations : Array.isArray(node.product_bundle) ? node.product_bundle : [];
432
+ indexReceiptDiscountTargets(children, targets);
433
+ }
434
+ }
435
+ function normalizeReceiptId(value) {
436
+ if (value === undefined || value === null) return null;
437
+ const normalized = String(value).trim();
438
+ return normalized ? normalized : null;
439
+ }
440
+ function getReceiptBundleMapId(node) {
441
+ return normalizeReceiptId(node.metadata?.[RECEIPT_BUNDLE_MAP_ID_KEY] ?? node._id);
442
+ }
443
+ function getReceiptDiscountBundleMapId(discount) {
444
+ return normalizeReceiptId(discount?.metadata?.[RECEIPT_BUNDLE_MAP_ID_KEY]);
445
+ }
446
+ function isSameReceiptDiscount(left, right) {
447
+ const leftOrderDiscountId = normalizeReceiptId(left?.order_discount_id);
448
+ const rightOrderDiscountId = normalizeReceiptId(right?.order_discount_id);
449
+ if (leftOrderDiscountId && rightOrderDiscountId) {
450
+ return leftOrderDiscountId === rightOrderDiscountId;
451
+ }
452
+ const leftResourceId = normalizeReceiptId(left?.discount?.resource_id ?? left?.resource_id ?? left?.discount_id);
453
+ const rightResourceId = normalizeReceiptId(right?.discount?.resource_id ?? right?.resource_id ?? right?.discount_id);
454
+ if (!leftResourceId || !rightResourceId) return false;
455
+ return leftResourceId === rightResourceId && getReceiptDiscountBundleMapId(left) === getReceiptDiscountBundleMapId(right) && String(left?.amount ?? left?.value ?? left?.discount_amount ?? '') === String(right?.amount ?? right?.value ?? right?.discount_amount ?? '');
456
+ }
361
457
  function resolveProductBasePrice(product) {
362
458
  const metadata = product.metadata || {};
363
459
  const origin = product._origin || metadata.origin || {};
@@ -373,18 +469,35 @@ function normalizeProductDiscounts(params) {
373
469
  currencySymbol,
374
470
  quantity
375
471
  } = params;
376
- return normalizeArray(product.discount_list).filter(discount => {
472
+ const rows = normalizeArray(product.discount_list).filter(discount => {
377
473
  const amount = discount.amount ?? discount.value ?? discount.discount_amount;
378
474
  return isNonZero(amount);
379
475
  }).map(discount => {
380
476
  const title = resolveDiscountTitleWithPercent(discount, locale);
381
477
  const amount = discount.amount ?? discount.value ?? discount.discount_amount;
382
- const formattedAmount = formatNegativeMoney(new _decimal.default(toMoneyNumber(amount)).mul(quantity), currencySymbol);
478
+ const isMarkup = isManualMarkup(discount);
479
+ const totalAmount = new _decimal.default(toMoneyNumber(amount)).mul(quantity);
480
+ const formattedAmount = isMarkup ? formatMoney(totalAmount.abs(), currencySymbol) : formatNegativeMoney(totalAmount, currencySymbol);
383
481
  return {
384
482
  item: title,
385
- value: formattedAmount
483
+ value: formattedAmount,
484
+ isMarkup
386
485
  };
387
486
  });
487
+ return rows.sort((left, right) => Number(right.isMarkup) - Number(left.isMarkup)).map(({
488
+ isMarkup: _isMarkup,
489
+ ...row
490
+ }) => row);
491
+ }
492
+ function isManualMarkup(discount) {
493
+ if (discount.type !== 'product') return false;
494
+ if (discount.discount?.discount_type === 'change_price') return true;
495
+ const amount = discount.amount ?? discount.value ?? discount.discount_amount;
496
+ return new _decimal.default(toMoneyNumber(amount)).isNegative();
497
+ }
498
+ function hasProductDiscount(product, extensionList = []) {
499
+ const hasDiscountListAmount = normalizeArray(product.discount_list).some(discount => isNonZero(discount.amount ?? discount.value ?? discount.discount_amount));
500
+ return hasDiscountListAmount || extensionList.some(row => /^\s*-/.test(stringify(row?.value)));
388
501
  }
389
502
  function buildProductExtensionList(params) {
390
503
  const {
@@ -467,7 +580,9 @@ function resolveDiscountTitleWithPercent(discount, locale) {
467
580
  function resolveDiscountTitle(discount, locale) {
468
581
  const title = getLocalizedValue(discount.discount?.name ?? discount.discount?.title ?? discount.discount?.message ?? discount.name ?? discount.title ?? discount.message, locale);
469
582
  if (title) return title;
470
- if (discount.type === 'product') return label(locale, 'manualDiscount');
583
+ if (discount.type === 'product') {
584
+ return label(locale, isManualMarkup(discount) ? 'manualMarkup' : 'manualDiscount');
585
+ }
471
586
  return '';
472
587
  }
473
588
  function resolveProductTitle(params) {
@@ -545,12 +660,22 @@ function normalizeProductCombinations(params) {
545
660
  const optionsTotal = sumNormalizedOptionTotals(combinationsOptions, currencySymbol);
546
661
  const explicitBasePrice = firstPresentValue(bundle.base_price, bundle.metadata?.source_product_price);
547
662
  const basePrice = isPresentId(explicitBasePrice) ? explicitBasePrice : 0;
663
+ const extensionList = buildProductExtensionList({
664
+ product: bundle,
665
+ locale,
666
+ currencySymbol,
667
+ quantity,
668
+ originalPrice: formattedPrice
669
+ });
670
+ const shouldIncludeBasePrice = combinationsOptions.length > 0 || nestedCombinations.length > 0 || hasProductDiscount(bundle, extensionList);
548
671
  return {
549
672
  product_title: baseTitle,
550
673
  product_quantity: quantity,
551
674
  price: formattedPrice,
552
675
  total_selling_price: formatCalculatedMoney(new _decimal.default(toMoneyNumber(formattedPrice)).mul(quantity), currencySymbol),
553
- base_price: formatCalculatedMoney(basePrice, currencySymbol),
676
+ ...(shouldIncludeBasePrice ? {
677
+ base_price: formatCalculatedMoney(basePrice, currencySymbol)
678
+ } : {}),
554
679
  combinations_options: combinationsOptions,
555
680
  ...(combinationsOptions.length ? {
556
681
  options_total_price: optionsTotal
@@ -561,6 +686,9 @@ function normalizeProductCombinations(params) {
561
686
  ...(productNote ? {
562
687
  product_note: productNote
563
688
  } : {}),
689
+ ...(extensionList.length ? {
690
+ extension_list: extensionList
691
+ } : {}),
564
692
  ...(nestedCombinations.length ? {
565
693
  combinations: nestedCombinations
566
694
  } : {})
@@ -587,16 +715,27 @@ function normalizeExistingCombinations(combinations, locale, currencySymbol) {
587
715
  delete snapshot.product_note;
588
716
  delete snapshot.note;
589
717
  delete snapshot.combinations;
718
+ delete snapshot.discount_list;
590
719
  const quantity = toNumber(combination.product_quantity ?? combination.num ?? combination.quantity ?? 1, 1);
591
720
  const unitPrice = firstPresentValue(combination.selling_price, combination.price, combination.original_price) ?? 0;
592
721
  const optionsAmount = sumMoneyValues(normalizedOptions.map(option => option.total_price));
593
722
  const explicitBasePrice = firstPresentValue(combination.base_price);
594
723
  const basePrice = isPresentId(explicitBasePrice) ? explicitBasePrice : 0;
724
+ const extensionList = buildProductExtensionList({
725
+ product: combination,
726
+ locale,
727
+ currencySymbol,
728
+ quantity,
729
+ originalPrice: unitPrice
730
+ });
731
+ const shouldIncludeBasePrice = normalizedOptions.length > 0 || nestedCombinations.length > 0 || hasProductDiscount(combination, extensionList);
595
732
  return {
596
733
  ...snapshot,
597
734
  product_quantity: quantity,
598
735
  total_selling_price: formatCalculatedMoney(new _decimal.default(toMoneyNumber(unitPrice)).mul(quantity), currencySymbol),
599
- base_price: formatCalculatedMoney(basePrice, currencySymbol),
736
+ ...(shouldIncludeBasePrice ? {
737
+ base_price: formatCalculatedMoney(basePrice, currencySymbol)
738
+ } : {}),
600
739
  ...(Array.isArray(combination.combinations_options) ? {
601
740
  combinations_options: normalizedOptions
602
741
  } : Array.isArray(combination.options) ? {
@@ -611,6 +750,9 @@ function normalizeExistingCombinations(combinations, locale, currencySymbol) {
611
750
  ...(productNote ? {
612
751
  product_note: productNote
613
752
  } : {}),
753
+ ...(extensionList.length ? {
754
+ extension_list: extensionList
755
+ } : {}),
614
756
  ...(nestedCombinations.length ? {
615
757
  combinations: nestedCombinations
616
758
  } : {})
@@ -985,24 +1127,13 @@ function buildDelivery(order, locale) {
985
1127
  function buildAppointment(order, locale) {
986
1128
  const bookings = sortBookings(normalizeArray(order.bookings));
987
1129
  if (bookings.length) {
988
- return bookings.map(booking => {
989
- const snapshot = {
990
- ...booking
991
- };
992
- delete snapshot.product_uid;
993
- delete snapshot.booking_uid;
994
- const productUid = firstPresentValue(booking.product_uid, booking.metadata?.product_uid);
995
- const bookingUid = firstPresentValue(booking.metadata?.unique_identification_number, booking.booking_uid);
996
- return {
997
- ...snapshot,
998
- ...(isPresentId(productUid) ? {
999
- product_uid: productUid
1000
- } : {}),
1001
- ...(isPresentId(bookingUid) ? {
1002
- booking_uid: bookingUid
1003
- } : {})
1004
- };
1005
- });
1130
+ const allResources = normalizeArray(order.resources || order.resource_list);
1131
+ return bookings.flatMap(booking => buildAppointmentRows({
1132
+ booking,
1133
+ allResources,
1134
+ bookingCount: bookings.length,
1135
+ locale
1136
+ }));
1006
1137
  }
1007
1138
  const tableName = order.table_name || order.metadata?.table_name || order.metadata?.table?.name || order.form_data?.table_name;
1008
1139
  if (!tableName) return [];
@@ -1011,6 +1142,82 @@ function buildAppointment(order, locale) {
1011
1142
  value: getLocalizedValue(tableName, locale)
1012
1143
  }];
1013
1144
  }
1145
+ function buildAppointmentRows(params) {
1146
+ const {
1147
+ booking,
1148
+ allResources,
1149
+ bookingCount,
1150
+ locale
1151
+ } = params;
1152
+ const productUid = stringify(firstPresentValue(booking.product_uid, booking.metadata?.product_uid)).trim();
1153
+ const bookingUid = stringify(firstPresentValue(booking.metadata?.unique_identification_number, booking.booking_uid)).trim();
1154
+ const association = {
1155
+ product_uid: productUid,
1156
+ booking_uid: bookingUid
1157
+ };
1158
+ const bookingId = stringify(firstPresentValue(booking.booking_id, booking.schedule_event_id, bookingUid)).trim();
1159
+ const bookingTime = formatBookingRange(booking, locale);
1160
+ const resourceText = formatBookingResources(resolveBookingResourcesForReceipt(booking, allResources, bookingCount), locale);
1161
+ const holder = getLocalizedValue(booking.holder?.name ?? booking.metadata?.holder?.name, locale).trim();
1162
+ return [{
1163
+ item: label(locale, 'bookingId'),
1164
+ value: bookingId,
1165
+ ...association
1166
+ }, {
1167
+ item: label(locale, 'bookingDateTime'),
1168
+ value: bookingTime,
1169
+ ...association
1170
+ }, {
1171
+ item: label(locale, 'bookingResource'),
1172
+ value: resourceText,
1173
+ ...association
1174
+ }, {
1175
+ item: label(locale, 'bookingHolder'),
1176
+ value: holder,
1177
+ ...association
1178
+ }].filter(row => Boolean(row.value));
1179
+ }
1180
+ function formatBookingRange(booking, locale) {
1181
+ const startDate = stringify(booking.start_date);
1182
+ const startTime = stringify(booking.start_time);
1183
+ const endDate = stringify(booking.end_date || startDate);
1184
+ const endTime = stringify(booking.end_time);
1185
+ const start = firstValidBookingDate(booking.start_at, booking.start_datetime, booking.start_date_time, `${startDate} ${startTime}`.trim());
1186
+ const end = firstValidBookingDate(booking.end_at, booking.end_datetime, booking.end_date_time, endTime ? `${endDate} ${endTime}`.trim() : '');
1187
+ if (!start) {
1188
+ return [startDate, startTime, endTime ? `- ${endDate} ${endTime}` : ''].filter(Boolean).join(' ');
1189
+ }
1190
+ const dateFormat = locale === 'en' ? 'DD/MM/YYYY' : 'YYYY/MM/DD';
1191
+ const startText = start.format(`${dateFormat} HH:mm`);
1192
+ if (!end) return startText;
1193
+ return `${startText} - ${end.isSame(start, 'day') ? end.format('HH:mm') : end.format(`${dateFormat} HH:mm`)}`;
1194
+ }
1195
+ function firstValidBookingDate(...values) {
1196
+ for (const value of values) {
1197
+ if (!isPresentId(value)) continue;
1198
+ const parsed = (0, _dayjs.default)(value);
1199
+ if (parsed.isValid()) return parsed;
1200
+ }
1201
+ return null;
1202
+ }
1203
+ function resolveBookingResourcesForReceipt(booking, allResources, bookingCount) {
1204
+ const embedded = normalizeArray(booking.resources).filter(resource => Boolean(resource) && typeof resource === 'object' && !Array.isArray(resource));
1205
+ const resourceIds = new Set([booking.resource_id, booking.relation_id, ...normalizeArray(booking.resource_ids), ...normalizeArray(booking.metadata?.resource_ids)].map(value => stringify(value).trim()).filter(Boolean));
1206
+ for (const resource of embedded) {
1207
+ const id = stringify(resource.id ?? resource.resource_id ?? resource.relation_id).trim();
1208
+ if (id) resourceIds.add(id);
1209
+ }
1210
+ if (resourceIds.size) {
1211
+ const matched = allResources.filter(resource => resourceIds.has(stringify(resource.id ?? resource.resource_id ?? resource.relation_id).trim()));
1212
+ if (matched.length) return matched;
1213
+ }
1214
+ if (embedded.length) return embedded;
1215
+ if (bookingCount === 1 && allResources.length) return allResources;
1216
+ return [];
1217
+ }
1218
+ function formatBookingResources(resources, locale) {
1219
+ return resources.map(resource => [getLocalizedValue(resource.form_title || resource.metadata?.form_name || resource.relation_form_name || resource.metadata?.relation_form_name, locale), getLocalizedValue(resource.title || resource.name || resource.main_field || resource.metadata?.main_field || resource.metadata?.resource_name, locale)].filter(Boolean).join(' ')).filter(Boolean).join(', ');
1220
+ }
1014
1221
  function sortBookings(bookings) {
1015
1222
  return bookings.map((booking, index) => ({
1016
1223
  booking,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 5 | 3 | 1 | 2 | 4 | 6;
329
+ weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.10.35",
4
+ "version": "0.10.37",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",