@wix/headless-bookings 1.0.17 → 1.0.19

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.
Files changed (43) hide show
  1. package/cjs/dist/__mocks__/booking/booking-client-service.js +4 -1
  2. package/cjs/dist/__mocks__/services/services-mocks.d.ts +13 -0
  3. package/cjs/dist/__mocks__/services/services-mocks.js +92 -1
  4. package/cjs/dist/react/core/booking/Booking.d.ts +6 -0
  5. package/cjs/dist/react/core/booking/Booking.js +2 -0
  6. package/cjs/dist/react/core/payment/Payment.d.ts +2 -1
  7. package/cjs/dist/react/core/payment/Payment.js +11 -8
  8. package/cjs/dist/react/payment/Payment.d.ts +3 -2
  9. package/cjs/dist/react/payment/Payment.js +11 -5
  10. package/cjs/dist/services/booking/book-action/buildBookingRequest.js +13 -4
  11. package/cjs/dist/services/booking/book-action/types.d.ts +6 -0
  12. package/cjs/dist/services/booking/booking.d.ts +17 -0
  13. package/cjs/dist/services/booking/booking.js +8 -0
  14. package/cjs/dist/services/index.d.ts +1 -1
  15. package/cjs/dist/services/payment/payment.d.ts +4 -1
  16. package/cjs/dist/services/payment/payment.def.d.ts +49 -1
  17. package/cjs/dist/services/payment/payment.js +107 -69
  18. package/cjs/dist/services/servicePayment.d.ts +26 -0
  19. package/cjs/dist/services/servicePayment.js +46 -0
  20. package/cjs/dist/utils/money.d.ts +12 -2
  21. package/cjs/dist/utils/money.js +30 -18
  22. package/dist/__mocks__/booking/booking-client-service.js +4 -1
  23. package/dist/__mocks__/services/services-mocks.d.ts +13 -0
  24. package/dist/__mocks__/services/services-mocks.js +91 -0
  25. package/dist/react/core/booking/Booking.d.ts +6 -0
  26. package/dist/react/core/booking/Booking.js +2 -0
  27. package/dist/react/core/payment/Payment.d.ts +2 -1
  28. package/dist/react/core/payment/Payment.js +11 -8
  29. package/dist/react/payment/Payment.d.ts +3 -2
  30. package/dist/react/payment/Payment.js +11 -5
  31. package/dist/services/booking/book-action/buildBookingRequest.js +13 -4
  32. package/dist/services/booking/book-action/types.d.ts +6 -0
  33. package/dist/services/booking/booking.d.ts +17 -0
  34. package/dist/services/booking/booking.js +8 -0
  35. package/dist/services/index.d.ts +1 -1
  36. package/dist/services/payment/payment.d.ts +4 -1
  37. package/dist/services/payment/payment.def.d.ts +49 -1
  38. package/dist/services/payment/payment.js +107 -69
  39. package/dist/services/servicePayment.d.ts +26 -0
  40. package/dist/services/servicePayment.js +40 -0
  41. package/dist/utils/money.d.ts +12 -2
  42. package/dist/utils/money.js +30 -18
  43. package/package.json +4 -4
@@ -29,18 +29,20 @@ function createMockSignalsService() {
29
29
  };
30
30
  }
