@ticketboothapp/booking 1.2.85 → 1.2.87

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.85",
3
+ "version": "1.2.87",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -142,6 +142,41 @@ function omitZeroAmountPromoDiscountSummaryLines(lines: PriceSummaryLine[]): Pri
142
142
  });
143
143
  }
144
144
 
145
+ /**
146
+ * `serverPreview.priceSummaryLines` tracks the last quote response; ticket row qty can lag the picker until debounced quote
147
+ * completes. Align ticket rows to live {@link quantities} and rescale line total proportionally (same idea as admin
148
+ * `mapSummaryLinesToFeReceiptLineItems`); tax-included reconcile then aligns euros to display total.
149
+ */
150
+ function resolveTicketQtyFromQuantities(
151
+ category: string,
152
+ quantities: Record<string, number>,
153
+ ): number | undefined {
154
+ const c = category.trim();
155
+ if (Object.prototype.hasOwnProperty.call(quantities, c)) return quantities[c];
156
+ const up = c.toUpperCase();
157
+ for (const [key, val] of Object.entries(quantities)) {
158
+ if (key.toUpperCase() === up) return val;
159
+ }
160
+ return undefined;
161
+ }
162
+
163
+ function mergePickerTicketQtyIntoPriceSummaryLines(
164
+ lines: PriceSummaryLine[],
165
+ quantities: Record<string, number>,
166
+ ): PriceSummaryLine[] {
167
+ return lines.map((line) => {
168
+ if (line.kind !== 'ticket') return line;
169
+ const uiQty = resolveTicketQtyFromQuantities(line.category, quantities);
170
+ const lineQty = Math.max(0, Number(line.qty) || 0);
171
+ const effectiveQty = uiQty != null && uiQty >= 0 ? Math.round(uiQty) : lineQty;
172
+ let itemTotal = roundMoney(line.itemTotal);
173
+ if (lineQty > 0 && effectiveQty !== lineQty) {
174
+ itemTotal = roundMoney((line.itemTotal * effectiveQty) / lineQty);
175
+ }
176
+ return { ...line, qty: Math.max(0, effectiveQty), itemTotal };
177
+ });
178
+ }
179
+
145
180
  function formatTicketLineItemsForSummary(lines: Array<{ category: string; qty: number }>): string {
146
181
  const labels: Record<string, string> = {
147
182
  ADULT: 'adult',
@@ -2963,7 +2998,10 @@ export function ChangeBookingFlow({
2963
2998
  let raw: PriceSummaryLine[];
2964
2999
  if (suppressSelfServeCurrencyUi && selfServePricingConfirmed) {
2965
3000
  const serverLines = latestChangeQuote?.serverPreview?.priceSummaryLines;
2966
- raw = serverLines && serverLines.length > 0 ? serverLines : checkoutPriceSummaryLines;
3001
+ raw =
3002
+ serverLines && serverLines.length > 0
3003
+ ? mergePickerTicketQtyIntoPriceSummaryLines(serverLines, quantities)
3004
+ : checkoutPriceSummaryLines;
2967
3005
  } else {
2968
3006
  raw = checkoutPriceSummaryLines;
2969
3007
  }
@@ -2973,6 +3011,7 @@ export function ChangeBookingFlow({
2973
3011
  selfServePricingConfirmed,
2974
3012
  checkoutPriceSummaryLines,
2975
3013
  latestChangeQuote?.serverPreview?.priceSummaryLines,
3014
+ quantities,
2976
3015
  ]);
2977
3016
 
2978
3017
  /** Receipt/server lines already include {@link PriceSummary}'s TAX row — do not also pass `taxAmount` or it duplicates. */
@@ -3536,19 +3575,15 @@ export function ChangeBookingFlow({
3536
3575
  const displayChangeFlowSubtotal = displayedChangeAmounts.subtotal;
3537
3576
  const displayChangeFlowTax = displayedChangeAmounts.tax;
3538
3577
 
3539
- /** When quote is confirmed but BE sends no `priceSummaryLines`, we still show FE-built lines while total is quote-driven — reconcile ticket amounts for tax-included currencies. */
3540
- const selfServeSummaryUsesServerLines =
3541
- suppressSelfServeCurrencyUi &&
3542
- selfServePricingConfirmed &&
3543
- (latestChangeQuote?.serverPreview?.priceSummaryLines?.length ?? 0) > 0;
3544
-
3578
+ /**
3579
+ * Tax-included: scale ticket row $ to match quote/display total. We **always** reconcile after lines are chosen
3580
+ * (including when lines come from `serverPreview.priceSummaryLines`) — server ticket row amounts can still disagree
3581
+ * with `serverDisplay.total` on EUR inclusive pricing.
3582
+ */
3545
3583
  const taxIncludedSelfServeReconciledPriceSummaryLines = useMemo(() => {
3546
3584
  if (!isTaxIncludedInPrice || !originalReceipt || !isCustomerSelfServeChange) {
3547
3585
  return checkoutPriceSummaryLinesForCheckout;
3548
3586
  }
3549
- if (selfServeSummaryUsesServerLines) {
3550
- return checkoutPriceSummaryLinesForCheckout;
3551
- }
3552
3587
  return reconcileTaxIncludedChangeFlowTicketLines(
3553
3588
  checkoutPriceSummaryLinesForCheckout,
3554
3589
  displayChangeFlowProposedTotal,
@@ -3558,7 +3593,6 @@ export function ChangeBookingFlow({
3558
3593
  isTaxIncludedInPrice,
3559
3594
  originalReceipt,
3560
3595
  isCustomerSelfServeChange,
3561
- selfServeSummaryUsesServerLines,
3562
3596
  checkoutPriceSummaryLinesForCheckout,
3563
3597
  displayChangeFlowProposedTotal,
3564
3598
  effectivePromoDiscountAmount,