@ticketboothapp/booking 1.2.83 → 1.2.85
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
|
@@ -152,14 +152,39 @@ function omitZeroAmountPromoDiscountSummaryLines(lines: PriceSummaryLine[]): Pri
|
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
function
|
|
155
|
+
function resolveTicketQtyFromQuantities(
|
|
156
|
+
category: string,
|
|
157
|
+
quantities: Record<string, number>,
|
|
158
|
+
): number | undefined {
|
|
159
|
+
const c = category.trim();
|
|
160
|
+
if (Object.prototype.hasOwnProperty.call(quantities, c)) return quantities[c];
|
|
161
|
+
const up = c.toUpperCase();
|
|
162
|
+
for (const [key, val] of Object.entries(quantities)) {
|
|
163
|
+
if (key.toUpperCase() === up) return val;
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Receipt TICKET rows sent on admin quote must follow picker {@link quantities}: BE apply uses these lines for headcount when feReceipt is authoritative — server `priceSummaryLines` can lag counts. */
|
|
169
|
+
function mapSummaryLinesToFeReceiptLineItems(
|
|
170
|
+
lines: PriceSummaryLine[],
|
|
171
|
+
quantities: Record<string, number>,
|
|
172
|
+
): NonNullable<AdminFeAuthoritativeReceipt['lineItems']> {
|
|
156
173
|
return lines.map((line) => {
|
|
157
174
|
if (line.kind === 'ticket') {
|
|
175
|
+
const uiQty = resolveTicketQtyFromQuantities(line.category, quantities);
|
|
176
|
+
const lineQty = Math.max(0, line.qty);
|
|
177
|
+
const effectiveQty =
|
|
178
|
+
uiQty != null && uiQty >= 0 ? Math.round(uiQty) : lineQty;
|
|
179
|
+
let amount = roundMoney(line.itemTotal);
|
|
180
|
+
if (lineQty > 0 && effectiveQty !== lineQty) {
|
|
181
|
+
amount = roundMoney((line.itemTotal * effectiveQty) / lineQty);
|
|
182
|
+
}
|
|
158
183
|
return {
|
|
159
184
|
label: line.category,
|
|
160
|
-
amount
|
|
185
|
+
amount,
|
|
161
186
|
type: 'TICKET',
|
|
162
|
-
quantity:
|
|
187
|
+
quantity: Math.max(0, effectiveQty),
|
|
163
188
|
};
|
|
164
189
|
}
|
|
165
190
|
const normalizedType = String(line.type ?? '').trim().toUpperCase();
|
|
@@ -3828,7 +3853,7 @@ export function AdminChangeBookingFlow({
|
|
|
3828
3853
|
const displayChangeFlowProposedTotalWithEditableLines = roundMoney(
|
|
3829
3854
|
displayChangeFlowProposedTotal + editableSummaryPreSubtotalDelta
|
|
3830
3855
|
);
|
|
3831
|
-
/** Tax-included
|
|
3856
|
+
/** Tax-included: scale ticket row $ on the PriceSummary so ADULT lines match the footer total (quote/display). Payment breakdown still uses {@link ticketLineItemsForChangeFlowDisplay} — it must reconcile to amount-due, not full new-booking total. */
|
|
3832
3857
|
const taxIncludedReconciledCheckoutPriceSummaryLines = useMemo(() => {
|
|
3833
3858
|
if (!isTaxIncludedInPrice || !originalReceipt || showProviderPricingInlineEditor) {
|
|
3834
3859
|
return editableCheckoutPriceSummaryLines;
|
|
@@ -3847,11 +3872,39 @@ export function AdminChangeBookingFlow({
|
|
|
3847
3872
|
effectivePromoDiscountAmount,
|
|
3848
3873
|
]);
|
|
3849
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
|
+
|
|
3850
3900
|
const adminFeAuthoritativeReceipt = useMemo((): AdminFeAuthoritativeReceipt => {
|
|
3851
3901
|
const hasTaxLine = taxIncludedReconciledCheckoutPriceSummaryLines.some(
|
|
3852
3902
|
(line) => line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'
|
|
3853
3903
|
);
|
|
3854
|
-
const lineItems = mapSummaryLinesToFeReceiptLineItems(
|
|
3904
|
+
const lineItems = mapSummaryLinesToFeReceiptLineItems(
|
|
3905
|
+
taxIncludedReconciledCheckoutPriceSummaryLines,
|
|
3906
|
+
quantities,
|
|
3907
|
+
);
|
|
3855
3908
|
if (!hasTaxLine && Math.abs(displayChangeFlowTax) >= 0.0005) {
|
|
3856
3909
|
lineItems.push({
|
|
3857
3910
|
label: t('booking.tax') !== 'booking.tax' ? t('booking.tax') : 'Taxes and fees',
|
|
@@ -3875,6 +3928,7 @@ export function AdminChangeBookingFlow({
|
|
|
3875
3928
|
};
|
|
3876
3929
|
}, [
|
|
3877
3930
|
taxIncludedReconciledCheckoutPriceSummaryLines,
|
|
3931
|
+
quantities,
|
|
3878
3932
|
displayChangeFlowTax,
|
|
3879
3933
|
displayChangeFlowSubtotal,
|
|
3880
3934
|
editableSummaryPreSubtotalDelta,
|
|
@@ -5034,11 +5088,8 @@ export function AdminChangeBookingFlow({
|
|
|
5034
5088
|
}),
|
|
5035
5089
|
)
|
|
5036
5090
|
: totalPrice;
|
|
5037
|
-
const ticketRowsForCheckoutBreakdown = taxIncludedReconciledCheckoutPriceSummaryLines.filter(
|
|
5038
|
-
(l): l is Extract<PriceSummaryLine, { kind: 'ticket' }> => l.kind === 'ticket',
|
|
5039
|
-
);
|
|
5040
5091
|
const lines = [
|
|
5041
|
-
...
|
|
5092
|
+
...ticketLineItemsForChangeFlowDisplay.map((line) => ({
|
|
5042
5093
|
label: line.category,
|
|
5043
5094
|
amount: line.itemTotal,
|
|
5044
5095
|
type: 'TICKET' as const,
|
|
@@ -5181,25 +5232,7 @@ export function AdminChangeBookingFlow({
|
|
|
5181
5232
|
availabilityProductOptionId,
|
|
5182
5233
|
itineraryDisplay: itineraryDisplay ?? undefined,
|
|
5183
5234
|
clientSecret: paymentIntent.clientSecret ?? '',
|
|
5184
|
-
ticketLinesForModal:
|
|
5185
|
-
const rate = pricing.find((r) => r.category === line.category);
|
|
5186
|
-
const breakdown = getPriceBreakdown(
|
|
5187
|
-
line.category,
|
|
5188
|
-
rate?.priceCAD ?? 0,
|
|
5189
|
-
rate?.baseInDisplayCurrency,
|
|
5190
|
-
rate?.appliedAdjustments ?? []
|
|
5191
|
-
);
|
|
5192
|
-
const qty = Math.max(0, line.qty);
|
|
5193
|
-
return {
|
|
5194
|
-
line: {
|
|
5195
|
-
category: line.category,
|
|
5196
|
-
qty,
|
|
5197
|
-
itemTotal: line.itemTotal,
|
|
5198
|
-
pricePerUnit: qty > 0 ? roundMoney(line.itemTotal / qty) : 0,
|
|
5199
|
-
},
|
|
5200
|
-
breakdown,
|
|
5201
|
-
};
|
|
5202
|
-
}),
|
|
5235
|
+
ticketLinesForModal: checkoutModalTicketLinesDisplay,
|
|
5203
5236
|
feeLineItems: feeLineItemsWithAddOns,
|
|
5204
5237
|
returnPriceAdjustment: checkoutReturnLineAmount,
|
|
5205
5238
|
cancellationPolicyFee,
|
|
@@ -5217,26 +5250,6 @@ export function AdminChangeBookingFlow({
|
|
|
5217
5250
|
return;
|
|
5218
5251
|
}
|
|
5219
5252
|
|
|
5220
|
-
const ticketLinesForModal: CheckoutModalLineItem[] = ticketRowsForCheckoutBreakdown.map((line) => {
|
|
5221
|
-
const rate = pricing.find((r) => r.category === line.category);
|
|
5222
|
-
const breakdown = getPriceBreakdown(
|
|
5223
|
-
line.category,
|
|
5224
|
-
rate?.priceCAD ?? 0,
|
|
5225
|
-
rate?.baseInDisplayCurrency,
|
|
5226
|
-
rate?.appliedAdjustments ?? []
|
|
5227
|
-
);
|
|
5228
|
-
const qty = Math.max(0, line.qty);
|
|
5229
|
-
return {
|
|
5230
|
-
line: {
|
|
5231
|
-
category: line.category,
|
|
5232
|
-
qty,
|
|
5233
|
-
itemTotal: line.itemTotal,
|
|
5234
|
-
pricePerUnit: qty > 0 ? roundMoney(line.itemTotal / qty) : 0,
|
|
5235
|
-
},
|
|
5236
|
-
breakdown,
|
|
5237
|
-
};
|
|
5238
|
-
});
|
|
5239
|
-
|
|
5240
5253
|
setCheckoutClientSecret(paymentIntent.clientSecret ?? '');
|
|
5241
5254
|
setCheckoutModalData({
|
|
5242
5255
|
reservationReference: changeBookingReferenceForPaidFlow ?? '',
|
|
@@ -5269,7 +5282,7 @@ export function AdminChangeBookingFlow({
|
|
|
5269
5282
|
return `${origin}/manage-booking?ref=${ref}&lastName=${ln}&${fromQ}${intentQ}`;
|
|
5270
5283
|
})()
|
|
5271
5284
|
: undefined,
|
|
5272
|
-
ticketLines:
|
|
5285
|
+
ticketLines: checkoutModalTicketLinesDisplay,
|
|
5273
5286
|
feeLineItems: feeLineItemsWithAddOns,
|
|
5274
5287
|
returnPriceAdjustment: checkoutReturnLineAmount,
|
|
5275
5288
|
cancellationPolicyFee,
|
|
@@ -3564,6 +3564,30 @@ export function ChangeBookingFlow({
|
|
|
3564
3564
|
effectivePromoDiscountAmount,
|
|
3565
3565
|
]);
|
|
3566
3566
|
|
|
3567
|
+
const checkoutModalTicketLinesDisplay = useMemo((): CheckoutModalLineItem[] => {
|
|
3568
|
+
return taxIncludedSelfServeReconciledPriceSummaryLines
|
|
3569
|
+
.filter((l): l is Extract<PriceSummaryLine, { kind: 'ticket' }> => l.kind === 'ticket')
|
|
3570
|
+
.map((line) => {
|
|
3571
|
+
const rate = pricing.find((r) => r.category === line.category);
|
|
3572
|
+
const breakdown = getPriceBreakdown(
|
|
3573
|
+
line.category,
|
|
3574
|
+
rate?.priceCAD ?? 0,
|
|
3575
|
+
rate?.baseInDisplayCurrency,
|
|
3576
|
+
rate?.appliedAdjustments ?? [],
|
|
3577
|
+
);
|
|
3578
|
+
const qty = Math.max(0, line.qty);
|
|
3579
|
+
return {
|
|
3580
|
+
line: {
|
|
3581
|
+
category: line.category,
|
|
3582
|
+
qty,
|
|
3583
|
+
itemTotal: line.itemTotal,
|
|
3584
|
+
pricePerUnit: qty > 0 ? roundMoney(line.itemTotal / qty) : 0,
|
|
3585
|
+
},
|
|
3586
|
+
breakdown,
|
|
3587
|
+
};
|
|
3588
|
+
});
|
|
3589
|
+
}, [taxIncludedSelfServeReconciledPriceSummaryLines, pricing, getPriceBreakdown]);
|
|
3590
|
+
|
|
3567
3591
|
const changeFlowClientEstimateDue = (() => {
|
|
3568
3592
|
if (!originalReceipt) return totalPrice;
|
|
3569
3593
|
// Customer self-serve: amount due comes from POST .../change/quote (`amountDueCents` / priceDiff), not FE delta math.
|
|
@@ -4466,11 +4490,8 @@ export function ChangeBookingFlow({
|
|
|
4466
4490
|
originalReceiptTotal: originalReceipt?.total ?? 0,
|
|
4467
4491
|
audience: 'customer',
|
|
4468
4492
|
});
|
|
4469
|
-
const ticketRowsForCheckoutBreakdown = taxIncludedSelfServeReconciledPriceSummaryLines.filter(
|
|
4470
|
-
(l): l is Extract<PriceSummaryLine, { kind: 'ticket' }> => l.kind === 'ticket',
|
|
4471
|
-
);
|
|
4472
4493
|
const lines = [
|
|
4473
|
-
...
|
|
4494
|
+
...ticketLineItemsForChangeFlowDisplay.map((line) => ({
|
|
4474
4495
|
label: line.category,
|
|
4475
4496
|
amount: line.itemTotal,
|
|
4476
4497
|
type: 'TICKET' as const,
|
|
@@ -4555,26 +4576,6 @@ export function ChangeBookingFlow({
|
|
|
4555
4576
|
})()
|
|
4556
4577
|
);
|
|
4557
4578
|
|
|
4558
|
-
const ticketLinesForModal: CheckoutModalLineItem[] = ticketRowsForCheckoutBreakdown.map((line) => {
|
|
4559
|
-
const rate = pricing.find((r) => r.category === line.category);
|
|
4560
|
-
const breakdown = getPriceBreakdown(
|
|
4561
|
-
line.category,
|
|
4562
|
-
rate?.priceCAD ?? 0,
|
|
4563
|
-
rate?.baseInDisplayCurrency,
|
|
4564
|
-
rate?.appliedAdjustments ?? []
|
|
4565
|
-
);
|
|
4566
|
-
const qty = Math.max(0, line.qty);
|
|
4567
|
-
return {
|
|
4568
|
-
line: {
|
|
4569
|
-
category: line.category,
|
|
4570
|
-
qty,
|
|
4571
|
-
itemTotal: line.itemTotal,
|
|
4572
|
-
pricePerUnit: qty > 0 ? roundMoney(line.itemTotal / qty) : 0,
|
|
4573
|
-
},
|
|
4574
|
-
breakdown,
|
|
4575
|
-
};
|
|
4576
|
-
});
|
|
4577
|
-
|
|
4578
4579
|
setCheckoutClientSecret(paymentIntent.clientSecret ?? '');
|
|
4579
4580
|
setCheckoutModalData({
|
|
4580
4581
|
reservationReference: changeBookingReferenceForPaidFlow ?? '',
|
|
@@ -4598,7 +4599,7 @@ export function ChangeBookingFlow({
|
|
|
4598
4599
|
return `${origin}/manage-booking?ref=${ref}&lastName=${ln}&${fromQ}${intentQ}`;
|
|
4599
4600
|
})()
|
|
4600
4601
|
: undefined,
|
|
4601
|
-
ticketLines:
|
|
4602
|
+
ticketLines: checkoutModalTicketLinesDisplay,
|
|
4602
4603
|
feeLineItems: feeLineItemsWithAddOns,
|
|
4603
4604
|
returnPriceAdjustment: checkoutReturnLineAmount,
|
|
4604
4605
|
cancellationPolicyFee,
|