31
31
  function createMockBookingService(config = {}) {
32
- const { serviceSelections = [], location = null, timezone = 'UTC', formSubmission = null, selectedPaymentOption, } = config;
32
+ const { serviceSelections = [], location = null, timezone = 'UTC', formSubmission = null, selectedPaymentOption, depositSelected, } = config;
33
33
  const serviceSelectionsSignal = mockSignal(serviceSelections);
34
34
  const locationSignal = mockSignal(location);
35
35
  const timezoneSignal = mockSignal(timezone);
36
36
  const formSubmissionSignal = mockSignal(formSubmission);
37
37
  const selectedPaymentOptionSignal = mockSignal(selectedPaymentOption);
38
+ const depositSelectedSignal = mockSignal(depositSelected);
38
39
  return {
39
40
  serviceSelections: serviceSelectionsSignal,
40
41
  location: locationSignal,
41
42
  timezone: timezoneSignal,
42
43
  formSubmission: formSubmissionSignal,
43
44
  selectedPaymentOption: selectedPaymentOptionSignal,
45
+ depositSelected: depositSelectedSignal,
44
46
  actions: {
45
47
  updateItem: vitest_1.vi.fn(),
46
48
  setItem: vitest_1.vi.fn(),
@@ -56,6 +58,7 @@ function createMockBookingService(config = {}) {
56
58
  setFormSubmission: vitest_1.vi.fn(),
57
59
  clearFormSubmission: vitest_1.vi.fn(),
58
60
  setSelectedPaymentOption: vitest_1.vi.fn(),
61
+ setDepositSelected: vitest_1.vi.fn(),
59
62
  setAllDay: vitest_1.vi.fn(),
60
63
  clearAll: vitest_1.vi.fn(),
61
64
  book: vitest_1.vi.fn(),
@@ -158,6 +158,19 @@ export declare function createLargeStaffMemberList(count: number): StaffMember[]
158
158
  * Mock service with deposit configured
159
159
  */
160
160
  export declare const mockServiceWithDeposit: Service;
161
+ /** Deposit set as a fixed amount under `depositDetails`, the newer field. */
162
+ export declare const mockServiceDepositDetailsAmount: Service;
163
+ /** Percentage deposit: `options.deposit` set, no amount anywhere on the entity. */
164
+ export declare const mockServicePercentageDeposit: Service;
165
+ /**
166
+ * Mock service with a deposit that may also be paid in full upfront — the only
167
+ * configuration where `booking.depositSelected` may be `false`.
168
+ */
169
+ export declare const mockServiceWithDepositFullUpfront: Service;
170
+ /**
171
+ * Mock VARIED-rate service with a deposit (both under `payment.varied`).
172
+ */
173
+ export declare const mockServiceVariedWithDeposit: Service;
161
174
  /**
162
175
  * Mock service with in-person payment option
163
176
  */
@@ -3,7 +3,7 @@
3
3
  * Shared mock data for booking service tests
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.mockServiceInPerson = exports.mockServiceWithDeposit = exports.mockSingleStaffMemberListConfig = exports.mockEmptyStaffMemberListConfig = exports.mockStaffMemberListConfig = exports.mockStaffMembers = exports.mockStaffMemberNoName = exports.mockStaffMemberMinimal = exports.mockStaffMember2 = exports.mockStaffMember = exports.mockAvailabilityFilter = exports.mockAvailabilityPagingMetadataLast = exports.mockAvailabilityPagingMetadata = exports.mockServicesWithAvailability = exports.mockServiceListConfigWithCategories = exports.mockCategories = exports.mockServiceConfig = exports.mockEmptyServiceListConfig = exports.mockServiceListConfigWithMore = exports.mockServiceListConfig = exports.mockPagingMetadataEmpty = exports.mockPagingMetadataWithMore = exports.mockPagingMetadata = exports.mockServices = exports.mockServiceDayRange = exports.mockServiceHourRange = exports.mockServiceFixedDuration = exports.mockServiceMinimal = exports.mockServiceCourse = exports.mockServiceClass = exports.mockServiceNoFee = exports.mockServiceCustomPrice = exports.mockServiceVariedPrice = exports.mockService = void 0;
6
+ exports.mockServiceInPerson = exports.mockServiceVariedWithDeposit = exports.mockServiceWithDepositFullUpfront = exports.mockServicePercentageDeposit = exports.mockServiceDepositDetailsAmount = exports.mockServiceWithDeposit = exports.mockSingleStaffMemberListConfig = exports.mockEmptyStaffMemberListConfig = exports.mockStaffMemberListConfig = exports.mockStaffMembers = exports.mockStaffMemberNoName = exports.mockStaffMemberMinimal = exports.mockStaffMember2 = exports.mockStaffMember = exports.mockAvailabilityFilter = exports.mockAvailabilityPagingMetadataLast = exports.mockAvailabilityPagingMetadata = exports.mockServicesWithAvailability = exports.mockServiceListConfigWithCategories = exports.mockCategories = exports.mockServiceConfig = exports.mockEmptyServiceListConfig = exports.mockServiceListConfigWithMore = exports.mockServiceListConfig = exports.mockPagingMetadataEmpty = exports.mockPagingMetadataWithMore = exports.mockPagingMetadata = exports.mockServices = exports.mockServiceDayRange = exports.mockServiceHourRange = exports.mockServiceFixedDuration = exports.mockServiceMinimal = exports.mockServiceCourse = exports.mockServiceClass = exports.mockServiceNoFee = exports.mockServiceCustomPrice = exports.mockServiceVariedPrice = exports.mockService = void 0;
7
7
  exports.createLargeServiceList = createLargeServiceList;
8
8
  exports.createLargeStaffMemberList = createLargeStaffMemberList;
9
9
  const auto_sdk_bookings_services_1 = require("@wix/auto_sdk_bookings_services");
@@ -540,6 +540,97 @@ exports.mockServiceWithDeposit = {
540
540
  },
541
541
  },
542
542
  };
543
+ /** Deposit set as a fixed amount under `depositDetails`, the newer field. */
544
+ exports.mockServiceDepositDetailsAmount = {
545
+ ...exports.mockService,
546
+ _id: 'test-service-deposit-details-amount',
547
+ name: 'Deposit Details Amount Service',
548
+ payment: {
549
+ rateType: auto_sdk_bookings_services_1.RateType.FIXED,
550
+ fixed: {
551
+ price: {
552
+ value: '100.00',
553
+ currency: 'USD',
554
+ },
555
+ depositDetails: {
556
+ amount: {
557
+ value: '25.00',
558
+ currency: 'USD',
559
+ },
560
+ },
561
+ },
562
+ options: {
563
+ online: true,
564
+ deposit: true,
565
+ },
566
+ },
567
+ };
568
+ /** Percentage deposit: `options.deposit` set, no amount anywhere on the entity. */
569
+ exports.mockServicePercentageDeposit = {
570
+ ...exports.mockService,
571
+ _id: 'test-service-percentage-deposit',
572
+ name: 'Percentage Deposit Service',
573
+ payment: {
574
+ rateType: auto_sdk_bookings_services_1.RateType.FIXED,
575
+ fixed: {
576
+ price: {
577
+ value: '10',
578
+ currency: 'USD',
579
+ },
580
+ fullUpfrontPaymentAllowed: true,
581
+ },
582
+ options: {
583
+ online: true,
584
+ inPerson: false,
585
+ deposit: true,
586
+ },
587
+ },
588
+ };
589
+ /**
590
+ * Mock service with a deposit that may also be paid in full upfront — the only
591
+ * configuration where `booking.depositSelected` may be `false`.
592
+ */
593
+ exports.mockServiceWithDepositFullUpfront = {
594
+ ...exports.mockService,
595
+ _id: 'test-service-deposit-full-upfront',
596
+ name: 'Service with Deposit and Full Upfront Allowed',
597
+ payment: {
598
+ rateType: auto_sdk_bookings_services_1.RateType.FIXED,
599
+ fixed: {
600
+ price: {
601
+ value: '100.00',
602
+ currency: 'USD',
603
+ },
604
+ deposit: {
605
+ value: '30.00',
606
+ currency: 'USD',
607
+ },
608
+ fullUpfrontPaymentAllowed: true,
609
+ },
610
+ },
611
+ };
612
+ /**
613
+ * Mock VARIED-rate service with a deposit (both under `payment.varied`).
614
+ */
615
+ exports.mockServiceVariedWithDeposit = {
616
+ ...exports.mockService,
617
+ _id: 'test-service-varied-deposit',
618
+ name: 'Varied Service with Deposit',
619
+ payment: {
620
+ rateType: auto_sdk_bookings_services_1.RateType.VARIED,
621
+ varied: {
622
+ defaultPrice: {
623
+ value: '80.00',
624
+ currency: 'USD',
625
+ },
626
+ deposit: {
627
+ value: '20.00',
628
+ currency: 'USD',
629
+ },
630
+ fullUpfrontPaymentAllowed: true,
631
+ },
632
+ },
633
+ };
543
634
  /**
544
635
  * Mock service with in-person payment option
545
636
  */
@@ -45,6 +45,12 @@ export interface BookingData {
45
45
  * heuristic applies. Set via `actions.setSelectedPaymentOption`.
46
46
  */
47
47
  selectedPaymentOption: SelectedPaymentOption | undefined;
48
+ /**
49
+ * Deposit-vs-full-upfront choice. `true` pays only the deposit now, `false`
50
+ * pays the full price now, `undefined` means not chosen. Set via
51
+ * `actions.setDepositSelected`.
52
+ */
53
+ depositSelected: boolean | undefined;
48
54
  actions: BookingServiceActions;
49
55
  }
50
56
  /**
@@ -118,6 +118,7 @@ function Data(props) {
118
118
  const timezone = bookingService.timezone.get();
119
119
  const formSubmission = bookingService.formSubmission.get();
120
120
  const selectedPaymentOption = bookingService.selectedPaymentOption.get();
121
+ const depositSelected = bookingService.depositSelected.get();
121
122
  const { actions } = bookingService;
122
123
  const location = resolveLocation(bookingLocation, serviceSelections);
123
124
  return children({
@@ -126,6 +127,7 @@ function Data(props) {
126
127
  timezone,
127
128
  formSubmission,
128
129
  selectedPaymentOption,
130
+ depositSelected,
129
131
  actions,
130
132
  });
131
133
  }
@@ -172,7 +172,8 @@ export interface ServiceOptionsProps {
172
172
  }
173
173
  /**
174
174
  * Core component that exposes service payment options via render props.
175
- * Reads isOnline, isInPerson, isDeposit from the payment service signal.
175
+ * Reads isOnline, isInPerson, isDeposit, canPayFullUpfront from the payment
176
+ * service signal.
176
177
  *
177
178
  * @component
178
179
  */
@@ -93,10 +93,12 @@ function Data(props) {
93
93
  const additionalInfoList = paymentDetails?.additionalInfo?.lineItems || [];
94
94
  const firstLineItemInfo = additionalInfoList[0];
95
95
  const customPrice = firstLineItemInfo?.customPrice || null;
96
- // Computed flags
97
- const hasTax = tax !== null && tax.amount > 0;
98
- const hasDiscount = discount !== null && discount.amount > 0;
99
- const isDeposit = payNow !== null && total !== null && payNow.amount < total.amount;
96
+ // Computed flags (amounts may be strings — compare numerically)
97
+ const hasTax = tax !== null && Number(tax.amount) > 0;
98
+ const hasDiscount = discount !== null && Number(discount.amount) > 0;
99
+ const isDeposit = payNow !== null &&
100
+ total !== null &&
101
+ Number(payNow.amount) < Number(total.amount);
100
102
  return props.children({
101
103
  subtotal,
102
104
  total,
@@ -202,7 +204,8 @@ function LineItemProvider(props) {
202
204
  }
203
205
  /**
204
206
  * Core component that exposes service payment options via render props.
205
- * Reads isOnline, isInPerson, isDeposit from the payment service signal.
207
+ * Reads isOnline, isInPerson, isDeposit, canPayFullUpfront from the payment
208
+ * service signal.
206
209
  *
207
210
  * @component
208
211
  */
@@ -229,9 +232,9 @@ function ServiceOptions(props) {
229
232
  */
230
233
  function LineItemInfo(props) {
231
234
  const { lineItem, currency } = useLineItemContext();
232
- // Computed flags
233
- const hasDiscount = lineItem.discount !== null && lineItem.discount.amount > 0;
234
- const hasDeposit = lineItem.deposit !== null && lineItem.deposit.amount > 0;
235
+ // Computed flags (amounts may be strings — compare numerically)
236
+ const hasDiscount = lineItem.discount !== null && Number(lineItem.discount.amount) > 0;
237
+ const hasDeposit = lineItem.deposit !== null && Number(lineItem.deposit.amount) > 0;
235
238
  return props.children({
236
239
  lineItem,
237
240
  currency,
@@ -210,7 +210,8 @@ export interface ServiceOptionsProps {
210
210
  *
211
211
  * Payment scenarios:
212
212
  * - `isOnline=true, isInPerson=false, isDeposit=false` → Pay now only (Due now = total)
213
- * - `isOnline=true, isInPerson=false, isDeposit=true` → Pay now + security deposit
213
+ * - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=false` → Pay now + security deposit
214
+ * - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=true` → Radio: Pay deposit now / Pay in full now
214
215
  * - `isOnline=true, isInPerson=true` → Radio: Pay Online / Pay on Arrival
215
216
  * - `isOnline=false, isInPerson=true` → Pay on arrival only
216
217
  *
@@ -223,7 +224,7 @@ export interface ServiceOptionsProps {
223
224
  * @example
224
225
  * ```tsx
225
226
  * <Payment.ServiceOptions asChild>
226
- * {({ isOnline, isInPerson, isDeposit }) => (
227
+ * {({ isOnline, isInPerson, isDeposit, canPayFullUpfront }) => (
227
228
  * // render the correct payment scenario
228
229
  * )}
229
230
  * </Payment.ServiceOptions>
@@ -183,7 +183,7 @@ exports.Total.displayName = 'Payment.Total';
183
183
  */
184
184
  exports.PayNow = react_1.default.forwardRef((props, ref) => {
185
185
  const { asChild, children, className } = props;
186
- return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payNow, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payNow, isDeposit }, "data-testid": exports.TestIds.paymentPayNow, "data-has-deposit": isDeposit, children: isDeposit && payNow && payNow.amount > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payNow })) })) }));
186
+ return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payNow, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payNow, isDeposit }, "data-testid": exports.TestIds.paymentPayNow, "data-has-deposit": isDeposit, children: isDeposit && payNow && Number(payNow.amount) > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payNow })) })) }));
187
187
  });
188
188
  exports.PayNow.displayName = 'Payment.PayNow';
189
189
  /**
@@ -198,7 +198,7 @@ exports.PayNow.displayName = 'Payment.PayNow';
198
198
  */
199
199
  exports.PayLater = react_1.default.forwardRef((props, ref) => {
200
200
  const { asChild, children, className } = props;
201
- return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payLater, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payLater, isDeposit }, "data-testid": exports.TestIds.paymentPayLater, "data-has-deposit": isDeposit, children: isDeposit && payLater && payLater.amount > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payLater })) })) }));
201
+ return ((0, jsx_runtime_1.jsx)(CorePayment.Data, { children: ({ payLater, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, className: className, customElement: children, customElementProps: { payLater, isDeposit }, "data-testid": exports.TestIds.paymentPayLater, "data-has-deposit": isDeposit, children: isDeposit && payLater && Number(payLater.amount) > 0 && ((0, jsx_runtime_1.jsx)(react_3.Money, { money: payLater })) })) }));
202
202
  });
203
203
  exports.PayLater.displayName = 'Payment.PayLater';
204
204
  /**
@@ -207,7 +207,8 @@ exports.PayLater.displayName = 'Payment.PayLater';
207
207
  *
208
208
  * Payment scenarios:
209
209
  * - `isOnline=true, isInPerson=false, isDeposit=false` → Pay now only (Due now = total)
210
- * - `isOnline=true, isInPerson=false, isDeposit=true` → Pay now + security deposit
210
+ * - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=false` → Pay now + security deposit
211
+ * - `isOnline=true, isInPerson=false, isDeposit=true, canPayFullUpfront=true` → Radio: Pay deposit now / Pay in full now
211
212
  * - `isOnline=true, isInPerson=true` → Radio: Pay Online / Pay on Arrival
212
213
  * - `isOnline=false, isInPerson=true` → Pay on arrival only
213
214
  *
@@ -220,7 +221,7 @@ exports.PayLater.displayName = 'Payment.PayLater';
220
221
  * @example
221
222
  * ```tsx
222
223
  * <Payment.ServiceOptions asChild>
223
- * {({ isOnline, isInPerson, isDeposit }) => (
224
+ * {({ isOnline, isInPerson, isDeposit, canPayFullUpfront }) => (
224
225
  * // render the correct payment scenario
225
226
  * )}
226
227
  * </Payment.ServiceOptions>
@@ -228,7 +229,12 @@ exports.PayLater.displayName = 'Payment.PayLater';
228
229
  */
229
230
  exports.ServiceOptions = react_1.default.forwardRef((props, ref) => {
230
231
  const { asChild, children } = props;
231
- return ((0, jsx_runtime_1.jsx)(CorePayment.ServiceOptions, { children: ({ isOnline, isInPerson, isDeposit }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, customElement: children, customElementProps: { isOnline, isInPerson, isDeposit }, "data-testid": exports.TestIds.paymentServiceOptions, "data-is-online": isOnline, "data-is-in-person": isInPerson, "data-is-deposit": isDeposit, children: null })) }));
232
+ return ((0, jsx_runtime_1.jsx)(CorePayment.ServiceOptions, { children: ({ isOnline, isInPerson, isDeposit, canPayFullUpfront }) => ((0, jsx_runtime_1.jsx)(react_2.AsChildSlot, { ref: ref, asChild: asChild, customElement: children, customElementProps: {
233
+ isOnline,
234
+ isInPerson,
235
+ isDeposit,
236
+ canPayFullUpfront,
237
+ }, "data-testid": exports.TestIds.paymentServiceOptions, "data-is-online": isOnline, "data-is-in-person": isInPerson, "data-is-deposit": isDeposit, "data-can-pay-full-upfront": canPayFullUpfront, children: null })) }));
232
238
  });
233
239
  exports.ServiceOptions.displayName = 'Payment.ServiceOptions';
234
240
  /**
@@ -7,6 +7,7 @@ exports.buildBookingRequest = buildBookingRequest;
7
7
  const auto_sdk_bookings_availability_time_slots_1 = require("@wix/auto_sdk_bookings_availability-time-slots");
8
8
  const auto_sdk_bookings_bookings_1 = require("@wix/auto_sdk_bookings_bookings");
9
9
  const constants_js_1 = require("../../constants.js");
10
+ const servicePayment_js_1 = require("../../servicePayment.js");
10
11
  /**
11
12
  * Derives the selected payment option from service payment settings.
12
13
  * Maps service.payment.options to booking API's selectedPaymentOption.
@@ -56,12 +57,20 @@ function buildBookingRequest(params) {
56
57
  const resource = item.timeSlot.resources?.[0] ?? item.resources?.[0];
57
58
  // Get location: prefer timeSlot.location, fallback to params.location
58
59
  const slotLocation = item.timeSlot.location ?? location;
60
+ // Consumer override (if set) wins over the service-config heuristic.
61
+ const selectedPaymentOption = params.selectedPaymentOption ?? deriveSelectedPaymentOption(item.service);
62
+ // The only state where the schema allows `false`. Outside it, omitting the key
63
+ // leaves the server default in place.
64
+ const depositSelectedApplies = params.depositSelected !== undefined &&
65
+ selectedPaymentOption === 'ONLINE' &&
66
+ (0, servicePayment_js_1.requiresDeposit)(item.service) &&
67
+ (0, servicePayment_js_1.isFullUpfrontPaymentAllowed)(item.service);
59
68
  return {
60
69
  booking: {
61
- // Payment option: consumer override (if set) wins over the
62
- // service-config heuristic.
63
- selectedPaymentOption: params.selectedPaymentOption ??
64
- deriveSelectedPaymentOption(item.service),
70
+ selectedPaymentOption,
71
+ ...(depositSelectedApplies && {
72
+ depositSelected: params.depositSelected,
73
+ }),
65
74
  // Participants
66
75
  totalParticipants: item.totalParticipants || 1,
67
76
  // App that created the booking (used to filter bookings by source app).
@@ -59,6 +59,12 @@ export interface BookActionParams {
59
59
  * service. When omitted, the existing service-config heuristic applies.
60
60
  */
61
61
  selectedPaymentOption?: SelectedPaymentOption;
62
+ /**
63
+ * Optional consumer choice: `true` pays only the deposit now, `false` pays the
64
+ * full price now. Dropped unless the booking is ONLINE and the service has a
65
+ * deposit with `fullUpfrontPaymentAllowed`. Omit to keep the server default.
66
+ */
67
+ depositSelected?: boolean;
62
68
  /**
63
69
  * DAY-range only. When `true`, the picked per-day slots are collapsed into a
64
70
  * single Booking spanning the whole range (`firstSlot.startDate ->
@@ -89,6 +89,12 @@ export interface BookingServiceActions {
89
89
  * is cleared and the heuristic applies again.
90
90
  */
91
91
  setSelectedPaymentOption(value: SelectedPaymentOption | null): void;
92
+ /**
93
+ * Set (or clear with `undefined`) the deposit-vs-full-upfront choice. `true`
94
+ * charges only the deposit now, `false` charges the full price now. Gate the UI
95
+ * on `Payment.ServiceOptions`' `isDeposit && canPayFullUpfront`.
96
+ */
97
+ setDepositSelected(value: boolean | undefined): void;
92
98
  /**
93
99
  * Toggle the DAY-range `allDay` flag. When `true`, `book()` collapses the
94
100
  * picked per-day slots into one range-spanning Booking created via
@@ -117,6 +123,12 @@ export interface BookingService {
117
123
  * service-config heuristic. Set to `'ONLINE'` or `'OFFLINE'` to override.
118
124
  */
119
125
  selectedPaymentOption: Signal<SelectedPaymentOption | undefined>;
126
+ /**
127
+ * Signal containing the deposit-vs-full-upfront choice. `true` pays only the
128
+ * deposit now, `false` pays the full price now. `undefined` means "not chosen"
129
+ * — `book()` omits the field and the preview keeps its deposit default.
130
+ */
131
+ depositSelected: Signal<boolean | undefined>;
120
132
  /** Actions for modifying booking state */
121
133
  actions: BookingServiceActions;
122
134
  }
@@ -146,6 +158,11 @@ export interface BookingServiceConfig {
146
158
  * service-config heuristic; set to `'ONLINE'` or `'OFFLINE'` to override.
147
159
  */
148
160
  selectedPaymentOption?: SelectedPaymentOption;
161
+ /**
162
+ * Optional initial deposit-vs-full-upfront choice. Omit to keep the server's
163
+ * default.
164
+ */
165
+ depositSelected?: boolean;
149
166
  /** Optional app ID override for the catalog reference. Defaults to the bookings app ID. */
150
167
  appId?: string;
151
168
  /**
@@ -74,6 +74,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
74
74
  const timezoneSignal = signalsService.signal(config.timezone ?? getClientTimezone());
75
75
  const formSubmissionSignal = signalsService.signal(config.formSubmission || null);
76
76
  const selectedPaymentOptionSignal = signalsService.signal(config.selectedPaymentOption);
77
+ const depositSelectedSignal = signalsService.signal(config.depositSelected);
77
78
  // Internal-only signal: set via `setAllDay`, read by `book()`. Not
78
79
  // exposed on the service surface — consumers derive and push the value
79
80
  // (e.g. from the picker's selection mode), so there's no read-back.
@@ -176,6 +177,10 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
176
177
  setSelectedPaymentOption(value) {
177
178
  selectedPaymentOptionSignal.set(value ?? undefined);
178
179
  },
180
+ // Deposit vs full upfront action
181
+ setDepositSelected(value) {
182
+ depositSelectedSignal.set(value);
183
+ },
179
184
  // All-day (DAY-range) action
180
185
  setAllDay(value) {
181
186
  allDaySignal.set(value);
@@ -195,6 +200,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
195
200
  const location = locationSignal.get();
196
201
  const timezone = timezoneSignal.get();
197
202
  const selectedPaymentOption = selectedPaymentOptionSignal.get();
203
+ const depositSelected = depositSelectedSignal.get();
198
204
  const allDay = allDaySignal.get();
199
205
  // Validation happens inside executeBookAction
200
206
  return (0, bookAction_js_1.executeBookAction)({
@@ -205,6 +211,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
205
211
  appId: config.appId,
206
212
  sourceAppId: config.sourceAppId,
207
213
  selectedPaymentOption,
214
+ depositSelected,
208
215
  allDay,
209
216
  });
210
217
  },
@@ -215,6 +222,7 @@ exports.BookingService = services_definitions_1.implementService.withConfig()(ex
215
222
  timezone: timezoneSignal,
216
223
  formSubmission: formSubmissionSignal,
217
224
  selectedPaymentOption: selectedPaymentOptionSignal,
225
+ depositSelected: depositSelectedSignal,
218
226
  actions,
219
227
  };
220
228
  });
@@ -9,6 +9,6 @@ export { ServiceListService, ServiceListServiceDefinition, type ServiceListServi
9
9
  export { SYNTHETIC_CUSTOM_ID, SYNTHETIC_CUSTOMER_ID, AvailabilityLocationType, type ServiceWithAvailabilityItem, type AvailabilityFilter, type Attribute, type AvailabilityLocation, } from '../api/query-services/index.js';
10
10
  export { executeBookAction, canBook, buildBookingRequest, buildCartRequest, buildDayRangeBookingRequest, createBookingsForCart, isDayRangeService, getDayRangeBounds, type CanBookParams, type BookResult, type BookingError, type BookActionParams, type BookChildProps, type BookProps, type BuildCartParams, type BuildDayRangeBookingRequest, type CreatedBookings, type DayRangeBounds, } from './booking/book-action/index.js';
11
11
  export { BookingFormService, BookingFormServiceDefinition, type BookingFormServiceAPI, type BookingFormServiceConfig, } from './booking-form/booking-form.js';
12
- export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, type ServicePaymentOptions, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
12
+ export { PaymentService, PaymentServiceDefinition, type PaymentServiceAPI, type PaymentServiceConfig, type PaymentDetails, type PricingServiceSelection, type LineItemAdditionalInfo, type AppliedAdditionalFee, type PreviewPriceInfo, type ServicePaymentOptions, loadPaymentConfig, type SuccessPaymentConfigResult, type ErrorPaymentConfigResult, } from './payment/payment.js';
13
13
  export { LocationListService, LocationListServiceDefinition, LocationType, loadLocationListServiceInitialData, locationListServiceBinding, type LocationListServiceAPI, type LocationListServiceConfig, type LocationListActions, type Location, type LoadLocationListServiceResult, getLocationById, } from './location-list/location-list.js';
14
14
  export { StaffMemberListService, StaffMemberListServiceDefinition, loadStaffMemberListServiceInitialData, staffMemberListServiceBinding, type StaffMemberListServiceAPI, type StaffMemberListServiceConfig, type StaffMemberListActions, type StaffMemberData, type LoadStaffMemberListServiceResult, } from './staff-member-list/staff-member-list.js';
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { type PaymentServiceConfig, type PaymentServiceInternalConfig, type PricingServiceSelection } from './payment.def.js';
7
7
  import type { SelectedPaymentOption } from '../booking/book-action/types.js';
8
- export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type PricingServiceSelection, type ServicePaymentOptions, } from './payment.def.js';
8
+ export { PaymentServiceDefinition, type PaymentServiceConfig, type PaymentDetails, type LineItemAdditionalInfo, type AppliedAdditionalFee, type PreviewPriceInfo, type PricingServiceSelection, type ServicePaymentOptions, } from './payment.def.js';
9
9
  export type { PaymentServiceAPI, PaymentServiceInternalConfig, } from './payment.def.js';
10
10
  export declare const PaymentService: import("@wix/services-definitions").ServiceFactory<string & {
11
11
  __api: import("./payment.def.js").PaymentServiceAPI;
@@ -28,9 +28,12 @@ export type ErrorPaymentConfigResult = {
28
28
  * @param params.totalParticipants - Number of participants (default: 1)
29
29
  * @param params.selectedPaymentOption - Optional consumer-selected payment option;
30
30
  * overrides the service-config heuristic on each line item's `paymentOption`.
31
+ * @param params.depositSelected - Optional deposit-vs-full-upfront choice; `false`
32
+ * resolves a deposit service to full payment. Omit to keep the deposit default.
31
33
  */
32
34
  export declare function loadPaymentConfig(params: {
33
35
  pricingServiceSelections: PricingServiceSelection[];
34
36
  totalParticipants?: number;
35
37
  selectedPaymentOption?: SelectedPaymentOption;
38
+ depositSelected?: boolean;
36
39
  }): Promise<SuccessPaymentConfigResult | ErrorPaymentConfigResult>;
@@ -5,6 +5,7 @@
5
5
  import type { Signal } from '@wix/services-definitions/core-services/signals';
6
6
  import type { CalculateTotalsResponse } from '@wix/auto_sdk_ecom_totals-calculator';
7
7
  import type { Service } from '@wix/auto_sdk_bookings_services';
8
+ import type { BookingLineItem, PriceInfo } from '@wix/auto_sdk_bookings_pricing';
8
9
  import type { SelectedPaymentOption } from '../booking/book-action/types.js';
9
10
  import type { ServiceSelectionTimeSlot } from '../booking/booking.js';
10
11
  /**
@@ -16,13 +17,47 @@ export interface ServicePaymentOptions {
16
17
  isOnline: boolean;
17
18
  /** Customer can pay in person (on arrival) */
18
19
  isInPerson: boolean;
19
- /** A deposit is required at booking time */
20
+ /**
21
+ * A deposit is required at booking time — including percentage deposits, which
22
+ * set no amount. For the amount use `Payment.PayNow` / `Payment.PayLater`.
23
+ */
20
24
  isDeposit: boolean;
25
+ /**
26
+ * Customers may pay the full price upfront instead of only the deposit.
27
+ * Meaningful only with `isDeposit`; together they gate the
28
+ * deposit-vs-pay-in-full toggle.
29
+ */
30
+ canPayFullUpfront: boolean;
21
31
  }
22
32
  /**
23
33
  * Payment option for line items
24
34
  */
25
35
  export type PaymentOption = 'FULL_PAYMENT_ONLINE' | 'FULL_PAYMENT_OFFLINE' | 'DEPOSIT_ONLINE';
36
+ /**
37
+ * An additional fee pricing applied to a booking line, as served.
38
+ */
39
+ export interface AppliedAdditionalFee {
40
+ /** The service's additional fee ID. */
41
+ feeId?: string;
42
+ /** Units the fee was charged for (1 for a per-reservation fee). */
43
+ units?: number;
44
+ /** The fee amount for this line. */
45
+ amount?: number;
46
+ }
47
+ /**
48
+ * `PriceInfo` with the additional-fee fields `previewPrice` serves, which the
49
+ * public pricing SDK types don't declare (they are `@internal` there). Types
50
+ * only: the values are the response as served.
51
+ */
52
+ export interface PreviewPriceInfo extends PriceInfo {
53
+ bookingLineItems?: (BookingLineItem & {
54
+ additionalFees?: AppliedAdditionalFee[];
55
+ })[];
56
+ /** Sum of all lines' additional fees. */
57
+ totalAdditionalFees?: number | null;
58
+ /** `calculatedPrice` plus `totalAdditionalFees`. */
59
+ calculatedPriceWithFees?: number | null;
60
+ }
26
61
  /**
27
62
  * Additional computed info for a line item (not in SDK response)
28
63
  */
@@ -31,6 +66,14 @@ export interface LineItemAdditionalInfo {
31
66
  lineItemId: string;
32
67
  /** Custom price (for CUSTOM rate type services) */
33
68
  customPrice?: string;
69
+ /**
70
+ * The raw `previewPrice` response for this line, as served — for fields the
71
+ * payment service does not read. Not the amounts charged: those (including
72
+ * a capped deposit) come from `response`. Set only when the line was priced
73
+ * by `previewPrice` (duration-range services, or a deposit the server
74
+ * resolves).
75
+ */
76
+ priceInfo?: PreviewPriceInfo;
34
77
  }
35
78
  /**
36
79
  * Payment calculation result with SDK response and additional computed info
@@ -83,6 +126,11 @@ export interface PaymentServiceInternalConfig extends PaymentServiceConfig {
83
126
  * set, overrides the service-config heuristic in line item `paymentOption`.
84
127
  */
85
128
  selectedPaymentOption?: SelectedPaymentOption;
129
+ /**
130
+ * Deposit-vs-full-upfront choice for lazy loading. `false` resolves a deposit
131
+ * service to full payment instead of `DEPOSIT_ONLINE`.
132
+ */
133
+ depositSelected?: boolean;
86
134
  }
87
135
  export interface PaymentServiceAPI {
88
136
  paymentDetailsSignal: Signal<PaymentDetails | null>;