@ticketboothapp/booking 1.2.139 → 1.2.141
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 +1 -1
- package/src/components/booking/AdminChangeBookingContent.tsx +1 -0
- package/src/components/booking/AdminChangeBookingFlow.tsx +1 -0
- package/src/components/booking/AdminChangeCheckoutPanel.tsx +3 -0
- package/src/components/booking/AdminChangeReceiptComparison.tsx +83 -21
- package/src/components/booking/useAdminChangePriceSummary.ts +1 -2
- package/src/components/booking/useAdminChangeQuotePreview.ts +10 -16
- package/src/components/booking/useAdminChangeReceiptDerivation.ts +6 -1
- package/src/lib/booking-api.ts +69 -0
package/package.json
CHANGED
|
@@ -971,6 +971,7 @@ export function AdminChangeBookingFlow({
|
|
|
971
971
|
receiptTax: adminFeAuthoritativeReceipt.tax,
|
|
972
972
|
receiptTotal: adminFeAuthoritativeReceipt.total,
|
|
973
973
|
originalReceipt,
|
|
974
|
+
isServerAmendmentQuote: latestChangeQuote?.pricingVersion === 'booking-amendment-v1',
|
|
974
975
|
...{ priceSummaryLinesIncludeTaxRow, isTaxIncludedInPrice, showProviderPricingInlineEditor },
|
|
975
976
|
taxRate: pricingConfig?.taxRate,
|
|
976
977
|
...{ providerPricingUi, providerQuotedLines },
|
|
@@ -30,6 +30,7 @@ export interface AdminChangeCheckoutPanelProps {
|
|
|
30
30
|
receiptTotal: number;
|
|
31
31
|
originalReceipt: ChangeBookingFlowProps['originalReceipt'];
|
|
32
32
|
priceSummaryLinesIncludeTaxRow: boolean;
|
|
33
|
+
isServerAmendmentQuote?: boolean;
|
|
33
34
|
isTaxIncludedInPrice: boolean;
|
|
34
35
|
taxRate?: number;
|
|
35
36
|
currency: Currency;
|
|
@@ -99,6 +100,7 @@ export function AdminChangeCheckoutPanel({
|
|
|
99
100
|
receiptTotal,
|
|
100
101
|
originalReceipt,
|
|
101
102
|
priceSummaryLinesIncludeTaxRow,
|
|
103
|
+
isServerAmendmentQuote,
|
|
102
104
|
isTaxIncludedInPrice,
|
|
103
105
|
taxRate,
|
|
104
106
|
currency,
|
|
@@ -188,6 +190,7 @@ export function AdminChangeCheckoutPanel({
|
|
|
188
190
|
}}
|
|
189
191
|
newPriceSummaryLines={priceSummaryLines}
|
|
190
192
|
newPriceSummaryLinesIncludeTaxRow={priceSummaryLinesIncludeTaxRow}
|
|
193
|
+
isServerAmendmentQuote={isServerAmendmentQuote}
|
|
191
194
|
amountDue={changeFlowAmountDue}
|
|
192
195
|
amountDueLabel={totalSummaryLabel}
|
|
193
196
|
currency={currency}
|
|
@@ -16,6 +16,7 @@ export interface AdminChangeReceiptComparisonProps {
|
|
|
16
16
|
newReceipt: Pick<AdminFeAuthoritativeReceipt, 'subtotal' | 'tax' | 'total'>;
|
|
17
17
|
newPriceSummaryLines: PriceSummaryLine[];
|
|
18
18
|
newPriceSummaryLinesIncludeTaxRow: boolean;
|
|
19
|
+
isServerAmendmentQuote?: boolean;
|
|
19
20
|
amountDue: number;
|
|
20
21
|
amountDueLabel: string;
|
|
21
22
|
currency: Currency;
|
|
@@ -84,12 +85,17 @@ function amendmentDeltaLines(
|
|
|
84
85
|
|
|
85
86
|
return proposedLines.flatMap((line): PriceSummaryLine[] => {
|
|
86
87
|
const original = remainingOriginal.get(lineIdentity(line));
|
|
87
|
-
const amount = roundMoney(lineAmount(line) - (original?.amount ?? 0));
|
|
88
88
|
const proposedQuantity = lineQuantity(line);
|
|
89
89
|
const quantity =
|
|
90
90
|
proposedQuantity == null && original?.quantity == null
|
|
91
91
|
? null
|
|
92
92
|
: (proposedQuantity ?? 0) - (original?.quantity ?? 0);
|
|
93
|
+
const proposedAmount = lineAmount(line);
|
|
94
|
+
const amount = roundMoney(
|
|
95
|
+
quantity != null && quantity > 0 && proposedQuantity != null && proposedQuantity > 0
|
|
96
|
+
? (proposedAmount / proposedQuantity) * quantity
|
|
97
|
+
: proposedAmount - (original?.amount ?? 0),
|
|
98
|
+
);
|
|
93
99
|
if (Math.abs(amount) < 0.005 && (quantity == null || quantity === 0)) return [];
|
|
94
100
|
|
|
95
101
|
if (line.kind === 'ticket') {
|
|
@@ -104,7 +110,9 @@ function amendmentDeltaLines(
|
|
|
104
110
|
const isTax = String(line.type ?? '').toUpperCase() === 'TAX';
|
|
105
111
|
return [{
|
|
106
112
|
...line,
|
|
107
|
-
label: isTax
|
|
113
|
+
label: isTax
|
|
114
|
+
? (amount >= 0 ? 'Additional tax' : 'Tax reduction')
|
|
115
|
+
: line.label.replace(/\s*\([^)]*(?:people|person|x\s*\d+)[^)]*\)\s*$/i, '').trim(),
|
|
108
116
|
amount,
|
|
109
117
|
quantity: quantity == null ? null : Math.abs(quantity),
|
|
110
118
|
editable: false,
|
|
@@ -117,8 +125,7 @@ export function AdminChangeReceiptComparison({
|
|
|
117
125
|
originalReceipt,
|
|
118
126
|
newReceipt,
|
|
119
127
|
newPriceSummaryLines,
|
|
120
|
-
|
|
121
|
-
amountDue,
|
|
128
|
+
isServerAmendmentQuote = false,
|
|
122
129
|
amountDueLabel,
|
|
123
130
|
currency,
|
|
124
131
|
locale,
|
|
@@ -132,11 +139,56 @@ export function AdminChangeReceiptComparison({
|
|
|
132
139
|
[originalReceipt],
|
|
133
140
|
);
|
|
134
141
|
const originalLinesIncludeTaxRow = hasTaxLine(originalReceiptLines);
|
|
135
|
-
const calculatedChangeLines = useMemo(
|
|
136
|
-
()
|
|
137
|
-
|
|
142
|
+
const calculatedChangeLines = useMemo(() => {
|
|
143
|
+
if (!isServerAmendmentQuote) {
|
|
144
|
+
return amendmentDeltaLines(originalReceiptLines, newPriceSummaryLines);
|
|
145
|
+
}
|
|
146
|
+
const nonTax = newPriceSummaryLines.filter(
|
|
147
|
+
(line) => !(line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'),
|
|
148
|
+
);
|
|
149
|
+
const tax = roundMoney(
|
|
150
|
+
newPriceSummaryLines.reduce(
|
|
151
|
+
(sum, line) =>
|
|
152
|
+
line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'
|
|
153
|
+
? sum + line.amount
|
|
154
|
+
: sum,
|
|
155
|
+
0,
|
|
156
|
+
),
|
|
157
|
+
);
|
|
158
|
+
return Math.abs(tax) < 0.005
|
|
159
|
+
? nonTax
|
|
160
|
+
: [
|
|
161
|
+
...nonTax,
|
|
162
|
+
{
|
|
163
|
+
kind: 'line' as const,
|
|
164
|
+
label: tax >= 0 ? 'Additional tax' : 'Tax reduction',
|
|
165
|
+
amount: tax,
|
|
166
|
+
type: 'TAX',
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
}, [isServerAmendmentQuote, newPriceSummaryLines, originalReceiptLines]);
|
|
170
|
+
const nonTaxChangeSubtotal = roundMoney(
|
|
171
|
+
calculatedChangeLines.reduce(
|
|
172
|
+
(sum, line) =>
|
|
173
|
+
line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'
|
|
174
|
+
? sum
|
|
175
|
+
: sum + lineAmount(line),
|
|
176
|
+
0,
|
|
177
|
+
),
|
|
178
|
+
);
|
|
179
|
+
const receiptTaxDelta = roundMoney(
|
|
180
|
+
isServerAmendmentQuote
|
|
181
|
+
? calculatedChangeLines.reduce(
|
|
182
|
+
(sum, line) =>
|
|
183
|
+
line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'
|
|
184
|
+
? sum + line.amount
|
|
185
|
+
: sum,
|
|
186
|
+
0,
|
|
187
|
+
)
|
|
188
|
+
: taxRate != null && nonTaxChangeSubtotal > 0
|
|
189
|
+
? nonTaxChangeSubtotal * taxRate
|
|
190
|
+
: newReceipt.tax - originalReceipt.tax,
|
|
138
191
|
);
|
|
139
|
-
const receiptTaxDelta = roundMoney(newReceipt.tax - originalReceipt.tax);
|
|
140
192
|
const changeLines = useMemo(() => {
|
|
141
193
|
if (hasTaxLine(calculatedChangeLines) || Math.abs(receiptTaxDelta) < 0.005) {
|
|
142
194
|
return calculatedChangeLines;
|
|
@@ -161,7 +213,10 @@ export function AdminChangeReceiptComparison({
|
|
|
161
213
|
0,
|
|
162
214
|
),
|
|
163
215
|
);
|
|
164
|
-
const
|
|
216
|
+
const displayedAmountDue = roundMoney(changeLines.reduce((sum, line) => sum + lineAmount(line), 0));
|
|
217
|
+
const displayedUpdatedTotal = roundMoney(originalReceipt.total + displayedAmountDue);
|
|
218
|
+
const displayedUpdatedSubtotal = roundMoney(originalReceipt.subtotal + nonTaxChangeSubtotal);
|
|
219
|
+
const displayedUpdatedTax = roundMoney(originalReceipt.tax + changeTax);
|
|
165
220
|
const originalCurrency = originalReceipt.currency ?? currency;
|
|
166
221
|
const originalReceiptLinesWithComparableBreakdowns = useMemo(
|
|
167
222
|
() =>
|
|
@@ -184,9 +239,9 @@ export function AdminChangeReceiptComparison({
|
|
|
184
239
|
[originalReceiptLines],
|
|
185
240
|
);
|
|
186
241
|
const amountDueClass =
|
|
187
|
-
|
|
242
|
+
displayedAmountDue < -0.005
|
|
188
243
|
? 'text-emerald-700'
|
|
189
|
-
:
|
|
244
|
+
: displayedAmountDue > 0.005
|
|
190
245
|
? 'text-stone-900'
|
|
191
246
|
: 'text-stone-700';
|
|
192
247
|
|
|
@@ -219,10 +274,10 @@ export function AdminChangeReceiptComparison({
|
|
|
219
274
|
<p className="mt-0.5 text-xs text-stone-500">Only newly charged, credited, or repriced value</p>
|
|
220
275
|
</div>
|
|
221
276
|
<span className="shrink-0 text-xs font-medium text-stone-500">
|
|
222
|
-
{formatCurrencyAmount(
|
|
277
|
+
{formatCurrencyAmount(displayedAmountDue, currency, displayLocale)}
|
|
223
278
|
</span>
|
|
224
279
|
</div>
|
|
225
|
-
{changeLines.length === 0 && Math.abs(
|
|
280
|
+
{changeLines.length === 0 && Math.abs(displayedAmountDue) < 0.005 ? (
|
|
226
281
|
<div className="rounded-md border border-dashed border-stone-300 bg-white/70 px-3 py-4 text-center">
|
|
227
282
|
<p className="text-sm font-medium text-stone-700">No pricing changes</p>
|
|
228
283
|
<p className="mt-1 text-xs text-stone-500">The selected booking details match the existing purchase.</p>
|
|
@@ -230,10 +285,10 @@ export function AdminChangeReceiptComparison({
|
|
|
230
285
|
) : (
|
|
231
286
|
<PriceSummary
|
|
232
287
|
lines={changeLines}
|
|
233
|
-
total={
|
|
288
|
+
total={displayedAmountDue}
|
|
234
289
|
currency={currency}
|
|
235
290
|
locale={displayLocale}
|
|
236
|
-
subtotal={
|
|
291
|
+
subtotal={nonTaxChangeSubtotal}
|
|
237
292
|
taxAmount={!changeLinesIncludeTaxRow ? changeTax : 0}
|
|
238
293
|
taxRate={taxRate}
|
|
239
294
|
size="sm"
|
|
@@ -249,16 +304,23 @@ export function AdminChangeReceiptComparison({
|
|
|
249
304
|
<p className="mt-0.5 text-xs text-stone-500">Read-only pricing result; historical and added cohorts remain separate when supplied by the server</p>
|
|
250
305
|
</div>
|
|
251
306
|
<span className="shrink-0 text-xs font-medium text-stone-500">
|
|
252
|
-
{formatCurrencyAmount(
|
|
307
|
+
{formatCurrencyAmount(displayedUpdatedTotal, currency, displayLocale)}
|
|
253
308
|
</span>
|
|
254
309
|
</div>
|
|
255
310
|
<PriceSummary
|
|
256
|
-
lines={
|
|
257
|
-
|
|
311
|
+
lines={[
|
|
312
|
+
...originalReceiptLines.filter(
|
|
313
|
+
(line) => !(line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'),
|
|
314
|
+
),
|
|
315
|
+
...changeLines.filter(
|
|
316
|
+
(line) => !(line.kind === 'line' && String(line.type ?? '').toUpperCase() === 'TAX'),
|
|
317
|
+
),
|
|
318
|
+
].map((line) => ({ ...line, editable: false, lineKey: undefined }))}
|
|
319
|
+
total={displayedUpdatedTotal}
|
|
258
320
|
currency={currency}
|
|
259
321
|
locale={displayLocale}
|
|
260
|
-
subtotal={
|
|
261
|
-
taxAmount={
|
|
322
|
+
subtotal={displayedUpdatedSubtotal}
|
|
323
|
+
taxAmount={displayedUpdatedTax}
|
|
262
324
|
taxRate={taxRate}
|
|
263
325
|
size="sm"
|
|
264
326
|
t={t}
|
|
@@ -276,7 +338,7 @@ export function AdminChangeReceiptComparison({
|
|
|
276
338
|
<div className="flex flex-wrap items-center justify-between gap-2 rounded-lg border border-stone-200 bg-stone-50 px-3 py-2">
|
|
277
339
|
<span className="text-sm font-semibold text-stone-900">{amountDueLabel}</span>
|
|
278
340
|
<span className={`text-lg font-semibold tabular-nums ${amountDueClass}`}>
|
|
279
|
-
{formatCurrencyAmount(
|
|
341
|
+
{formatCurrencyAmount(displayedAmountDue, currency, displayLocale)}
|
|
280
342
|
</span>
|
|
281
343
|
</div>
|
|
282
344
|
</div>
|
|
@@ -336,7 +336,7 @@ export function useAdminChangePriceSummary({
|
|
|
336
336
|
|
|
337
337
|
const checkoutPriceSummaryLinesForCheckout = useMemo(() => {
|
|
338
338
|
let raw: PriceSummaryLine[];
|
|
339
|
-
if (
|
|
339
|
+
if (suppressSelfServeCurrencyUi && selfServePricingConfirmed) {
|
|
340
340
|
raw =
|
|
341
341
|
latestServerPriceSummaryLines && latestServerPriceSummaryLines.length > 0
|
|
342
342
|
? latestServerPriceSummaryLines
|
|
@@ -366,7 +366,6 @@ export function useAdminChangePriceSummary({
|
|
|
366
366
|
}, [
|
|
367
367
|
suppressSelfServeCurrencyUi,
|
|
368
368
|
selfServePricingConfirmed,
|
|
369
|
-
useAdminFeAuthoritativeQuote,
|
|
370
369
|
checkoutPriceSummaryLines,
|
|
371
370
|
latestServerPriceSummaryLines,
|
|
372
371
|
effectivePromoDiscountAmount,
|
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
} from 'react';
|
|
9
9
|
import {
|
|
10
10
|
quoteChangeBooking,
|
|
11
|
-
|
|
11
|
+
quoteAdminChangeBookingV2,
|
|
12
12
|
type AdminFeAuthoritativeReceipt,
|
|
13
13
|
type Availability,
|
|
14
14
|
type ItineraryDisplayStep,
|
|
15
15
|
type Product,
|
|
16
16
|
type ReturnOption,
|
|
17
17
|
} from '../../lib/booking-api';
|
|
18
|
-
import { roundMoney } from '../../lib/booking/change-flow-pricing';
|
|
19
18
|
import { getItineraryStepLabel } from '../../lib/booking/itinerary-display';
|
|
20
19
|
import type { OrderSummaryTicketLine } from '../../lib/booking/pricing';
|
|
21
20
|
import { formatCurrencyAmount } from '../../lib/currency';
|
|
@@ -262,9 +261,11 @@ export function useAdminChangeQuotePreview({
|
|
|
262
261
|
hasChangesFromInitial: hasEffectiveChangeSelection,
|
|
263
262
|
selectionTotal:
|
|
264
263
|
originalReceipt
|
|
265
|
-
?
|
|
266
|
-
?
|
|
267
|
-
:
|
|
264
|
+
? selfServePricingConfirmed && latestChangeQuote?.serverPreview?.totalNewBooking != null
|
|
265
|
+
? latestChangeQuote.serverPreview.totalNewBooking
|
|
266
|
+
: suppressSelfServeCurrencyUi
|
|
267
|
+
? null
|
|
268
|
+
: displayChangeFlowProposedTotalWithEditableLines
|
|
268
269
|
: totalPrice,
|
|
269
270
|
selectionCurrency: currency,
|
|
270
271
|
};
|
|
@@ -282,7 +283,7 @@ export function useAdminChangeQuotePreview({
|
|
|
282
283
|
displayChangeFlowProposedTotalWithEditableLines,
|
|
283
284
|
suppressSelfServeCurrencyUi,
|
|
284
285
|
selfServePricingConfirmed,
|
|
285
|
-
|
|
286
|
+
latestChangeQuote?.serverPreview?.totalNewBooking,
|
|
286
287
|
]);
|
|
287
288
|
|
|
288
289
|
useEffect(() => {
|
|
@@ -423,18 +424,11 @@ export function useAdminChangeQuotePreview({
|
|
|
423
424
|
previousReturnAvailabilityId: initialValues.returnAvailabilityId ?? null,
|
|
424
425
|
},
|
|
425
426
|
};
|
|
426
|
-
const deterministicClientProposedTotal = useAdminFeAuthoritativeQuote
|
|
427
|
-
? adminFeAuthoritativeReceipt.total
|
|
428
|
-
: changeFlowNewBookingTotal;
|
|
429
|
-
const deterministicAmountDue = originalReceipt
|
|
430
|
-
? roundMoney(adminFeAuthoritativeReceipt.total - originalReceipt.total)
|
|
431
|
-
: roundMoney(changeFlowClientEstimateDue);
|
|
432
427
|
const quote = useAdminFeAuthoritativeQuote
|
|
433
|
-
? await
|
|
428
|
+
? await quoteAdminChangeBookingV2({
|
|
434
429
|
...quoteRequestBase,
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
clientProposedTotal: deterministicClientProposedTotal,
|
|
430
|
+
// V2 is server-authoritative. Do not bind it to the outbound-only FE estimate.
|
|
431
|
+
clientProposedTotal: undefined,
|
|
438
432
|
})
|
|
439
433
|
: await quoteChangeBooking(quoteRequestBase);
|
|
440
434
|
if (seq !== changeQuoteRequestSeq.current) return;
|
|
@@ -188,7 +188,12 @@ export function useAdminChangeReceiptDerivation({
|
|
|
188
188
|
});
|
|
189
189
|
})();
|
|
190
190
|
const changeFlowClientEstimateDue = normalizeNearZeroOwed(
|
|
191
|
-
roundMoney(
|
|
191
|
+
roundMoney(
|
|
192
|
+
changeFlowClientEstimateDueBase +
|
|
193
|
+
(latestChangeQuote?.pricingVersion === 'booking-amendment-v1'
|
|
194
|
+
? 0
|
|
195
|
+
: editableSummaryPreSubtotalDelta),
|
|
196
|
+
),
|
|
192
197
|
);
|
|
193
198
|
const changeFlowAmountDue = normalizeNearZeroOwed(changeFlowClientEstimateDue);
|
|
194
199
|
|
package/src/lib/booking-api.ts
CHANGED
|
@@ -1290,6 +1290,23 @@ export interface AdminChangeBookingQuoteRequest extends ChangeBookingQuoteReques
|
|
|
1290
1290
|
feAmountDueMajorUnits?: number;
|
|
1291
1291
|
}
|
|
1292
1292
|
|
|
1293
|
+
export interface AdminChangeBookingQuoteV2Data {
|
|
1294
|
+
oldReceipt: {
|
|
1295
|
+
currency?: string | null;
|
|
1296
|
+
grossSubtotal?: number | null;
|
|
1297
|
+
taxAmount?: number | null;
|
|
1298
|
+
payableTotal?: number | null;
|
|
1299
|
+
lines?: PricingV2QuoteLineSnapshot[] | null;
|
|
1300
|
+
};
|
|
1301
|
+
newQuote?: PricingV2QuoteSnapshot | null;
|
|
1302
|
+
balanceDelta?: number | null;
|
|
1303
|
+
amountToCharge?: number | null;
|
|
1304
|
+
refundCandidate?: number | null;
|
|
1305
|
+
canApply: boolean;
|
|
1306
|
+
reasonIfBlocked?: string | null;
|
|
1307
|
+
unsupportedFeatures?: string[];
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1293
1310
|
export interface ChangeBookingQuoteReceipt {
|
|
1294
1311
|
subtotal?: number;
|
|
1295
1312
|
tax?: number;
|
|
@@ -1593,6 +1610,58 @@ export async function quoteChangeBookingAdminFeReceipt(
|
|
|
1593
1610
|
data) as ChangeBookingQuoteResponse;
|
|
1594
1611
|
}
|
|
1595
1612
|
|
|
1613
|
+
/** Server-authoritative Pricing V2 quote used by the provider-dashboard amendment preview. */
|
|
1614
|
+
export async function quoteAdminChangeBookingV2(
|
|
1615
|
+
request: ChangeBookingQuoteRequest
|
|
1616
|
+
): Promise<ChangeBookingQuoteResponse> {
|
|
1617
|
+
const { bookingReference, lastName: _lastName, ...payload } = request;
|
|
1618
|
+
const res = await fetch(
|
|
1619
|
+
`${API_BASE}/1/admin/bookings/${encodeURIComponent(bookingReference)}/change/quote-v2`,
|
|
1620
|
+
{
|
|
1621
|
+
method: 'POST',
|
|
1622
|
+
headers: getAuthHeaders(),
|
|
1623
|
+
body: JSON.stringify(payload),
|
|
1624
|
+
}
|
|
1625
|
+
);
|
|
1626
|
+
if (!res.ok) {
|
|
1627
|
+
const err = await parseJsonSafely(res);
|
|
1628
|
+
const message = isApiErrorPayload(err)
|
|
1629
|
+
? err.errorMessage || err.error || 'Failed to quote admin booking change'
|
|
1630
|
+
: 'Failed to quote admin booking change';
|
|
1631
|
+
throw new Error(message);
|
|
1632
|
+
}
|
|
1633
|
+
const response = await parseJsonSafely(res);
|
|
1634
|
+
const outer = (response as { data?: unknown } | null)?.data;
|
|
1635
|
+
const data = ((outer as { data?: AdminChangeBookingQuoteV2Data } | null)?.data ??
|
|
1636
|
+
outer) as AdminChangeBookingQuoteV2Data;
|
|
1637
|
+
const oldReceipt = data.oldReceipt;
|
|
1638
|
+
const newQuote = data.newQuote ?? null;
|
|
1639
|
+
const currency = newQuote?.currency ?? oldReceipt.currency ?? undefined;
|
|
1640
|
+
return {
|
|
1641
|
+
pricingQuote: newQuote,
|
|
1642
|
+
quote: newQuote,
|
|
1643
|
+
balanceDelta: data.balanceDelta ?? newQuote?.balanceDelta ?? undefined,
|
|
1644
|
+
amountToCharge: data.amountToCharge ?? newQuote?.amountToCharge ?? undefined,
|
|
1645
|
+
refundCandidate: data.refundCandidate ?? newQuote?.refundCandidate ?? undefined,
|
|
1646
|
+
priceDiff: data.balanceDelta ?? newQuote?.balanceDelta ?? 0,
|
|
1647
|
+
currency: currency ?? undefined,
|
|
1648
|
+
canProceed: data.canApply,
|
|
1649
|
+
reasonIfBlocked: data.reasonIfBlocked ?? undefined,
|
|
1650
|
+
originalReceipt: {
|
|
1651
|
+
subtotal: oldReceipt.grossSubtotal ?? undefined,
|
|
1652
|
+
tax: oldReceipt.taxAmount ?? undefined,
|
|
1653
|
+
total: oldReceipt.payableTotal ?? 0,
|
|
1654
|
+
currency: oldReceipt.currency ?? undefined,
|
|
1655
|
+
lineItems: oldReceipt.lines?.map((line) => ({
|
|
1656
|
+
label: line.label ?? undefined,
|
|
1657
|
+
amount: line.amount ?? undefined,
|
|
1658
|
+
type: line.type ?? undefined,
|
|
1659
|
+
quantity: line.quantity ?? undefined,
|
|
1660
|
+
})),
|
|
1661
|
+
},
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1596
1665
|
export async function createChangeBookingPaymentIntent(
|
|
1597
1666
|
changeIntentId: string
|
|
1598
1667
|
): Promise<CreateChangePaymentIntentResponse> {
|