@ticketboothapp/booking 1.2.95 → 1.2.96

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.95",
3
+ "version": "1.2.96",
4
4
  "private": false,
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -4153,47 +4153,9 @@ export function AdminChangeBookingFlow({
4153
4153
  });
4154
4154
  }, [adminCustomReceiptLines]);
4155
4155
 
4156
- /**
4157
- * Provider `/change` applies from booking item billable rows plus `pricingAdjustment`.
4158
- * For admin FE-authoritative receipts, the quote/receipt total can include an explicit tax row while the provider
4159
- * billable-row builder does not add that row on a date-only change. Send it as an automatic adjustment so
4160
- * `newTotalAmount` and the billable line sum stay in lockstep.
4161
- */
4162
- const providerReceiptTaxAdjustment = useMemo((): Array<{ label: string; amount: number }> => {
4163
- if (!isProviderDashboardChange || !useAdminFeAuthoritativeQuote) return [];
4164
- const tax = roundMoney(adminFeAuthoritativeReceipt.tax);
4165
- if (Math.abs(tax) < 0.005) return [];
4166
- const providerAlreadyHasTaxLine = providerQuotedLines.some((line) => {
4167
- const type = String(line.type ?? '').trim().toUpperCase();
4168
- const label = String(line.label ?? '').trim().toLowerCase();
4169
- return type === 'TAX' || label.includes('tax');
4170
- });
4171
- if (providerAlreadyHasTaxLine) return [];
4172
- const taxLine = adminFeAuthoritativeReceipt.lineItems.find(
4173
- (line) => String(line.type ?? '').trim().toUpperCase() === 'TAX'
4174
- );
4175
- return [
4176
- {
4177
- label: taxLine?.label?.trim() || (t('booking.tax') !== 'booking.tax' ? t('booking.tax') : 'Taxes and fees'),
4178
- amount: tax,
4179
- },
4180
- ];
4181
- }, [
4182
- isProviderDashboardChange,
4183
- useAdminFeAuthoritativeQuote,
4184
- adminFeAuthoritativeReceipt.tax,
4185
- adminFeAuthoritativeReceipt.lineItems,
4186
- providerQuotedLines,
4187
- t,
4188
- ]);
4189
-
4190
4156
  const mergedProviderAdditionalAdjustments = useMemo(
4191
- () => [
4192
- ...providerAdditionalAdjustments,
4193
- ...adminCustomLinesAsAdditionalAdjustments,
4194
- ...providerReceiptTaxAdjustment,
4195
- ],
4196
- [providerAdditionalAdjustments, adminCustomLinesAsAdditionalAdjustments, providerReceiptTaxAdjustment]
4157
+ () => [...providerAdditionalAdjustments, ...adminCustomLinesAsAdditionalAdjustments],
4158
+ [providerAdditionalAdjustments, adminCustomLinesAsAdditionalAdjustments]
4197
4159
  );
4198
4160
 
