@ticketboothapp/booking 1.2.84 → 1.2.86

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.84",
3
+ "version": "1.2.86",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -3872,6 +3872,31 @@ export function AdminChangeBookingFlow({
3872
3872
  effectivePromoDiscountAmount,
3873
3873
  ]);
3874
3874
 
3875
+ /** Stripe modal / admin pay modal must use the same ticket row amounts as PriceSummary; unreconciled catalog lines caused ADULT € vs total mismatch (tax-included). PI `buildCheckoutBreakdown` stays on catalog ticket rows. */
3876
+ const checkoutModalTicketLinesDisplay = useMemo((): CheckoutModalLineItem[] => {
3877
+ return taxIncludedReconciledCheckoutPriceSummaryLines
3878
+ .filter((l): l is Extract<PriceSummaryLine, { kind: 'ticket' }> => l.kind === 'ticket')
3879
+ .map((line) => {
3880
+ const rate = pricing.find((r) => r.category === line.category);
3881
+ const breakdown = getPriceBreakdown(
3882
+ line.category,
3883
+ rate?.priceCAD ?? 0,
3884
+ rate?.baseInDisplayCurrency,
3885
+ rate?.appliedAdjustments ?? [],
3886
+ );
3887
+ const qty = Math.max(0, line.qty);
3888
+ return {
3889
+ line: {
3890
+ category: line.category,
3891
+ qty,
3892
+ itemTotal: line.itemTotal,
3893
+ pricePerUnit: qty > 0 ? roundMoney(line.itemTotal / qty) : 0,
3894
+ },
3895
+ breakdown,
3896
+ };
3897
+ });
3898
+ }, [taxIncludedReconciledCheckoutPriceSummaryLines, pricing, getPriceBreakdown]);
3899
+
3875
3900
  const adminFeAuthoritativeReceipt = useMemo((): AdminFeAuthoritativeReceipt => {
3876
3901
  const hasTaxLine = taxIncludedReconciledCheckoutPriceSummaryLines.some(
3877
3902
  (line) => line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'
@@ -5207,16 +5232,7 @@ export function AdminChangeBookingFlow({
5207
5232
  availabilityProductOptionId,
5208
5233
  itineraryDisplay: itineraryDisplay ?? undefined,
5209
5234
  clientSecret: paymentIntent.clientSecret ?? '',
5210
- ticketLinesForModal: ticketLineItemsForChangeFlowDisplay.map((line) => {
5211
- const rate = pricing.find((r) => r.category === line.category);
5212
- const breakdown = getPriceBreakdown(
5213
- line.category,
5214
- rate?.priceCAD ?? 0,
5215
- rate?.baseInDisplayCurrency,
5216
- rate?.appliedAdjustments ?? []
5217
- );
5218
- return { line, breakdown };
5219
- }),
5235
+ ticketLinesForModal: checkoutModalTicketLinesDisplay,
5220
5236
  feeLineItems: feeLineItemsWithAddOns,
5221
5237
  returnPriceAdjustment: checkoutReturnLineAmount,
5222
5238
  cancellationPolicyFee,
@@ -5234,17 +5250,6 @@ export function AdminChangeBookingFlow({
5234
5250
  return;
5235
5251
  }
5236
5252
 
5237
- const ticketLinesForModal: CheckoutModalLineItem[] = ticketLineItemsForChangeFlowDisplay.map((line) => {
5238
- const rate = pricing.find((r) => r.category === line.category);
5239
- const breakdown = getPriceBreakdown(
5240
- line.category,
5241
- rate?.priceCAD ?? 0,
5242
- rate?.baseInDisplayCurrency,
5243
- rate?.appliedAdjustments ?? []
5244
- );
5245
- return { line, breakdown };
5246
- });
5247
-
5248
5253
  setCheckoutClientSecret(paymentIntent.clientSecret ?? '');
5249
5254
  setCheckoutModalData({
5250
5255
  reservationReference: changeBookingReferenceForPaidFlow ?? '',
@@ -5277,7 +5282,7 @@ export function AdminChangeBookingFlow({
5277
5282
  return `${origin}/manage-booking?ref=${ref}&lastName=${ln}&${fromQ}${intentQ}`;
5278
5283
  })()
5279
5284
  : undefined,
5280
- ticketLines: ticketLinesForModal,
5285
+ ticketLines: checkoutModalTicketLinesDisplay,
5281
5286
  feeLineItems: feeLineItemsWithAddOns,
5282
5287
  returnPriceAdjustment: checkoutReturnLineAmount,
5283
5288
  cancellationPolicyFee,
@@ -3536,19 +3536,15 @@ export function ChangeBookingFlow({
3536
3536
  const displayChangeFlowSubtotal = displayedChangeAmounts.subtotal;
3537
3537
  const displayChangeFlowTax = displayedChangeAmounts.tax;
3538
3538
 
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
-
3539
+ /**
3540
+ * Tax-included: scale ticket row $ to match quote/display total. We **always** reconcile after lines are chosen
3541
+ * (including when lines come from `serverPreview.priceSummaryLines`) — server ticket row amounts can still disagree
3542
+ * with `serverDisplay.total` on EUR inclusive pricing.
3543
+ */
3545
3544
  const taxIncludedSelfServeReconciledPriceSummaryLines = useMemo(() => {
3546
3545
  if (!isTaxIncludedInPrice || !originalReceipt || !isCustomerSelfServeChange) {
3547
3546
  return checkoutPriceSummaryLinesForCheckout;
3548
3547
  }
3549
- if (selfServeSummaryUsesServerLines) {
3550
- return checkoutPriceSummaryLinesForCheckout;
3551
- }
3552
3548
  return reconcileTaxIncludedChangeFlowTicketLines(
3553
3549
  checkoutPriceSummaryLinesForCheckout,
3554
3550
  displayChangeFlowProposedTotal,
@@ -3558,12 +3554,35 @@ export function ChangeBookingFlow({
3558
3554
  isTaxIncludedInPrice,
3559
3555
  originalReceipt,
3560
3556
  isCustomerSelfServeChange,
3561
- selfServeSummaryUsesServerLines,
3562
3557
  checkoutPriceSummaryLinesForCheckout,
3563
3558
  displayChangeFlowProposedTotal,
3564
3559
  effectivePromoDiscountAmount,
3565
3560
  ]);
3566
3561
 
3562
+ const checkoutModalTicketLinesDisplay = useMemo((): CheckoutModalLineItem[] => {
3563
+ return taxIncludedSelfServeReconciledPriceSummaryLines
3564
+ .filter((l): l is Extract<PriceSummaryLine, { kind: 'ticket' }> => l.kind === 'ticket')
3565
+ .map((line) => {
3566
+ const rate = pricing.find((r) => r.category === line.category);
3567
+ const breakdown = getPriceBreakdown(
3568
+ line.category,
3569
+ rate?.priceCAD ?? 0,
3570
+ rate?.baseInDisplayCurrency,
3571
+ rate?.appliedAdjustments ?? [],
3572
+ );
3573
+ const qty = Math.max(0, line.qty);
3574
+ return {
3575
+ line: {
3576
+ category: line.category,
3577
+ qty,
3578
+ itemTotal: line.itemTotal,
3579
+ pricePerUnit: qty > 0 ? roundMoney(line.itemTotal / qty) : 0,
3580
+ },
3581
+ breakdown,
3582
+ };
3583
+ });
3584
+ }, [taxIncludedSelfServeReconciledPriceSummaryLines, pricing, getPriceBreakdown]);
3585
+
3567
3586
  const changeFlowClientEstimateDue = (() => {
3568
3587
  if (!originalReceipt) return totalPrice;
3569
3588
  // Customer self-serve: amount due comes from POST .../change/quote (`amountDueCents` / priceDiff), not FE delta math.
@@ -4552,17 +4571,6 @@ export function ChangeBookingFlow({
4552
4571
  })()
4553
4572
  );
4554
4573
 
4555
- const ticketLinesForModal: CheckoutModalLineItem[] = ticketLineItemsForChangeFlowDisplay.map((line) => {
4556
- const rate = pricing.find((r) => r.category === line.category);
4557
- const breakdown = getPriceBreakdown(
4558
- line.category,
4559
- rate?.priceCAD ?? 0,
4560
- rate?.baseInDisplayCurrency,
4561
- rate?.appliedAdjustments ?? []
4562
- );
4563
- return { line, breakdown };
4564
- });
4565
-
4566
4574
  setCheckoutClientSecret(paymentIntent.clientSecret ?? '');
4567
4575
  setCheckoutModalData({
4568
4576
  reservationReference: changeBookingReferenceForPaidFlow ?? '',
@@ -4586,7 +4594,7 @@ export function ChangeBookingFlow({
4586
4594
  return `${origin}/manage-booking?ref=${ref}&lastName=${ln}&${fromQ}${intentQ}`;
4587
4595
  })()
4588
4596
  : undefined,
4589
- ticketLines: ticketLinesForModal,
4597
+ ticketLines: checkoutModalTicketLinesDisplay,
4590
4598
  feeLineItems: feeLineItemsWithAddOns,
4591
4599
  returnPriceAdjustment: checkoutReturnLineAmount,
4592
4600
  cancellationPolicyFee,