@ticketboothapp/booking 1.2.94 → 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
|
@@ -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
|
-
|
package/src/strings/en.json
CHANGED
|
@@ -143,6 +143,7 @@
|
|
|
143
143
|
"orgPayoutMethodPlaceholder": "Select payout method",
|
|
144
144
|
"orgPayoutMethodCheque": "Cheque",
|
|
145
145
|
"orgPayoutMethodETransfer": "E-transfer",
|
|
146
|
+
"orgPayoutMethodCash": "Cash",
|
|
146
147
|
"orgPayoutPayee": "Payee",
|
|
147
148
|
"orgPayoutRecipientMode": "Recipient mode",
|
|
148
149
|
"orgPayoutNotes": "Notes",
|