@ticketboothapp/booking 1.2.166 → 1.2.168
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 +15 -1
- package/src/components/booking/AdminChangeBookingFlow.tsx +274 -94
- package/src/components/booking/AdminChangeCheckoutPanel.tsx +49 -13
- package/src/components/booking/AdminChangePricingPanel.tsx +400 -134
- package/src/components/booking/AdminChangePromoEditor.tsx +97 -0
- package/src/components/booking/AdminChangeReceiptComparison.tsx +172 -147
- package/src/components/booking/ChangeBookingFlow.tsx +6 -3
- package/src/components/booking/ChangeBookingQuoteStatusPlaceholder.tsx +7 -2
- package/src/components/booking/ChangeBookingSelectionControlsPanel.tsx +6 -0
- package/src/components/booking/ChangeBookingTicketsAndAddOnsPanel.tsx +80 -0
- package/src/components/booking/NewBookingFlow.tsx +14 -2
- package/src/components/booking/PickupLocationSelector.module.css +22 -0
- package/src/components/booking/PickupLocationSelector.tsx +3 -3
- package/src/components/booking/PriceBreakdown.tsx +66 -15
- package/src/components/booking/PriceSummary.tsx +16 -0
- package/src/components/booking/PrivateShuttleBookingFlow.tsx +52 -14
- package/src/components/booking/PrivateShuttleCheckoutSection.tsx +95 -54
- package/src/components/booking/admin-adjustment-components.ts +44 -0
- package/src/components/booking/admin-adjustment-tax-behavior.ts +50 -0
- package/src/components/booking/admin-change-flow-state-helpers.ts +10 -0
- package/src/components/booking/admin-change-provider-payload.ts +12 -1
- package/src/components/booking/admin-change-quote-request-key.ts +41 -1
- package/src/components/booking/admin-change-receipt-lines.ts +49 -0
- package/src/components/booking/admin-change-v2-quote-request.ts +109 -0
- package/src/components/booking/admin-refund-decision-context.ts +122 -0
- package/src/components/booking/admin-refund-disposition.ts +71 -2
- package/src/components/booking/availability-date-selection.ts +16 -0
- package/src/components/booking/booking-flow-types.ts +4 -0
- package/src/components/booking/booking-flow.css +5 -0
- package/src/components/booking/change-booking-error-message.ts +137 -0
- package/src/components/booking/change-booking-flow-helpers.ts +77 -2
- package/src/components/booking/change-booking-quote-guards.ts +4 -1
- package/src/components/booking/change-booking-quote-state.ts +44 -1
- package/src/components/booking/incompatible-add-on-selections.ts +19 -0
- package/src/components/booking/private-shuttle-availability.ts +14 -0
- package/src/components/booking/private-shuttle-cancellation-policy.ts +9 -0
- package/src/components/booking/private-shuttle-checkout-controller.ts +5 -0
- package/src/components/booking/private-shuttle-provider-change-runner.ts +21 -0
- package/src/components/booking/private-shuttle-reservation-runner.ts +5 -3
- package/src/components/booking/provider-dashboard-change-booking.ts +18 -2
- package/src/components/booking/use-standard-booking-availability.ts +5 -2
- package/src/components/booking/useAdminChangeCheckoutController.ts +56 -1
- package/src/components/booking/useAdminChangeProductReset.ts +6 -0
- package/src/components/booking/useAdminChangeProtectedPricing.ts +4 -0
- package/src/components/booking/useAdminChangeQuoteDisplayState.tsx +8 -6
- package/src/components/booking/useAdminChangeQuotePreview.ts +146 -61
- package/src/components/booking/useAdminCustomReceiptLines.ts +171 -10
- package/src/components/booking/useAdminProviderPricingAdjustments.ts +50 -19
- package/src/components/booking/useBookingAvailabilityAddOns.ts +26 -4
- package/src/components/booking/useBookingPromoAndQuantityController.ts +16 -2
- package/src/components/booking/useChangeBookingAddOnFloorController.ts +15 -9
- package/src/components/booking/useChangeBookingAutoSelections.ts +60 -17
- package/src/components/booking/useChangeBookingInitialHydration.ts +10 -7
- package/src/components/booking/useChangeBookingQuotePreview.ts +3 -1
- package/src/components/booking/useChangeBookingSelectionDetails.ts +23 -17
- package/src/components/booking/useStandardBookingAutoSelections.ts +55 -7
- package/src/lib/booking/booking-cutoffs.ts +22 -0
- package/src/lib/booking/change-booking-server-preview.ts +92 -5
- package/src/lib/booking/change-flow-pricing.ts +12 -0
- package/src/lib/booking/i18n/messages/en.json +1 -0
- package/src/lib/booking/i18n/messages/fr.json +1 -0
- package/src/lib/booking-api.ts +76 -1
- package/test/change-booking-helpers.test.ts +1319 -7
- package/src/components/booking/useAdminChangePricingDebugPanel.tsx +0 -178
|
@@ -3,10 +3,16 @@ import type {
|
|
|
3
3
|
ProviderDashboardInitialBooking,
|
|
4
4
|
} from './provider-dashboard-change-booking';
|
|
5
5
|
import type { PrivateShuttleAddOnSelection } from './private-shuttle-reservation-runner';
|
|
6
|
+
import {
|
|
7
|
+
buildPrivateShuttleItineraryDisplayForStorage,
|
|
8
|
+
type PrivateShuttleCheckoutItineraryItem,
|
|
9
|
+
} from './private-shuttle-reservation-runner';
|
|
6
10
|
|
|
7
11
|
export interface ApplyPrivateShuttleProviderChangeParams {
|
|
8
12
|
onChangeBooking: (data: ProviderDashboardChangeBookingPayload) => Promise<void>;
|
|
13
|
+
parentProductId: string;
|
|
9
14
|
selectedOption: string;
|
|
15
|
+
selectedAvailabilityId?: string | null;
|
|
10
16
|
selectedDate: string;
|
|
11
17
|
selectedStartTime: string;
|
|
12
18
|
billableResourceCount: number;
|
|
@@ -22,13 +28,18 @@ export interface ApplyPrivateShuttleProviderChangeParams {
|
|
|
22
28
|
activePromoCode: string | null;
|
|
23
29
|
totalPrice: number;
|
|
24
30
|
additionalHoursCount: number;
|
|
31
|
+
draftItineraryDestinations: string[];
|
|
32
|
+
draftItineraryPlanningNotes: string;
|
|
33
|
+
itineraryDisplayItems: PrivateShuttleCheckoutItineraryItem[];
|
|
25
34
|
isAdmin: boolean;
|
|
26
35
|
providerChangeAuthoritativeReceipt?: ProviderDashboardChangeBookingPayload['authoritativeReceipt'];
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
export async function applyPrivateShuttleProviderChange({
|
|
30
39
|
onChangeBooking,
|
|
40
|
+
parentProductId,
|
|
31
41
|
selectedOption,
|
|
42
|
+
selectedAvailabilityId,
|
|
32
43
|
selectedDate,
|
|
33
44
|
selectedStartTime,
|
|
34
45
|
billableResourceCount,
|
|
@@ -44,6 +55,9 @@ export async function applyPrivateShuttleProviderChange({
|
|
|
44
55
|
activePromoCode,
|
|
45
56
|
totalPrice,
|
|
46
57
|
additionalHoursCount,
|
|
58
|
+
draftItineraryDestinations,
|
|
59
|
+
draftItineraryPlanningNotes,
|
|
60
|
+
itineraryDisplayItems,
|
|
47
61
|
isAdmin,
|
|
48
62
|
providerChangeAuthoritativeReceipt,
|
|
49
63
|
}: ApplyPrivateShuttleProviderChangeParams): Promise<void> {
|
|
@@ -52,7 +66,9 @@ export async function applyPrivateShuttleProviderChange({
|
|
|
52
66
|
const startTimeISO = `${selectedDate}T${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:00-06:00`;
|
|
53
67
|
|
|
54
68
|
await onChangeBooking({
|
|
69
|
+
parentProductId,
|
|
55
70
|
productId: selectedOption,
|
|
71
|
+
availabilityId: selectedAvailabilityId ?? null,
|
|
56
72
|
dateTime: selectedDate,
|
|
57
73
|
bookingItems,
|
|
58
74
|
returnAvailabilityId: null,
|
|
@@ -60,6 +76,11 @@ export async function applyPrivateShuttleProviderChange({
|
|
|
60
76
|
travelerHotel:
|
|
61
77
|
selectedPickupLocationName ?? customPickupAddress ?? initialBooking?.travelerHotel ?? null,
|
|
62
78
|
startTime: startTimeISO,
|
|
79
|
+
draftItinerary: {
|
|
80
|
+
destinations: draftItineraryDestinations,
|
|
81
|
+
planningNotes: draftItineraryPlanningNotes.trim(),
|
|
82
|
+
},
|
|
83
|
+
itineraryDisplay: buildPrivateShuttleItineraryDisplayForStorage(itineraryDisplayItems),
|
|
63
84
|
passengerCount,
|
|
64
85
|
childSafetySeatsCount: childSafetySeatsCount > 0 ? childSafetySeatsCount : null,
|
|
65
86
|
foodRestrictions: foodRestrictions.trim() || null,
|
|
@@ -84,10 +84,11 @@ export interface ReservePrivateShuttleForCheckoutParams {
|
|
|
84
84
|
pricingProfileIdForAvailabilities: string | null;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
function buildPrivateShuttleItineraryDisplayForStorage(
|
|
87
|
+
export function buildPrivateShuttleItineraryDisplayForStorage(
|
|
88
88
|
itineraryDisplayItems: PrivateShuttleCheckoutItineraryItem[]
|
|
89
89
|
): ItineraryDisplayStep[] {
|
|
90
|
-
|
|
90
|
+
let hasPickup = false;
|
|
91
|
+
return itineraryDisplayItems.map((item) => {
|
|
91
92
|
if (item.isProposedStops) {
|
|
92
93
|
return {
|
|
93
94
|
stepType: ItineraryStepType.draft,
|
|
@@ -95,7 +96,8 @@ function buildPrivateShuttleItineraryDisplayForStorage(
|
|
|
95
96
|
place: item.label,
|
|
96
97
|
};
|
|
97
98
|
}
|
|
98
|
-
const isPickup =
|
|
99
|
+
const isPickup = !hasPickup;
|
|
100
|
+
hasPickup = true;
|
|
99
101
|
return {
|
|
100
102
|
stepType: isPickup ? ItineraryStepType.pickup : ItineraryStepType.drop_off,
|
|
101
103
|
time: item.time ?? 'TBD',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Currency } from './CurrencySwitcher';
|
|
2
|
-
import type { ItineraryDisplayStep } from '../../lib/booking-api';
|
|
2
|
+
import type { AdminPromoApplicationScope, ItineraryDisplayStep } from '../../lib/booking-api';
|
|
3
3
|
|
|
4
4
|
export type AdminAmendmentAdjustmentMode =
|
|
5
5
|
| 'FIXED_AMOUNT'
|
|
@@ -45,6 +45,10 @@ export type ProviderDashboardChangeBookingPayload = {
|
|
|
45
45
|
pickupLocationId?: string | null;
|
|
46
46
|
travelerHotel?: string | null;
|
|
47
47
|
startTime?: string | null;
|
|
48
|
+
draftItinerary?: {
|
|
49
|
+
destinations?: string[];
|
|
50
|
+
planningNotes?: string;
|
|
51
|
+
} | null;
|
|
48
52
|
itineraryDisplay?: ItineraryDisplayStep[] | null;
|
|
49
53
|
passengerCount?: number | null;
|
|
50
54
|
childSafetySeatsCount?: number | null;
|
|
@@ -52,6 +56,7 @@ export type ProviderDashboardChangeBookingPayload = {
|
|
|
52
56
|
addOnSelections?: Array<{ addOnId: string; variantId?: string; quantity?: number }> | null;
|
|
53
57
|
cancellationPolicyId?: string | null;
|
|
54
58
|
promoCode?: string | null;
|
|
59
|
+
promoApplicationScope?: AdminPromoApplicationScope | null;
|
|
55
60
|
newTotalAmount?: number;
|
|
56
61
|
additionalHoursCount?: number | null;
|
|
57
62
|
pricingAdjustment?: {
|
|
@@ -99,6 +104,8 @@ export type ProviderDashboardChangeBookingPayload = {
|
|
|
99
104
|
/** Seeds the flow when opening provider change-booking (matches TicketBooth `BookingWidget` `initialBooking`). */
|
|
100
105
|
export type ProviderDashboardInitialBooking = {
|
|
101
106
|
bookingReference: string;
|
|
107
|
+
/** Original parent catalog product id; required when the editor is mounted on a different target family. */
|
|
108
|
+
parentProductId?: string | null;
|
|
102
109
|
productId: string;
|
|
103
110
|
availabilityId?: string;
|
|
104
111
|
dateTime: string;
|
|
@@ -111,9 +118,18 @@ export type ProviderDashboardInitialBooking = {
|
|
|
111
118
|
pickupLocationId?: string | null;
|
|
112
119
|
travelerHotel?: string | null;
|
|
113
120
|
startTime?: string | null;
|
|
114
|
-
privateShuttleDetails?: {
|
|
121
|
+
privateShuttleDetails?: {
|
|
122
|
+
passengerCount?: number;
|
|
123
|
+
requestedPassengerCount?: number | null;
|
|
124
|
+
};
|
|
115
125
|
cancellationPolicyId?: string | null;
|
|
116
126
|
promoCode?: string | null;
|
|
117
127
|
additionalHoursCount?: number | null;
|
|
118
128
|
addOnSelections?: Array<{ addOnId: string; variantId?: string; quantity?: number }> | null;
|
|
129
|
+
customer?: {
|
|
130
|
+
firstName?: string | null;
|
|
131
|
+
lastName?: string | null;
|
|
132
|
+
email?: string | null;
|
|
133
|
+
phoneNumber?: string | null;
|
|
134
|
+
} | null;
|
|
119
135
|
};
|
|
@@ -18,7 +18,10 @@ import {
|
|
|
18
18
|
type Product,
|
|
19
19
|
type ReturnOption,
|
|
20
20
|
} from '../../lib/booking-api';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
filterAvailabilitiesAfterCurrentTime,
|
|
23
|
+
filterAvailabilitiesAfterPublicBookingCutoff,
|
|
24
|
+
} from '../../lib/booking/booking-cutoffs';
|
|
22
25
|
import { shouldReplacePricingConfig } from '../../lib/booking/pricing-config';
|
|
23
26
|
import { useAvailabilitiesCache, buildAvailabilitiesCacheKey } from '../../contexts/AvailabilitiesCacheContext';
|
|
24
27
|
import {
|
|
@@ -628,7 +631,7 @@ export function useStandardBookingAvailability({
|
|
|
628
631
|
});
|
|
629
632
|
|
|
630
633
|
return isAdmin
|
|
631
|
-
? currentOrFutureAvailabilities
|
|
634
|
+
? filterAvailabilitiesAfterCurrentTime(currentOrFutureAvailabilities, bookingCutoffNow)
|
|
632
635
|
: filterAvailabilitiesAfterPublicBookingCutoff(
|
|
633
636
|
currentOrFutureAvailabilities,
|
|
634
637
|
bookingCutoffNow,
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
type AddOn,
|
|
13
13
|
type AdminAmendmentOperationSnapshot,
|
|
14
14
|
type AdminAmendmentRefundDisposition,
|
|
15
|
+
type AdminAmendmentActiveAdjustmentSnapshot,
|
|
15
16
|
type AdminFeAuthoritativeReceipt,
|
|
17
|
+
type AdminPromoApplicationScope,
|
|
16
18
|
type Availability,
|
|
17
19
|
type ChangeBookingQuotePricingDriftDetail,
|
|
18
20
|
type ChangeBookingQuoteTicketPricingTrace,
|
|
@@ -41,6 +43,7 @@ import {
|
|
|
41
43
|
import type { ChangeBookingFlowProps } from './booking-flow-types';
|
|
42
44
|
import type { CheckoutModalLineItem } from './CheckoutModal';
|
|
43
45
|
import type { Currency } from './CurrencySwitcher';
|
|
46
|
+
import type { AdminAdjustmentComponentOption } from './admin-adjustment-components';
|
|
44
47
|
import {
|
|
45
48
|
findMergedAvailabilityForSelection,
|
|
46
49
|
findMergedReturnVacancies,
|
|
@@ -67,6 +70,10 @@ import {
|
|
|
67
70
|
confirmFreeAdminCustomerChange,
|
|
68
71
|
quoteAdminCustomerChangeForCheckout,
|
|
69
72
|
} from './admin-change-customer-quote-runner';
|
|
73
|
+
import {
|
|
74
|
+
buildAdminChangeV2QuoteRequest,
|
|
75
|
+
quoteAdminChangeV2ForUi,
|
|
76
|
+
} from './admin-change-v2-quote-request';
|
|
70
77
|
import {
|
|
71
78
|
reservationHoldHasExpired,
|
|
72
79
|
RESERVATION_HOLD_EXPIRED_MESSAGE,
|
|
@@ -86,6 +93,10 @@ export interface AdminChangeLatestQuote {
|
|
|
86
93
|
quoteExpiresAt?: string;
|
|
87
94
|
pricingVersion?: string;
|
|
88
95
|
quotedTotal?: number;
|
|
96
|
+
amountPreviouslyPaid?: number;
|
|
97
|
+
currentPaymentCreditTotal?: number;
|
|
98
|
+
projectedPaymentCreditTotal?: number;
|
|
99
|
+
refundCandidate?: number;
|
|
89
100
|
paymentCreditTotal?: number;
|
|
90
101
|
refundDecisionOperations?: AdminAmendmentOperationSnapshot[];
|
|
91
102
|
returnPriceTreatmentOperations?: AdminAmendmentOperationSnapshot[];
|
|
@@ -95,8 +106,11 @@ export interface AdminChangeLatestQuote {
|
|
|
95
106
|
quotePreviousTotalCents?: number;
|
|
96
107
|
quoteNewTotalCents?: number;
|
|
97
108
|
serverPreview: ChangeBookingServerPreview;
|
|
109
|
+
authoritativeItineraryDisplay?: ItineraryDisplayStep[] | null;
|
|
98
110
|
pricingDriftDetail?: ChangeBookingQuotePricingDriftDetail;
|
|
99
111
|
ticketPricingTrace?: ChangeBookingQuoteTicketPricingTrace | null;
|
|
112
|
+
selectableAdjustmentComponents?: AdminAdjustmentComponentOption[];
|
|
113
|
+
reversibleAdjustments?: AdminAmendmentActiveAdjustmentSnapshot[];
|
|
100
114
|
}
|
|
101
115
|
|
|
102
116
|
export interface UseAdminChangeCheckoutControllerParams {
|
|
@@ -136,10 +150,12 @@ export interface UseAdminChangeCheckoutControllerParams {
|
|
|
136
150
|
onChangeBooking?: ChangeBookingFlowProps['onChangeBooking'];
|
|
137
151
|
cancellationPolicyId: string | null;
|
|
138
152
|
appliedPromoCode: string | null;
|
|
153
|
+
promoApplicationScope: AdminPromoApplicationScope;
|
|
139
154
|
displayChangeFlowProposedTotalWithEditableLines: number;
|
|
140
155
|
providerPricingOverrides: AdminChangeProviderLineOverride[];
|
|
141
156
|
mergedProviderAdditionalAdjustments: AdminChangeProviderAdditionalAdjustment[];
|
|
142
157
|
adminStructuredAdjustments: NonNullable<ProviderDashboardChangeBookingPayload['structuredAdjustments']>;
|
|
158
|
+
adminReverseAdjustmentIds: string[];
|
|
143
159
|
refundDispositionsByOperationId: NonNullable<
|
|
144
160
|
ProviderDashboardChangeBookingPayload['refundDispositionsByOperationId']
|
|
145
161
|
>;
|
|
@@ -237,10 +253,12 @@ export function useAdminChangeCheckoutController({
|
|
|
237
253
|
onChangeBooking,
|
|
238
254
|
cancellationPolicyId,
|
|
239
255
|
appliedPromoCode,
|
|
256
|
+
promoApplicationScope,
|
|
240
257
|
displayChangeFlowProposedTotalWithEditableLines,
|
|
241
258
|
providerPricingOverrides,
|
|
242
259
|
mergedProviderAdditionalAdjustments,
|
|
243
260
|
adminStructuredAdjustments,
|
|
261
|
+
adminReverseAdjustmentIds,
|
|
244
262
|
refundDispositionsByOperationId,
|
|
245
263
|
providerApplyAuthoritativeReceipt,
|
|
246
264
|
onSuccess,
|
|
@@ -358,10 +376,12 @@ export function useAdminChangeCheckoutController({
|
|
|
358
376
|
cancellationPolicyId,
|
|
359
377
|
initialCancellationPolicyId: initialValues?.cancellationPolicyId ?? null,
|
|
360
378
|
appliedPromoCode,
|
|
379
|
+
promoApplicationScope,
|
|
361
380
|
newTotalAmount: displayChangeFlowProposedTotalWithEditableLines,
|
|
362
381
|
providerPricingOverrides,
|
|
363
382
|
mergedProviderAdditionalAdjustments,
|
|
364
383
|
adminStructuredAdjustments,
|
|
384
|
+
adminReverseAdjustmentIds,
|
|
365
385
|
refundDispositionsByOperationId,
|
|
366
386
|
pricingV2QuoteId: authoritativeQuote?.quoteId ?? null,
|
|
367
387
|
pricingV2QuotedTotal: authoritativeQuote?.quotedTotal ?? authoritativeQuote?.serverDisplay?.total ?? null,
|
|
@@ -461,7 +481,42 @@ export function useAdminChangeCheckoutController({
|
|
|
461
481
|
let confirmedChangeAmountDueForCheckout: number | null = null;
|
|
462
482
|
let authoritativeChangeQuoteForCheckout = latestChangeQuote;
|
|
463
483
|
|
|
464
|
-
if (
|
|
484
|
+
if (isProviderDashboardChange && isChangeBookingContext) {
|
|
485
|
+
const bookingReference = initialValues?.bookingReference?.trim();
|
|
486
|
+
if (!bookingReference) throw new Error('Missing booking reference.');
|
|
487
|
+
authoritativeChangeQuoteForCheckout = await quoteAdminChangeV2ForUi(
|
|
488
|
+
buildAdminChangeV2QuoteRequest({
|
|
489
|
+
bookingReference,
|
|
490
|
+
lastName,
|
|
491
|
+
parentProductId: product.productId,
|
|
492
|
+
optionId: availabilityProductOptionId,
|
|
493
|
+
selectedAvailability,
|
|
494
|
+
pickupLocationId,
|
|
495
|
+
returnAvailabilityId: selectedReturnOption?.returnAvailabilityId ?? null,
|
|
496
|
+
bookingItems,
|
|
497
|
+
addOnSelections,
|
|
498
|
+
cancellationPolicyId,
|
|
499
|
+
promoCode: appliedPromoCode,
|
|
500
|
+
promoApplicationScope,
|
|
501
|
+
structuredAdjustments: adminStructuredAdjustments,
|
|
502
|
+
reverseAdjustmentIds: adminReverseAdjustmentIds,
|
|
503
|
+
includeSelectableAdjustmentComponents: adminStructuredAdjustments.some(
|
|
504
|
+
(adjustment) => adjustment.scope === 'SELECTED_COMPONENTS',
|
|
505
|
+
),
|
|
506
|
+
refundDispositionsByOperationId,
|
|
507
|
+
previousPassengerCount: changeFlowInitialTicketCount,
|
|
508
|
+
previousAvailabilityId: initialValues?.availabilityId ?? null,
|
|
509
|
+
previousReturnAvailabilityId: initialValues?.returnAvailabilityId ?? null,
|
|
510
|
+
}),
|
|
511
|
+
{
|
|
512
|
+
total: changeFlowNewBookingTotal,
|
|
513
|
+
subtotal: effectiveSubtotalForCheckout,
|
|
514
|
+
tax: effectiveTax,
|
|
515
|
+
},
|
|
516
|
+
currency,
|
|
517
|
+
);
|
|
518
|
+
setLatestChangeQuote(authoritativeChangeQuoteForCheckout);
|
|
519
|
+
} else if (isCustomerSelfServeChange) {
|
|
465
520
|
const quoteResult = await quoteAdminCustomerChangeForCheckout({
|
|
466
521
|
bookingReference: initialValues?.bookingReference,
|
|
467
522
|
lastName,
|
|
@@ -8,6 +8,7 @@ interface ResetRef {
|
|
|
8
8
|
|
|
9
9
|
export interface UseAdminChangeProductResetParams {
|
|
10
10
|
selectedChangeProductId: string;
|
|
11
|
+
setQuantities: Dispatch<SetStateAction<Record<string, number>>>;
|
|
11
12
|
setSelectedAvailability: Dispatch<SetStateAction<Availability | null>>;
|
|
12
13
|
setSelectedReturnOption: Dispatch<SetStateAction<ReturnOption | null>>;
|
|
13
14
|
setAddOns: Dispatch<SetStateAction<AddOn[]>>;
|
|
@@ -21,6 +22,7 @@ export interface UseAdminChangeProductResetParams {
|
|
|
21
22
|
|
|
22
23
|
export function useAdminChangeProductReset({
|
|
23
24
|
selectedChangeProductId,
|
|
25
|
+
setQuantities,
|
|
24
26
|
setSelectedAvailability,
|
|
25
27
|
setSelectedReturnOption,
|
|
26
28
|
setAddOns,
|
|
@@ -36,6 +38,9 @@ export function useAdminChangeProductReset({
|
|
|
36
38
|
useEffect(() => {
|
|
37
39
|
if (previousSelectedChangeProductIdRef.current === selectedChangeProductId) return;
|
|
38
40
|
previousSelectedChangeProductIdRef.current = selectedChangeProductId;
|
|
41
|
+
// Ticket categories belong to the selected product family. In particular, a private
|
|
42
|
+
// RESOURCE quantity must not survive a switch to a regular ADULT/CHILD/INFANT product.
|
|
43
|
+
setQuantities({});
|
|
39
44
|
setSelectedAvailability(null);
|
|
40
45
|
setSelectedReturnOption(null);
|
|
41
46
|
setAddOns([]);
|
|
@@ -47,6 +52,7 @@ export function useAdminChangeProductReset({
|
|
|
47
52
|
setError('');
|
|
48
53
|
}, [
|
|
49
54
|
selectedChangeProductId,
|
|
55
|
+
setQuantities,
|
|
50
56
|
setSelectedAvailability,
|
|
51
57
|
setSelectedReturnOption,
|
|
52
58
|
setAddOns,
|
|
@@ -20,6 +20,7 @@ type AdminCustomReceiptLine = {
|
|
|
20
20
|
amountInput: string;
|
|
21
21
|
amountSign?: number;
|
|
22
22
|
calculation: 'FIXED_AMOUNT' | 'PERCENTAGE';
|
|
23
|
+
sourceAdjustmentId?: string;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
function addOnSelectionTotal(selections: AddOnSelection[] | null | undefined, addOns: AddOn[]): number {
|
|
@@ -220,6 +221,9 @@ export function useAdminChangeProtectedPricing({
|
|
|
220
221
|
() =>
|
|
221
222
|
roundMoney(
|
|
222
223
|
adminCustomReceiptLines.reduce((sum, line) => {
|
|
224
|
+
// Existing ledger adjustments are already included in the persisted receipt. Their
|
|
225
|
+
// edit delta is server-priced as reverse + replace and must not be added again here.
|
|
226
|
+
if (line.sourceAdjustmentId) return sum;
|
|
223
227
|
if (line.calculation !== 'FIXED_AMOUNT') return sum;
|
|
224
228
|
const raw = line.amountInput.trim();
|
|
225
229
|
if (raw === '' || raw === '+' || raw === '-') return sum;
|
|
@@ -55,7 +55,7 @@ export interface UseAdminChangeQuoteDisplayStateParams {
|
|
|
55
55
|
pickupLocationId: string | null;
|
|
56
56
|
quantities: Record<string, number>;
|
|
57
57
|
addOnSelections: AddOnSelection[];
|
|
58
|
-
|
|
58
|
+
initialAddOnQtyByKey: Map<string, number>;
|
|
59
59
|
changeFlowResolvedInitialProductOptionId: string | null;
|
|
60
60
|
selectedParentProductChanged: boolean;
|
|
61
61
|
isProviderDashboardChange: boolean;
|
|
@@ -65,6 +65,7 @@ export interface UseAdminChangeQuoteDisplayStateParams {
|
|
|
65
65
|
editableSummaryPreSubtotalDelta: number;
|
|
66
66
|
adminCustomAdjustmentTotal: number;
|
|
67
67
|
adminCustomReceiptLines: AdminCustomReceiptLine[];
|
|
68
|
+
adminReverseAdjustmentIds: string[];
|
|
68
69
|
isManualOverrideEligibleLine: (line: ProviderDashboardPricingLine) => boolean;
|
|
69
70
|
isAdmin: boolean;
|
|
70
71
|
useAdminFeAuthoritativeQuote: boolean;
|
|
@@ -99,7 +100,7 @@ export function useAdminChangeQuoteDisplayState({
|
|
|
99
100
|
pickupLocationId,
|
|
100
101
|
quantities,
|
|
101
102
|
addOnSelections,
|
|
102
|
-
|
|
103
|
+
initialAddOnQtyByKey,
|
|
103
104
|
changeFlowResolvedInitialProductOptionId,
|
|
104
105
|
selectedParentProductChanged,
|
|
105
106
|
isProviderDashboardChange,
|
|
@@ -109,6 +110,7 @@ export function useAdminChangeQuoteDisplayState({
|
|
|
109
110
|
editableSummaryPreSubtotalDelta,
|
|
110
111
|
adminCustomAdjustmentTotal,
|
|
111
112
|
adminCustomReceiptLines,
|
|
113
|
+
adminReverseAdjustmentIds,
|
|
112
114
|
isManualOverrideEligibleLine,
|
|
113
115
|
isAdmin,
|
|
114
116
|
useAdminFeAuthoritativeQuote,
|
|
@@ -321,14 +323,14 @@ export function useAdminChangeQuoteDisplayState({
|
|
|
321
323
|
pickupLocationId,
|
|
322
324
|
quantities,
|
|
323
325
|
addOnSelections,
|
|
324
|
-
|
|
326
|
+
initialAddOnQtyByKey,
|
|
325
327
|
changeFlowResolvedInitialProductOptionId,
|
|
326
328
|
productChanged: selectedParentProductChanged,
|
|
327
329
|
});
|
|
328
330
|
const hasChangeSelection =
|
|
329
|
-
isProviderDashboardChange
|
|
331
|
+
(isProviderDashboardChange
|
|
330
332
|
? changeSelectionDetails.hasOperationalChangesFromInitial
|
|
331
|
-
: changeSelectionDetails.hasChangesFromInitial;
|
|
333
|
+
: changeSelectionDetails.hasChangesFromInitial) || Boolean(appliedPromoCode);
|
|
332
334
|
|
|
333
335
|
const {
|
|
334
336
|
providerTotalsPreview,
|
|
@@ -344,8 +346,8 @@ export function useAdminChangeQuoteDisplayState({
|
|
|
344
346
|
providerQuotedLines,
|
|
345
347
|
hasChangeSelection,
|
|
346
348
|
editableSummaryPreSubtotalDelta,
|
|
347
|
-
adminCustomAdjustmentTotal,
|
|
348
349
|
adminCustomReceiptLines,
|
|
350
|
+
adminReverseAdjustmentIds,
|
|
349
351
|
isManualOverrideEligibleLine,
|
|
350
352
|
});
|
|
351
353
|
|