@ticketboothapp/booking 1.2.146 → 1.2.148

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ticketboothapp/booking",
3
- "version": "1.2.146",
3
+ "version": "1.2.148",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -969,18 +969,12 @@ export function AdminChangeBookingFlow({
969
969
  receiptTax: adminFeAuthoritativeReceipt.tax,
970
970
  receiptTotal: adminFeAuthoritativeReceipt.total,
971
971
  originalReceipt,
972
- serverAmendmentLines:
973
- latestChangeQuote?.pricingVersion === 'booking-amendment-v1'
974
- ? latestChangeQuote.serverPreview?.priceSummaryLines ?? []
975
- : null,
976
- serverAmountDue:
977
- latestChangeQuote?.pricingVersion === 'booking-amendment-v1'
978
- ? latestChangeQuote.serverPreview?.amountDue ?? null
979
- : null,
980
- serverUpdatedTotal:
981
- latestChangeQuote?.pricingVersion === 'booking-amendment-v1'
982
- ? latestChangeQuote.serverPreview?.totalNewBooking ?? null
983
- : null,
972
+ // This flow is fed by the dedicated admin V2 quote endpoint. If it produced a
973
+ // normalized server preview, render it; do not discard valid data because an
974
+ // optional/versioned metadata string is missing or renamed.
975
+ serverAmendmentLines: latestChangeQuote?.serverPreview?.priceSummaryLines ?? null,
976
+ serverAmountDue: latestChangeQuote?.serverPreview?.amountDue ?? null,
977
+ serverUpdatedTotal: latestChangeQuote?.serverPreview?.totalNewBooking ?? null,
984
978
  serverQuoteError: changeQuoteFetchError,
985
979
  ...{ priceSummaryLinesIncludeTaxRow, isTaxIncludedInPrice, showProviderPricingInlineEditor },
986
980
  taxRate: pricingConfig?.taxRate,
@@ -61,6 +61,33 @@ export function AdminChangeReceiptComparison({
61
61
  const existingLines = originalLines(originalReceipt);
62
62
  const originalCurrency = originalReceipt.currency ?? currency;
63
63
  const quoteReady = amendmentLines != null && amountDue != null && updatedTotal != null;
64
+ const amendmentTax = amendmentLines?.reduce(
65
+ (sum, line) =>
66
+ line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'
67
+ ? sum + line.amount
68
+ : sum,
69
+ 0,
70
+ ) ?? 0;
71
+ const amendmentNonTaxLines = amendmentLines
72
+ ? [
73
+ ...amendmentLines.filter((line) => line.kind === 'ticket'),
74
+ ...amendmentLines.filter(
75
+ (line) => line.kind === 'line' && String(line.type ?? '').toUpperCase() !== 'TAX',
76
+ ),
77
+ ]
78
+ : [];
79
+ const amendmentSubtotal = amendmentNonTaxLines.reduce(
80
+ (sum, line) => sum + (line.kind === 'ticket' ? line.itemTotal : line.amount),
81
+ 0,
82
+ );
83
+ const amendmentDisplayLines: PriceSummaryLine[] = amendmentLines
84
+ ? [
85
+ ...amendmentNonTaxLines,
86
+ ...(Math.abs(amendmentTax) >= 0.005
87
+ ? [{ kind: 'line' as const, label: 'Additional tax', amount: amendmentTax, type: 'TAX' }]
88
+ : []),
89
+ ]
90
+ : [];
64
91
  const amountDueClass =
65
92
  amountDue != null && amountDue < -0.005
66
93
  ? 'text-emerald-700'
@@ -114,16 +141,17 @@ export function AdminChangeReceiptComparison({
114
141
  <div className="rounded-md border border-dashed border-stone-300 bg-white/70 px-3 py-4 text-center">
115
142
  <p className="text-sm font-medium text-stone-700">Waiting for server price…</p>
116
143
  </div>
117
- ) : amendmentLines.length === 0 && Math.abs(amountDue) < 0.005 ? (
144
+ ) : amendmentDisplayLines.length === 0 && Math.abs(amountDue) < 0.005 ? (
118
145
  <div className="rounded-md border border-dashed border-stone-300 bg-white/70 px-3 py-4 text-center">
119
146
  <p className="text-sm font-medium text-stone-700">No pricing changes</p>
120
147
  </div>
121
148
  ) : (
122
149
  <PriceSummary
123
- lines={amendmentLines}
150
+ lines={amendmentDisplayLines}
124
151
  total={amountDue}
125
152
  currency={currency}
126
153
  locale={displayLocale}
154
+ subtotal={amendmentSubtotal}
127
155
  size="sm"
128
156
  t={t}
129
157
  />
@@ -132,6 +132,19 @@ function breakdownFromPriceBasis(priceBasis: PriceBasisSnapshot | null | undefin
132
132
  };
133
133
  }
134
134
 
135
+ function finalUnitOnlyBreakdown(itemTotal: number, quantity: number) {
136
+ const finalUnitAmount = quantity > 0 ? roundMoney(itemTotal / quantity) : roundMoney(itemTotal);
137
+ return {
138
+ lineItems: [],
139
+ subtotalAfterAdjustments: finalUnitAmount,
140
+ feeLines: [],
141
+ taxRate: 0,
142
+ taxAmount: 0,
143
+ isTaxIncluded: false,
144
+ finalPrice: finalUnitAmount,
145
+ };
146
+ }
147
+
135
148
  function hasPaymentCreditLine(lines: PriceSummaryLine[]): boolean {
136
149
  return lines.some((line) => {
137
150
  if (line.kind !== 'line') return false;
@@ -193,7 +206,8 @@ export function mapQuoteLineItemsToPriceSummaryLines(
193
206
  category,
194
207
  qty: qty > 0 ? qty : 1,
195
208
  itemTotal: amount,
196
- breakdown: breakdownFromPriceBasis(item.priceBasis),
209
+ breakdown:
210
+ breakdownFromPriceBasis(item.priceBasis) ?? finalUnitOnlyBreakdown(amount, qty > 0 ? qty : 1),
197
211
  });
198
212
  continue;
199
213
  }
@@ -213,7 +227,8 @@ export function mapQuoteLineItemsToPriceSummaryLines(
213
227
  category: lettersOnly,
214
228
  qty,
215
229
  itemTotal: amount,
216
- breakdown: breakdownFromPriceBasis(item.priceBasis),
230
+ breakdown:
231
+ breakdownFromPriceBasis(item.priceBasis) ?? finalUnitOnlyBreakdown(amount, qty),
217
232
  });
218
233
  continue;
219
234
  }