4199
4161
  const changeFlowSelectionPreview = useMemo((): ChangeFlowSelectionPreview | null => {
@@ -61,17 +61,11 @@ import {
61
61
  roundMoney,
62
62
  } from '../../lib/booking/change-flow-pricing';
63
63
  import {
64
- mergePriceSummaryLinesForDrift,
65
- mergeLineComparisonsWithFullDrift,
66
64
  normalizePricingDriftDetailFromQuote,
67
65
  normalizeTicketPricingTraceFromQuote,
68
- sumPriceSummaryLinesMajorUnits,
69
- computePricingDriftDelta,
70
66
  } from '../../lib/booking/change-booking-pricing-drift';
71
- import { ChangeBookingPricingDriftPanel } from './ChangeBookingPricingDriftPanel';
72
67
  import {
73
68
  buildChangeBookingServerPreview,
74
- mapQuoteLineItemsToPriceSummaryLines,
75
69
  } from '../../lib/booking/change-booking-server-preview';
76
70
  import { buildCheckoutBreakdown } from '../../lib/booking/checkout-breakdown';
77
71
  import type { PricingConfig, PrecomputedPricesByCategory, ItineraryDisplayStep } from '../../lib/booking-api';
@@ -3171,190 +3165,6 @@ export function ChangeBookingFlow({
3171
3165
  originalReceiptTotal: originalReceipt?.total,
3172
3166
  });
3173
3167
 
3174
- /** When quote blocks checkout, compare FE vs server lines for debugging (prefers `pricingDriftDetail` from API when sent). */
3175
- const quoteBlockedPricingDrift = useMemo(() => {
3176
- if (!suppressSelfServeCurrencyUi || latestChangeQuote?.canProceed !== false) return null;
3177
- if (!selectedAvailability || totalQuantity <= 0) return null;
3178
-
3179
- const api = latestChangeQuote.pricingDriftDetail;
3180
- const currencyForFmt = (latestChangeQuote.currency ?? currency) as Currency;
3181
-
3182
- const clientMappedFromApi = mapQuoteLineItemsToPriceSummaryLines(api?.clientLineItems);
3183
- const useBeClientLines = clientMappedFromApi.length > 0;
3184
- /**
3185
- * Checkout passes tax/discount via PriceSummary props, not always as `priceSummaryLines`. Include them here so
3186
- * drift rows and their sums align with `changeFlowNewBookingTotal` (subtotal + tax − promo).
3187
- */
3188
- const clientLinesForMerge: PriceSummaryLine[] = (() => {
3189
- if (useBeClientLines) return clientMappedFromApi;
3190
- const lines: PriceSummaryLine[] = [...checkoutPriceSummaryLines];
3191
- const hasTaxLine = lines.some(
3192
- (l) => l.kind === 'line' && String(l.type ?? '').toUpperCase() === 'TAX',
3193
- );
3194
- if (!hasTaxLine && !isTaxIncludedInPrice && Math.abs(effectiveTax) >= 0.005) {
3195
- lines.push({
3196
- kind: 'line',
3197
- label: t('booking.tax') !== 'booking.tax' ? t('booking.tax') : 'Taxes and fees',
3198
- amount: effectiveTax,
3199
- type: 'TAX',
3200
- });
3201
- }
3202
- const hasPromoSummaryLine = lines.some(
3203
- (l) =>
3204
- l.kind === 'line' &&
3205
- (/PROMO|DISCOUNT|VOUCHER|GIFT/i.test(String(l.type ?? '')) ||
3206
- (l.amount < -0.005 && /promo|discount/i.test(l.label))),
3207
- );
3208
- if (!hasPromoSummaryLine && Math.abs(effectivePromoDiscountAmount) >= 0.005) {
3209
- const trimmedPromoCode = appliedPromoCode?.trim() ?? '';
3210
- const promoLabel =
3211
- trimmedPromoCode.length > 0
3212
- ? `Promo: ${trimmedPromoCode}`
3213
- : originalReceipt?.promoLabel?.trim() || 'Discount';
3214
- lines.push({
3215
- kind: 'line',
3216
- label: promoLabel,
3217
- amount: -effectivePromoDiscountAmount,
3218
- type: 'PROMO_CODE',
3219
- });
3220
- }
3221
- return lines;
3222
- })();
3223
-
3224
- const serverMappedFromApi = mapQuoteLineItemsToPriceSummaryLines(api?.serverLineItems);
3225
- const useBeServerLines = serverMappedFromApi.length > 0;
3226
- const serverLinesForMerge = useBeServerLines
3227
- ? serverMappedFromApi
3228
- : (latestChangeQuote.serverPreview?.priceSummaryLines ?? []);
3229
-
3230
- const clientTotalForDrift =
3231
- api?.clientTotalMajorUnits != null && Number.isFinite(api.clientTotalMajorUnits)
3232
- ? api.clientTotalMajorUnits
3233
- : useBeClientLines
3234
- ? sumPriceSummaryLinesMajorUnits(clientMappedFromApi)
3235
- : changeFlowNewBookingTotal;
3236
-
3237
- let totalDelta: number | null = null;
3238
- if (api?.deltaMajorUnits != null && Number.isFinite(api.deltaMajorUnits)) {
3239
- totalDelta = roundMoney(api.deltaMajorUnits);
3240
- }
3241
-
3242
- /**
3243
- * Server “price check” total: explicit API fields → sum of BE server lines → derive from delta → receipt preview totals.
3244
- */
3245
- let serverTotalFromQuote: number | undefined =
3246
- api?.serverTotalMajorUnits != null && Number.isFinite(api.serverTotalMajorUnits)
3247
- ? api.serverTotalMajorUnits
3248
- : undefined;
3249
- if (serverTotalFromQuote == null && useBeServerLines) {
3250
- serverTotalFromQuote = sumPriceSummaryLinesMajorUnits(serverMappedFromApi);
3251
- }
3252
- if (serverTotalFromQuote == null && totalDelta != null) {
3253
- serverTotalFromQuote = roundMoney(clientTotalForDrift - totalDelta);
3254
- }
3255
- if (serverTotalFromQuote == null) {
3256
- serverTotalFromQuote =
3257
- latestChangeQuote.serverDisplay?.total ??
3258
- latestChangeQuote.serverPreview?.totalNewBooking ??
3259
- undefined;
3260
- }
3261
- if (totalDelta == null && serverTotalFromQuote != null && Number.isFinite(serverTotalFromQuote)) {
3262
- totalDelta = roundMoney(clientTotalForDrift - serverTotalFromQuote);
3263
- }
3264
-
3265
- const mergedForDrift = mergePriceSummaryLinesForDrift(clientLinesForMerge, serverLinesForMerge);
3266
- const rows =
3267
- api?.lineComparisons && api.lineComparisons.length > 0
3268
- ? mergeLineComparisonsWithFullDrift(api.lineComparisons, mergedForDrift)
3269
- : mergedForDrift;
3270
-
3271
- const receiptAnchoring = api?.receiptAnchoring;
3272
- let driftRows = rows;
3273
- if (receiptAnchoring) {
3274
- const adj = roundMoney(
3275
- receiptAnchoring.reconciledTotalMajorUnits -
3276
- receiptAnchoring.requestedCatalogLineSumMajorUnits,
3277
- );
3278
- if (Math.abs(adj) >= 0.005) {
3279
- driftRows = [
3280
- ...rows,
3281
- {
3282
- key: 'meta:receipt-anchoring',
3283
- label: 'Receipt anchoring adjustment (BE only — not included in app total)',
3284
- clientAmount: null,
3285
- serverAmount: adj,
3286
- delta: computePricingDriftDelta(null, adj),
3287
- },
3288
- ];
3289
- }
3290
- }
3291
-
3292
- const hasTotalDelta = totalDelta != null && Math.abs(totalDelta) >= 0.005;
3293
-
3294
- if (driftRows.length === 0 && !hasTotalDelta) {
3295
- return null;
3296
- }
3297
-
3298
- const usesBeLinePayload = useBeClientLines || useBeServerLines;
3299
-
3300
- const ticketCartDetail = ticketLineItemsForChangeFlowDisplay
3301
- .filter((l) => (l.qty ?? 0) > 0)
3302
- .map((line) => {
3303
- const cat = line.category?.trim().toUpperCase() ?? '';
3304
- const rate = pricingForTicketSelector.find((r) => r.category.toUpperCase() === cat);
3305
- const rawList = rate?.baseInDisplayCurrency ?? rate?.priceCAD;
3306
- const listUnit =
3307
- rawList != null && Number.isFinite(Number(rawList))
3308
- ? Number(rawList)
3309
- : line.qty > 0
3310
- ? line.itemTotal / line.qty
3311
- : 0;
3312
- return {
3313
- category: cat,
3314
- qty: line.qty,
3315
- listUnitMajor: roundMoney(listUnit),
3316
- effectiveUnitMajor: roundMoney(line.qty > 0 ? line.itemTotal / line.qty : 0),
3317
- lineTotalMajor: line.itemTotal,
3318
- };
3319
- });
3320
-
3321
- return (
3322
- <ChangeBookingPricingDriftPanel
3323
- rows={driftRows}
3324
- clientTotal={clientTotalForDrift}
3325
- serverTotal={serverTotalFromQuote}
3326
- totalDelta={totalDelta}
3327
- currency={currencyForFmt}
3328
- locale={locale}
3329
- ticketCartDetail={ticketCartDetail.length > 0 ? ticketCartDetail : undefined}
3330
- serverTicketPricingTrace={latestChangeQuote.ticketPricingTrace ?? undefined}
3331
- receiptAnchoring={receiptAnchoring}
3332
- footnote={
3333
- usesBeLinePayload
3334
- ? 'Lines use pricingDriftDetail.clientLineItems / serverLineItems when the quote includes them; totals prefer explicit major-unit fields, then sums of those lines, then the live cart / receipt preview.'
3335
- : undefined
3336
- }
3337
- />
3338
- );
3339
- }, [
3340
- suppressSelfServeCurrencyUi,
3341
- latestChangeQuote,
3342
- selectedAvailability,
3343
- totalQuantity,
3344
- checkoutPriceSummaryLines,
3345
- changeFlowNewBookingTotal,
3346
- currency,
3347
- locale,
3348
- ticketLineItemsForChangeFlowDisplay,
3349
- pricingForTicketSelector,
3350
- isTaxIncludedInPrice,
3351
- effectiveTax,
3352
- effectivePromoDiscountAmount,
3353
- appliedPromoCode,
3354
- originalReceipt?.promoLabel,
3355
- t,
3356
- ]);
3357
-
3358
3168
  /** Replaces PriceSummary with non-numeric status until quote returns authoritative totals (no FE dollar amounts). */
3359
3169
  const selfServeCheckoutPlaceholder = useMemo(() => {
3360
3170
  if (!suppressSelfServeCurrencyUi || !selectedAvailability || totalQuantity <= 0) return undefined;
@@ -3377,7 +3187,6 @@ export function ChangeBookingFlow({
3377
3187
  return (
3378
3188
  <div className="rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-950">
3379
3189
  <div>{latestChangeQuote.reasonIfBlocked ?? 'This booking change is not available.'}</div>
3380
- {quoteBlockedPricingDrift}
3381
3190
  </div>
3382
3191
  );
3383
3192
  }
@@ -3394,7 +3203,6 @@ export function ChangeBookingFlow({
3394
3203
  changeQuoteLoading,
3395
3204
  changeQuoteFetchError,
3396
3205
  latestChangeQuote,
3397
- quoteBlockedPricingDrift,
3398
3206
  t,
3399
3207
  ]);
3400
3208
 
@@ -5058,4 +4866,3 @@ export function ChangeBookingFlow({
5058
4866
  </div>
5059
4867
  );
5060
4868
  }
5061
-