@pisell/pisellos 0.10.46 → 0.10.48

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.
@@ -9,15 +9,31 @@ var _dayjs = _interopRequireDefault(require("dayjs"));
9
9
  var _decimal = _interopRequireDefault(require("decimal.js"));
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
11
  const DEFAULT_LOCALES = ['en', 'zh_CN'];
12
+ const SERVICE_TYPE_LABEL_KEYS = {
13
+ takeaway: 'takeAway',
14
+ pick_up: 'pickUp',
15
+ table_service: 'tableService',
16
+ delivery: 'delivery',
17
+ room_service: 'roomService',
18
+ dine_in: 'dineIn',
19
+ delivery_by_uber: 'deliveryByUber',
20
+ delivery_by_panda: 'deliveryByPanda',
21
+ delivery_by_merchant: 'deliveryByMerchant'
22
+ };
12
23
  const LABELS = {
13
24
  en: {
14
25
  contactName: 'Contact name',
15
26
  contactMobile: 'Contact Mobile',
16
27
  email: 'email',
17
- dineIn: 'Dine-in',
18
- takeAway: 'Take away',
28
+ dineIn: 'Dine in',
29
+ takeAway: 'Takeaway',
19
30
  delivery: 'Delivery',
20
- pickUp: 'Pick-up',
31
+ pickUp: 'Pickup',
32
+ tableService: 'Table Service',
33
+ roomService: 'Room Service',
34
+ deliveryByUber: 'Uber Eats Delivery',
35
+ deliveryByPanda: 'HungryPanda Delivery',
36
+ deliveryByMerchant: 'Merchant Delivery',
21
37
  shopService: 'Dine-in',
22
38
  pickUpTime: 'Pick-up time',
23
39
  asap: 'ASAP',
@@ -33,6 +49,7 @@ const LABELS = {
33
49
  remainingAmount: 'Remaining amount',
34
50
  redeemPoints: 'Redeem points',
35
51
  remainingPoints: 'Points balance',
52
+ entitlementRemaining: 'Remaining',
36
53
  table: 'Table',
37
54
  bookingId: 'Booking ID',
38
55
  bookingDateTime: 'Date & time',
@@ -56,7 +73,12 @@ const LABELS = {
56
73
  dineIn: '堂食',
57
74
  takeAway: '外带',
58
75
  delivery: '配送',
59
- pickUp: '自提',
76
+ pickUp: '自取',
77
+ tableService: '送餐到桌',
78
+ roomService: '客房服务',
79
+ deliveryByUber: 'Uber 配送',
80
+ deliveryByPanda: '熊猫外卖配送',
81
+ deliveryByMerchant: '商家配送',
60
82
  shopService: '堂食',
61
83
  pickUpTime: '取餐时间',
62
84
  asap: '尽快',
@@ -72,6 +94,7 @@ const LABELS = {
72
94
  remainingAmount: '剩余金额',
73
95
  redeemPoints: '本次使用积分',
74
96
  remainingPoints: '积分余额',
97
+ entitlementRemaining: '剩余次数',
75
98
  table: '桌台',
76
99
  bookingId: '预约编号',
77
100
  bookingDateTime: '日期和时间',
@@ -96,6 +119,11 @@ const LABELS = {
96
119
  takeAway: '外帶',
97
120
  delivery: '配送',
98
121
  pickUp: '自取',
122
+ tableService: '送餐到桌',
123
+ roomService: '客房服務',
124
+ deliveryByUber: 'Uber 配送',
125
+ deliveryByPanda: '熊貓外賣配送',
126
+ deliveryByMerchant: '商家配送',
99
127
  shopService: '堂食',
100
128
  pickUpTime: '取餐時間',
101
129
  asap: '盡快',
@@ -111,6 +139,7 @@ const LABELS = {
111
139
  remainingAmount: '剩餘金額',
112
140
  redeemPoints: '本次使用積分',
113
141
  remainingPoints: '積分餘額',
142
+ entitlementRemaining: '剩餘次數',
114
143
  table: '桌台',
115
144
  bookingId: '預約編號',
116
145
  bookingDateTime: '日期和時間',
@@ -135,6 +164,11 @@ const LABELS = {
135
164
  takeAway: 'テイクアウト',
136
165
  delivery: '配達',
137
166
  pickUp: '受け取り',
167
+ tableService: 'テーブルサービス',
168
+ roomService: 'ルームサービス',
169
+ deliveryByUber: 'Uber Eats 配達',
170
+ deliveryByPanda: 'HungryPanda 配達',
171
+ deliveryByMerchant: '店舗による配達',
138
172
  shopService: '店内飲食',
139
173
  pickUpTime: '受取時間',
140
174
  asap: 'できるだけ早く',
@@ -148,6 +182,7 @@ const LABELS = {
148
182
  remainingAmount: '残高',
149
183
  redeemPoints: '利用ポイント',
150
184
  remainingPoints: 'ポイント残高',
185
+ entitlementRemaining: '残り回数',
151
186
  table: 'テーブル',
152
187
  bookingId: '予約ID',
153
188
  bookingDateTime: '日時',
@@ -173,6 +208,11 @@ const LABELS = {
173
208
  takeAway: 'Para levar',
174
209
  delivery: 'Entrega',
175
210
  pickUp: 'Recolha',
211
+ tableService: 'Serviço à mesa',
212
+ roomService: 'Serviço de quarto',
213
+ deliveryByUber: 'Entrega pela Uber Eats',
214
+ deliveryByPanda: 'Entrega pela HungryPanda',
215
+ deliveryByMerchant: 'Entrega pelo comerciante',
176
216
  shopService: 'Consumo no local',
177
217
  pickUpTime: 'Hora de recolha',
178
218
  asap: 'Assim que possível',
@@ -186,6 +226,7 @@ const LABELS = {
186
226
  remainingAmount: 'Saldo restante',
187
227
  redeemPoints: 'Pontos utilizados',
188
228
  remainingPoints: 'Saldo de pontos',
229
+ entitlementRemaining: 'Utilizações restantes',
189
230
  table: 'Mesa',
190
231
  bookingId: 'ID da reserva',
191
232
  bookingDateTime: 'Data e hora',
@@ -1128,9 +1169,8 @@ function normalizeCustomerDisplayValue(value) {
1128
1169
  return text;
1129
1170
  }
1130
1171
  function buildDelivery(order, locale) {
1131
- const deliveryType = stringify(order.delivery_type).trim();
1132
- const serviceType = deliveryType || stringify(firstPresentValue(order.metadata?.service_type, order.service_type)).trim();
1133
- const serviceTypeLabelKey = resolveServiceTypeLabelKey(serviceType, order);
1172
+ const serviceType = stringify(order.metadata?.shop_service_data?.service_type).trim();
1173
+ const serviceTypeLabelKey = resolveServiceTypeLabelKey(serviceType);
1134
1174
  if (!serviceTypeLabelKey) return [];
1135
1175
  const items = [{
1136
1176
  item: '',
@@ -1392,42 +1432,241 @@ function buildWallets(params) {
1392
1432
  virtualCurrencyUnit: virtualCurrencySnapshot ? getVirtualCurrencySnapshotUnit(virtualCurrencySnapshot, params.locale) : undefined
1393
1433
  });
1394
1434
  });
1395
- const displayedWalletPassIds = collectDisplayedWalletPassIds(displayedWalletPayments);
1396
- return [...paymentWallets, ...buildVoucherAssets(params), ...buildPointCardSnapshotAssets({
1435
+ const displayedWalletAssetIdentities = collectDisplayedWalletAssetIdentities(displayedWalletPayments);
1436
+ const voucherWallets = buildVoucherAssets({
1437
+ ...params,
1438
+ displayedWalletAssetIdentities
1439
+ });
1440
+ const productDiscountWallets = buildProductDiscountAssets({
1441
+ ...params,
1442
+ displayedWalletAssetIdentities
1443
+ });
1444
+ return [...paymentWallets, ...voucherWallets, ...productDiscountWallets, ...buildPointCardSnapshotAssets({
1397
1445
  order: params.order,
1398
1446
  locale: params.locale,
1399
- displayedWalletPassIds
1447
+ displayedWalletAssetIdentities
1400
1448
  }), ...buildVirtualCurrencySnapshotAssets({
1401
1449
  snapshots: virtualCurrencySnapshots.items,
1402
1450
  order: params.order,
1403
1451
  locale: params.locale,
1404
- displayedWalletPassIds
1452
+ displayedWalletAssetIdentities
1405
1453
  })];
1406
1454
  }
1407
- function collectDisplayedWalletPassIds(payments) {
1408
- const ids = new Set();
1455
+ function collectDisplayedWalletAssetIdentities(payments) {
1456
+ const identities = [];
1409
1457
  payments.forEach(payment => {
1410
1458
  const fundRecord = getFundRecord(payment);
1411
- [payment.voucher_id, fundRecord?.voucher_id].forEach(value => {
1412
- const id = normalizeWalletPassId(value);
1413
- if (id) ids.add(id);
1459
+ const ids = Array.from(new Set([fundRecord?.voucher_id, payment.voucher_id].map(value => normalizeWalletPassId(value)).filter(value => !!value)));
1460
+ const codes = normalizeWalletAssetCodes(fundRecord?.code, fundRecord?.encoded);
1461
+ if (!ids.length) {
1462
+ registerWalletAssetIdentity(identities, {
1463
+ id: null,
1464
+ codes
1465
+ });
1466
+ return;
1467
+ }
1468
+ ids.forEach(id => {
1469
+ registerWalletAssetIdentity(identities, {
1470
+ id,
1471
+ codes
1472
+ });
1414
1473
  });
1415
1474
  });
1416
- return ids;
1475
+ return identities;
1476
+ }
1477
+ const PRODUCT_WALLET_DISCOUNT_TYPES = new Set(['good_pass', 'discount_card', 'product_discount_card', 'entitlement_pass']);
1478
+ function buildProductDiscountAssets(params) {
1479
+ const fallbackAssetTime = firstPresentValue(params.order.updated_at, params.order.created_at);
1480
+ return collectProductWalletDiscountAssets(params.order).flatMap(asset => {
1481
+ if (!claimWalletAssetIdentity(params.displayedWalletAssetIdentities, {
1482
+ id: asset.id,
1483
+ codes: asset.codes
1484
+ })) return [];
1485
+ const name = getProductWalletDiscountName(asset, params.locale);
1486
+ const assetTime = getProductWalletDiscountTime(asset) ?? fallbackAssetTime;
1487
+ const timeRow = isPresentId(assetTime) ? {
1488
+ item: formatDateTime(assetTime, params.locale),
1489
+ value: ''
1490
+ } : null;
1491
+ if (asset.type === 'entitlement_pass') {
1492
+ const remaining = getProductEntitlementBalance(asset);
1493
+ return [[{
1494
+ item: name,
1495
+ value: ''
1496
+ }, ...(remaining ? [{
1497
+ item: label(params.locale, 'entitlementRemaining'),
1498
+ value: formatEntitlementUses(remaining, params.locale)
1499
+ }] : []), ...(timeRow ? [timeRow] : [])]];
1500
+ }
1501
+ const percent = getProductWalletDiscountPercent(asset);
1502
+ if (percent) {
1503
+ return [[{
1504
+ item: appendPercentToVoucherName(name, percent),
1505
+ value: formatVoucherDiscount(percent, params.locale)
1506
+ }, ...(timeRow ? [timeRow] : [])]];
1507
+ }
1508
+ const balance = getProductWalletMoneyBalance(asset);
1509
+ return [[{
1510
+ item: name,
1511
+ value: ''
1512
+ }, ...(balance ? [{
1513
+ item: label(params.locale, 'balance'),
1514
+ value: formatMoney(balance, params.currencySymbol)
1515
+ }] : []), ...(timeRow ? [timeRow] : [])]];
1516
+ });
1517
+ }
1518
+ function collectProductWalletDiscountAssets(order) {
1519
+ const assets = [];
1520
+ const assetsById = new Map();
1521
+ normalizeArray(order.products).forEach(rawProduct => {
1522
+ if (!rawProduct || typeof rawProduct !== 'object') return;
1523
+ visitProductWalletDiscounts(restoreReceiptDiscountHierarchy(rawProduct), assets, assetsById);
1524
+ });
1525
+ return assets;
1526
+ }
1527
+ function visitProductWalletDiscounts(product, assets, assetsById) {
1528
+ normalizeArray(product.discount_list).forEach(record => {
1529
+ if (!record || typeof record !== 'object' || Array.isArray(record)) return;
1530
+ const type = getProductWalletDiscountType(record);
1531
+ if (!type) return;
1532
+ const id = getProductWalletDiscountAssetId(record);
1533
+ if (!id) return;
1534
+ const codes = getProductWalletDiscountCodes(record);
1535
+ const existing = assetsById.get(id);
1536
+ if (existing) {
1537
+ existing.records.push(record);
1538
+ existing.codes = Array.from(new Set([...existing.codes, ...codes]));
1539
+ return;
1540
+ }
1541
+ const asset = {
1542
+ id,
1543
+ type,
1544
+ codes,
1545
+ records: [record]
1546
+ };
1547
+ assetsById.set(id, asset);
1548
+ assets.push(asset);
1549
+ });
1550
+ for (const childKey of ['combinations', 'product_bundle', 'bundle']) {
1551
+ normalizeArray(product[childKey]).forEach(child => {
1552
+ if (!child || typeof child !== 'object' || Array.isArray(child)) return;
1553
+ visitProductWalletDiscounts(child, assets, assetsById);
1554
+ });
1555
+ }
1556
+ }
1557
+ function getProductWalletDiscountType(record) {
1558
+ for (const value of [record.tag, record.type, record.discount?.tag, record.discount?.type]) {
1559
+ const type = stringify(value).trim().toLowerCase();
1560
+ if (PRODUCT_WALLET_DISCOUNT_TYPES.has(type)) return type;
1561
+ }
1562
+ return null;
1563
+ }
1564
+ function getProductWalletDiscountAssetId(record) {
1565
+ for (const value of [record.discount?.resource_id, record.resource_id, record.id, record.discount_id]) {
1566
+ const id = normalizeWalletPassId(value);
1567
+ if (id && id !== '0') return id;
1568
+ }
1569
+ return null;
1570
+ }
1571
+ function getProductWalletDiscountCodes(record) {
1572
+ return normalizeWalletAssetCodes(record.code, record.encoded, record.discount?.code, record.discount?.encoded);
1573
+ }
1574
+ function getProductWalletDiscountName(asset, locale) {
1575
+ for (const record of asset.records) {
1576
+ for (const value of [record.discount?.title, record.discount?.name, record.discount?.message, record.product_name, record.format_title, record.title, record.name, record.message]) {
1577
+ const name = getLocalizedValue(value, locale).trim();
1578
+ if (name) return name;
1579
+ }
1580
+ }
1581
+ return asset.codes[0] || label(locale, 'giftCard');
1582
+ }
1583
+ function getProductWalletDiscountTime(asset) {
1584
+ for (const field of ['updated_at', 'created_at', 'collection_time']) {
1585
+ for (const record of asset.records) {
1586
+ const value = firstPresentValue(record[field], record.discount?.[field]);
1587
+ if (isPresentId(value)) return value;
1588
+ }
1589
+ }
1590
+ return undefined;
1591
+ }
1592
+ function getProductEntitlementBalance(asset) {
1593
+ for (const record of asset.records) {
1594
+ const balance = getEntitlementBalance(record.balance, record.discount?.balance);
1595
+ if (balance) return balance;
1596
+ }
1597
+ return null;
1598
+ }
1599
+ function getEntitlementBalance(...values) {
1600
+ for (const value of values) {
1601
+ if (!isNumericAmount(value)) continue;
1602
+ const balance = new _decimal.default(value);
1603
+ if (balance.isFinite() && balance.isInteger() && balance.gte(0)) {
1604
+ return balance;
1605
+ }
1606
+ }
1607
+ return null;
1608
+ }
1609
+ function formatEntitlementUses(value, locale) {
1610
+ const count = value.toFixed(0);
1611
+ switch (normalizeLocaleKey(locale)) {
1612
+ case 'zh_CN':
1613
+ case 'zh_HK':
1614
+ return `${count}次`;
1615
+ case 'ja':
1616
+ return `${count}回`;
1617
+ case 'pt':
1618
+ return `${count} ${value.eq(1) ? 'utilização' : 'utilizações'}`;
1619
+ default:
1620
+ return `${count} ${value.eq(1) ? 'use' : 'uses'}`;
1621
+ }
1622
+ }
1623
+ function getProductWalletDiscountPercent(asset) {
1624
+ if (asset.type !== 'discount_card' && asset.type !== 'product_discount_card') return null;
1625
+ for (const record of asset.records) {
1626
+ const discountType = stringify(firstPresentValue(record.discount_card_type, record.metadata?.discount_card_type, record.discount?.discount_card_type, record.discount?.metadata?.discount_card_type)).trim().toLowerCase();
1627
+ if (discountType && discountType !== 'percent' && discountType !== 'percentage') continue;
1628
+ const candidates = [record.percent, record.discount?.percent];
1629
+ if (discountType === 'percent' || discountType === 'percentage') {
1630
+ candidates.push(record.par_value, record.discount?.par_value);
1631
+ }
1632
+ for (const value of candidates) {
1633
+ if (!isNumericAmount(value)) continue;
1634
+ const percent = new _decimal.default(value);
1635
+ if (percent.isFinite() && percent.gt(0) && percent.lte(100)) {
1636
+ return percent;
1637
+ }
1638
+ }
1639
+ }
1640
+ return null;
1641
+ }
1642
+ function getProductWalletMoneyBalance(asset) {
1643
+ for (const record of asset.records) {
1644
+ for (const value of [record.balance, record.discount?.balance]) {
1645
+ if (!isNumericAmount(value)) continue;
1646
+ return _decimal.default.max(new _decimal.default(value), 0);
1647
+ }
1648
+ }
1649
+ for (const record of asset.records) {
1650
+ const parValue = firstPresentValue(record.par_value, record.discount?.par_value);
1651
+ const usedParValue = firstPresentValue(record.used_par_value, record.discount?.used_par_value);
1652
+ if (!isNumericAmount(parValue) || !isNumericAmount(usedParValue)) continue;
1653
+ return _decimal.default.max(new _decimal.default(parValue).minus(new _decimal.default(usedParValue)), 0);
1654
+ }
1655
+ return null;
1417
1656
  }
1418
1657
  function buildPointCardSnapshotAssets(params) {
1419
1658
  const snapshots = params.order.order_meta_list?.point_cards_snapshot;
1420
1659
  if (!Array.isArray(snapshots)) return [];
1421
1660
  const snapshotTime = firstPresentValue(params.order.updated_at, params.order.created_at);
1422
- const seenSnapshotIds = new Set();
1423
1661
  return snapshots.flatMap(snapshot => {
1424
1662
  if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) return [];
1425
1663
  const pointCard = snapshot;
1426
1664
  if (stringify(pointCard.tag).trim().toLowerCase() !== 'point_card') return [];
1427
- const id = normalizeWalletPassId(pointCard.id);
1428
- if (!id || seenSnapshotIds.has(id)) return [];
1429
- seenSnapshotIds.add(id);
1430
- if (params.displayedWalletPassIds.has(id)) return [];
1665
+ const assetId = normalizeWalletPassId(pointCard.id);
1666
+ if (!assetId || !claimWalletAssetIdentity(params.displayedWalletAssetIdentities, {
1667
+ id: assetId,
1668
+ codes: []
1669
+ })) return [];
1431
1670
  const rows = [{
1432
1671
  item: stringify(pointCard.product_name).trim() || label(params.locale, 'pointCard'),
1433
1672
  value: ''
@@ -1483,8 +1722,11 @@ function findVirtualCurrencySnapshotForPayment(payment, snapshotsById) {
1483
1722
  function buildVirtualCurrencySnapshotAssets(params) {
1484
1723
  const snapshotTime = firstPresentValue(params.order.updated_at, params.order.created_at);
1485
1724
  return params.snapshots.flatMap(virtualCurrency => {
1486
- const id = normalizeWalletPassId(virtualCurrency.id);
1487
- if (!id || params.displayedWalletPassIds.has(id)) return [];
1725
+ const assetId = normalizeWalletPassId(virtualCurrency.id);
1726
+ if (!assetId || !claimWalletAssetIdentity(params.displayedWalletAssetIdentities, {
1727
+ id: assetId,
1728
+ codes: []
1729
+ })) return [];
1488
1730
  const rows = [{
1489
1731
  item: stringify(virtualCurrency.product_name).trim(),
1490
1732
  value: ''
@@ -1535,6 +1777,49 @@ function normalizeWalletPassId(value) {
1535
1777
  if (typeof value !== 'string') return null;
1536
1778
  return value.trim() || null;
1537
1779
  }
1780
+ function firstNormalizedWalletAssetId(...values) {
1781
+ for (const value of values) {
1782
+ const id = normalizeWalletPassId(value);
1783
+ if (id) return id;
1784
+ }
1785
+ return null;
1786
+ }
1787
+ function normalizeWalletAssetCodes(...values) {
1788
+ return Array.from(new Set(values.map(value => normalizeWalletPassId(value)).filter(value => !!value)));
1789
+ }
1790
+ function registerWalletAssetIdentity(identities, candidate) {
1791
+ if (!candidate.id && !candidate.codes.length) return;
1792
+ const existing = identities.find(identity => isSameWalletAssetIdentity(identity, candidate));
1793
+ if (existing) {
1794
+ mergeWalletAssetIdentity(existing, candidate);
1795
+ return;
1796
+ }
1797
+ identities.push({
1798
+ id: candidate.id,
1799
+ codes: [...candidate.codes]
1800
+ });
1801
+ }
1802
+ function claimWalletAssetIdentity(identities, candidate) {
1803
+ if (!candidate.id && !candidate.codes.length) return true;
1804
+ const existing = identities.find(identity => isSameWalletAssetIdentity(identity, candidate));
1805
+ if (existing) {
1806
+ mergeWalletAssetIdentity(existing, candidate);
1807
+ return false;
1808
+ }
1809
+ identities.push({
1810
+ id: candidate.id,
1811
+ codes: [...candidate.codes]
1812
+ });
1813
+ return true;
1814
+ }
1815
+ function isSameWalletAssetIdentity(left, right) {
1816
+ if (left.id && right.id) return left.id === right.id;
1817
+ return left.codes.some(code => right.codes.includes(code));
1818
+ }
1819
+ function mergeWalletAssetIdentity(target, source) {
1820
+ if (!target.id && source.id) target.id = source.id;
1821
+ target.codes = Array.from(new Set([...target.codes, ...source.codes]));
1822
+ }
1538
1823
  function getPointCardSnapshotRemainingPoints(snapshot) {
1539
1824
  if (!isNumericAmount(snapshot.par_value) || !isNumericAmount(snapshot.used_par_value)) {
1540
1825
  return null;
@@ -1542,19 +1827,26 @@ function getPointCardSnapshotRemainingPoints(snapshot) {
1542
1827
  return _decimal.default.max(new _decimal.default(snapshot.par_value).minus(new _decimal.default(snapshot.used_par_value)), 0);
1543
1828
  }
1544
1829
  function buildVoucherAssets(params) {
1545
- const seenVoucherKeys = new Set();
1546
1830
  const fallbackAssetTime = firstPresentValue(params.order.updated_at, params.order.created_at);
1547
- return normalizeArray(params.order.vouchers).flatMap((voucher, index) => {
1831
+ return normalizeArray(params.order.vouchers).flatMap(voucher => {
1548
1832
  if (!voucher || typeof voucher !== 'object' || Array.isArray(voucher)) return [];
1549
- const voucherKey = getVoucherAssetKey(voucher, index);
1550
- if (seenVoucherKeys.has(voucherKey)) return [];
1551
- seenVoucherKeys.add(voucherKey);
1833
+ if (!claimWalletAssetIdentity(params.displayedWalletAssetIdentities, getVoucherAssetIdentity(voucher))) return [];
1552
1834
  const name = getVoucherAssetName(voucher, params.locale);
1553
1835
  const assetTime = firstPresentValue(voucher.updated_at, voucher.created_at, voucher.collection_time, fallbackAssetTime);
1554
1836
  const timeRow = isPresentId(assetTime) ? {
1555
1837
  item: formatDateTime(assetTime, params.locale),
1556
1838
  value: ''
1557
1839
  } : null;
1840
+ if (isEntitlementVoucher(voucher)) {
1841
+ const remaining = getEntitlementBalance(voucher.balance, voucher.metadata?.balance);
1842
+ return [[{
1843
+ item: name,
1844
+ value: ''
1845
+ }, ...(remaining ? [{
1846
+ item: label(params.locale, 'entitlementRemaining'),
1847
+ value: formatEntitlementUses(remaining, params.locale)
1848
+ }] : []), ...(timeRow ? [timeRow] : [])]];
1849
+ }
1558
1850
  if (isTicketVoucher(voucher)) {
1559
1851
  const validity = getVoucherValidity(voucher, params.locale);
1560
1852
  return [[{
@@ -1583,6 +1875,9 @@ function buildVoucherAssets(params) {
1583
1875
  });
1584
1876
  }
1585
1877
  const TICKET_VOUCHER_TAGS = new Set(['ticket', 'product_package_ticket', 'appointment_ticket', 'session_ticket']);
1878
+ function isEntitlementVoucher(voucher) {
1879
+ return [voucher.tag, voucher.type].some(value => stringify(value).trim().toLowerCase() === 'entitlement_pass');
1880
+ }
1586
1881
  function isTicketVoucher(voucher) {
1587
1882
  return TICKET_VOUCHER_TAGS.has(stringify(voucher.tag).trim().toLowerCase());
1588
1883
  }
@@ -1657,9 +1952,11 @@ function formatVoucherValidityDate(value, locale) {
1657
1952
  text: time ? `${time} ${date}` : date
1658
1953
  };
1659
1954
  }
1660
- function getVoucherAssetKey(voucher, index) {
1661
- const identity = firstPresentValue(voucher.voucher_id, voucher.id, voucher.code, voucher.encoded);
1662
- return identity === undefined ? `voucher-index:${index}` : `voucher:${String(identity)}`;
1955
+ function getVoucherAssetIdentity(voucher) {
1956
+ return {
1957
+ id: firstNormalizedWalletAssetId(voucher.voucher_id, voucher.id),
1958
+ codes: normalizeWalletAssetCodes(voucher.code, voucher.encoded)
1959
+ };
1663
1960
  }
1664
1961
  function getVoucherAssetName(voucher, locale) {
1665
1962
  return getLocalizedValue(voucher.product_name || voucher.name || voucher.title, locale) || stringify(voucher.encoded || voucher.code || label(locale, 'giftCard'));
@@ -1896,25 +2193,8 @@ function getLocalizedValue(value, locale) {
1896
2193
  const underscoredLocale = locale.replace('-', '_');
1897
2194
  return stringify(value[locale] ?? value[dashedLocale] ?? value[underscoredLocale] ?? value.original ?? value.auto ?? value.default ?? value.en ?? '');
1898
2195
  }
1899
- function resolveServiceTypeLabelKey(serviceType, order) {
1900
- const normalized = serviceType.trim().toLowerCase().replace(/[\s-]+/g, '_');
1901
- if (['', 'nil', 'none', 'unknown'].includes(normalized)) return null;
1902
- if (['pickup', 'pick_up', 'self_pickup'].includes(normalized)) return 'pickUp';
1903
- if (['delivery', 'shipping', 'local_delivery'].includes(normalized)) return 'delivery';
1904
- if (['takeaway', 'take_away'].includes(normalized)) return 'takeAway';
1905
- if (['dine_in', 'dinein'].includes(normalized)) return 'dineIn';
1906
- if (['shop_service', 'shop_server'].includes(normalized)) {
1907
- return resolveShopServiceLabelKey(order);
1908
- }
1909
- return null;
1910
- }
1911
- function resolveShopServiceLabelKey(order) {
1912
- 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);
1913
- if (!isPresentId(rawShopServiceType)) return 'dineIn';
1914
- const normalized = stringify(rawShopServiceType).trim().toLowerCase().replace(/[\s-]+/g, '_');
1915
- if (['takeaway', 'take_away'].includes(normalized)) return 'takeAway';
1916
- if (['dine_in', 'dinein'].includes(normalized)) return 'dineIn';
1917
- return null;
2196
+ function resolveServiceTypeLabelKey(serviceType) {
2197
+ return SERVICE_TYPE_LABEL_KEYS[serviceType] || null;
1918
2198
  }
1919
2199
  function normalizeBooleanFlag(value) {
1920
2200
  if (value === true || value === 1 || stringify(value).trim() === '1') return 1;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.10.46",
4
+ "version": "0.10.48",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",