@v-office/website-sdk 2.11.0 → 2.13.0
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/README.md +6 -1
- package/dist/capabilities/search.d.mts +2 -0
- package/dist/capabilities/search.mjs +2 -0
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/{client-DYAHnU5F.mjs → client-Ma0daa2H.mjs} +140 -68
- package/dist/index.d.mts +569 -344
- package/dist/index.mjs +1 -1
- package/dist/instructions/CHANGELOG.md +2 -0
- package/dist/instructions/MIGRATION.md +2 -0
- package/dist/instructions/README.md +12 -4
- package/dist/instructions/booking.md +56 -40
- package/dist/instructions/quote.md +100 -6
- package/dist/instructions/search.md +99 -12
- package/dist/instructions/versions/2.12.0/CHANGELOG.md +56 -0
- package/dist/instructions/versions/2.12.0/MIGRATION.md +194 -0
- package/dist/instructions/versions/2.13.0/CHANGELOG.md +87 -0
- package/dist/instructions/versions/2.13.0/MIGRATION.md +315 -0
- package/dist/instructions/versions/2.5.0/MIGRATION.md +3 -0
- package/dist/{quote-Cs6jGoRS.mjs → quote-Qy_affum.mjs} +4 -4
- package/dist/{rentals-CFod9H4m.mjs → rentals-BG1diZoo.mjs} +7 -4
- package/dist/{search-QlZrI7ue.mjs → search-Byi6XboR.mjs} +39 -19
- package/dist/{to-rental-highlights-B6a_fi0j.mjs → to-rental-highlights-BVikT4Iz.mjs} +4 -2
- package/dist/translations/shared/de-DE/booking.json +7 -0
- package/dist/translations/shared/en-US/booking.json +7 -0
- package/instructions/CHANGELOG.md +2 -0
- package/instructions/MIGRATION.md +2 -0
- package/instructions/README.md +12 -4
- package/instructions/booking.md +56 -40
- package/instructions/quote.md +100 -6
- package/instructions/search.md +99 -12
- package/instructions/versions/2.12.0/CHANGELOG.md +56 -0
- package/instructions/versions/2.12.0/MIGRATION.md +194 -0
- package/instructions/versions/2.13.0/CHANGELOG.md +87 -0
- package/instructions/versions/2.13.0/MIGRATION.md +315 -0
- package/instructions/versions/2.5.0/MIGRATION.md +3 -0
- package/package.json +16 -13
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Migration: 2.11.0 to 2.12.0
|
|
2
|
+
|
|
3
|
+
2.12.0 adds optional discount information to priced legacy v9 search results,
|
|
4
|
+
normalizes empty quote booking-card lines across v9 and v10, and completes v10
|
|
5
|
+
card-level pre-modifier totals across all modifier presentation paths. It also
|
|
6
|
+
rejects unsupported v9 flexible-period searches before transport and restores
|
|
7
|
+
empty-query inventory browsing on v9. Existing supported calls remain valid
|
|
8
|
+
without changes.
|
|
9
|
+
|
|
10
|
+
## 1. Reuse the Shared Discount Output
|
|
11
|
+
|
|
12
|
+
Legacy v9 now uses the same optional shape introduced for v10 in 2.11.0:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type SearchDiscount = {
|
|
16
|
+
readonly formattedOriginalTotal: string;
|
|
17
|
+
readonly applied: readonly {
|
|
18
|
+
readonly label: string;
|
|
19
|
+
readonly formattedAmount: string;
|
|
20
|
+
}[];
|
|
21
|
+
};
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
For exact-period results, read `discount` from the item:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
result.items[0]?.discount;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For nearby suggestions, read it from the individual alternative period:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
result.alternatives?.[0]?.alternativePeriods[0]?.discount;
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 2. Understand the Legacy v9 Mapping
|
|
37
|
+
|
|
38
|
+
For priced v9 results:
|
|
39
|
+
|
|
40
|
+
- `calc.total` remains the final `formattedTotal`.
|
|
41
|
+
- `discount` is present only when `calc.oTotal` is greater than `calc.total`.
|
|
42
|
+
- `discount.formattedOriginalTotal` is formatted from `calc.oTotal`.
|
|
43
|
+
- A non-empty `calc.discountName` becomes the label of the single applied entry.
|
|
44
|
+
- The applied amount is the formatted negative difference
|
|
45
|
+
`calc.total - calc.oTotal`.
|
|
46
|
+
- If the backend supplies no usable discount name, `applied` is empty while the
|
|
47
|
+
formatted original total remains available.
|
|
48
|
+
|
|
49
|
+
The SDK omits `discount` when there is no final total or when the original total is
|
|
50
|
+
not greater than the final total.
|
|
51
|
+
|
|
52
|
+
## 3. Account for Backend Detail Differences
|
|
53
|
+
|
|
54
|
+
v9 exposes one aggregated discount name and therefore returns at most one
|
|
55
|
+
`discount.applied` entry. v10 search can expose multiple `discount.applied`
|
|
56
|
+
entries. Consumers should render the array without assuming a fixed length.
|
|
57
|
+
|
|
58
|
+
Both backends return presentation-ready localized strings. Backend numeric amounts
|
|
59
|
+
and internal modifier keys are not part of the public output.
|
|
60
|
+
|
|
61
|
+
## 4. Account for Booking-Card Cleanup
|
|
62
|
+
|
|
63
|
+
Quote booking cards on both backends now omit numeric zero-value lines without
|
|
64
|
+
subitems from the `other` section, matching the existing handling of included and
|
|
65
|
+
tax sections.
|
|
66
|
+
|
|
67
|
+
- A zero-only `other` section is omitted.
|
|
68
|
+
- A mixed `other` section retains its non-zero lines unchanged.
|
|
69
|
+
- Lines with subitems remain available because they still carry descriptive
|
|
70
|
+
content.
|
|
71
|
+
|
|
72
|
+
No required booking-card property was added and the public schema remains
|
|
73
|
+
source-compatible. Runtime output can contain fewer empty rows. Sites that used a
|
|
74
|
+
zero-value row to represent a declined service should use explicit selection or
|
|
75
|
+
service state instead of inferring that state from the price breakdown.
|
|
76
|
+
|
|
77
|
+
## 5. Render v10 Quote Modifiers
|
|
78
|
+
|
|
79
|
+
On v10, an item at `bookingCardInformation.sections[].lines[].item` can include:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
{
|
|
83
|
+
modifiers?: readonly {
|
|
84
|
+
label: string;
|
|
85
|
+
amount: string;
|
|
86
|
+
}[];
|
|
87
|
+
totalBeforeModifiers?: string;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The card can also include `bookingCardInformation.totalBeforeModifiers`.
|
|
92
|
+
`appliedCharge` and `total` are the final amounts after modifiers. The
|
|
93
|
+
corresponding `totalBeforeModifiers` is the formatted amount before modifiers and
|
|
94
|
+
is omitted when there is no non-zero net modifier effect. `modifiers` is omitted
|
|
95
|
+
when the item has none; entries with the same localized label are grouped and
|
|
96
|
+
their amounts are summed before formatting.
|
|
97
|
+
|
|
98
|
+
Included, tax, and other lines attach their adjustments to `item.modifiers`.
|
|
99
|
+
Negative modifiers from backend lines that do not map to those sections may
|
|
100
|
+
instead appear as dedicated booking-card lines. In 2.12.0, card-level
|
|
101
|
+
`totalBeforeModifiers` accounts for both forms. v9 quote cards omit these fields.
|
|
102
|
+
|
|
103
|
+
Example for `de-DE`:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"bookingCardInformation": {
|
|
108
|
+
"sections": [
|
|
109
|
+
{
|
|
110
|
+
"lines": [
|
|
111
|
+
{
|
|
112
|
+
"item": {
|
|
113
|
+
"position": "Inklusivpreis",
|
|
114
|
+
"appliedCharge": "1.554,00 €",
|
|
115
|
+
"modifiers": [
|
|
116
|
+
{
|
|
117
|
+
"label": "Frühbucher/Last-Minute",
|
|
118
|
+
"amount": "-140,00 €"
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"totalBeforeModifiers": "1.694,00 €"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
"total": "1.596,70 €",
|
|
128
|
+
"totalBeforeModifiers": "1.736,70 €"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Do not assume a voucher appears as its own section line. Use
|
|
134
|
+
`quote.voucher.status` for voucher application status and the booking-card fields
|
|
135
|
+
for price presentation. To keep price arithmetic visible, render the pre-modifier
|
|
136
|
+
amount, modifier rows, and final amount separately. Whether to display or strike
|
|
137
|
+
through a reference price remains the consuming site's product and legal
|
|
138
|
+
decision.
|
|
139
|
+
|
|
140
|
+
## 6. Keep Flexible Search Disabled on v9
|
|
141
|
+
|
|
142
|
+
No configuration or supported request migration is required. Legacy v9 now rejects
|
|
143
|
+
the unsupported flexible-period keys `month`, `dates`, `nights`, and `weekend`
|
|
144
|
+
before transport instead of silently returning an unpriced item list. Keep
|
|
145
|
+
flexible search unavailable on v9 sites and use fixed `start`/`end` period
|
|
146
|
+
queries. v10 flexible search is unchanged.
|
|
147
|
+
|
|
148
|
+
The rejection is a `CoreSDKError` with operation `v9.search` and occurs before a
|
|
149
|
+
GraphQL request is sent. The public `SearchSearchInput` type remains unchanged
|
|
150
|
+
because its `query` field is an opaque query string.
|
|
151
|
+
|
|
152
|
+
This release enriches v9 search output when its existing response contains
|
|
153
|
+
sufficient discount data, removes empty quote breakdown rows from both backends,
|
|
154
|
+
and can return the existing optional card-level `totalBeforeModifiers` in
|
|
155
|
+
additional v10 cases.
|
|
156
|
+
|
|
157
|
+
## 7. Remove Dummy Occupancy from Empty v9 Searches
|
|
158
|
+
|
|
159
|
+
Legacy v9 now sends an empty backend-filter set as GraphQL `data: null` instead of
|
|
160
|
+
`data: []`. An empty query can therefore browse the first page of searchable
|
|
161
|
+
inventory under the configured rental scope:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
await sdk.live.search.search({
|
|
165
|
+
locale: "de-DE",
|
|
166
|
+
query: "",
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Remove workarounds that inject `adults=1` only to make an empty query return
|
|
171
|
+
results. Real occupancy, period, and non-empty backend filters keep their existing
|
|
172
|
+
mapping. Pagination and `limit` still apply, and an undated result does not assert
|
|
173
|
+
availability for a particular stay.
|
|
174
|
+
|
|
175
|
+
## Recommended Verification
|
|
176
|
+
|
|
177
|
+
1. Run a priced v9 exact-period search where the original total exceeds the final
|
|
178
|
+
total and verify the formatted values and label.
|
|
179
|
+
2. Verify discounted v9 alternative periods independently.
|
|
180
|
+
3. Run a v9 search without a discount and confirm existing rendering is unchanged.
|
|
181
|
+
4. Verify a missing v9 discount name produces an empty `applied` array.
|
|
182
|
+
5. Verify v9 rejects `month`, `dates`, `nights`, and `weekend` before transport.
|
|
183
|
+
6. Run an empty v9 query and confirm it returns searchable inventory without a
|
|
184
|
+
dummy occupancy value.
|
|
185
|
+
7. Recheck a discounted v10 search and confirm its existing multi-entry behavior
|
|
186
|
+
remains unchanged.
|
|
187
|
+
8. Quote a v9 and v10 rental with a zero-value `other` service and confirm the
|
|
188
|
+
empty section is absent.
|
|
189
|
+
9. Confirm a mixed `other` section retains only its non-zero lines.
|
|
190
|
+
10. Quote a discounted v10 rental and render `item.modifiers`, item-level
|
|
191
|
+
`totalBeforeModifiers`, and card-level `totalBeforeModifiers`.
|
|
192
|
+
11. Confirm a v9 quote continues to omit the modifier fields.
|
|
193
|
+
12. Verify a v10 modifier rendered as a dedicated line still contributes to the
|
|
194
|
+
card-level `totalBeforeModifiers`.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog: 2.13.0
|
|
2
|
+
|
|
3
|
+
This release adds static backend search capability discovery and replaces the
|
|
4
|
+
ambiguous flat booking payment schedule with a shared, presentation-ready payment
|
|
5
|
+
model for v9 and v10. It preserves every known remaining payment step, separates
|
|
6
|
+
contractual steps from full-payment alternatives, and keeps backend credentials
|
|
7
|
+
out of the public booking output.
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- `@v-office/website-sdk/capabilities/search` exposes pure, instance-independent
|
|
12
|
+
helpers for checking flexible-period support and the supported period query keys
|
|
13
|
+
for a backend.
|
|
14
|
+
- `BookingOutput.payment.schedule` contains the remaining contractual payment
|
|
15
|
+
steps known after booking.
|
|
16
|
+
- `BookingOutput.payment.alternatives` contains optional ways to settle the
|
|
17
|
+
complete outstanding balance.
|
|
18
|
+
- Schedule entries have a stable `kind`: `prepayment`, `remaining_payment`,
|
|
19
|
+
`installment`, or `deposit`.
|
|
20
|
+
- Full-payment alternatives use `kind: "full_amount"`.
|
|
21
|
+
- v10 booking output includes all remaining online, on-site, and external payment
|
|
22
|
+
steps instead of exposing only the next online step.
|
|
23
|
+
- v10 schedule entries can include translated `paymentAt` text derived from the
|
|
24
|
+
backend payment location and recipient.
|
|
25
|
+
- Legacy v9 now preserves its independently supplied remaining-payment amount and
|
|
26
|
+
deadline.
|
|
27
|
+
|
|
28
|
+
## Changed
|
|
29
|
+
|
|
30
|
+
- `dueOn` is now a complete translated, long-form display string such as
|
|
31
|
+
`Zahlbar bis zum 6. Februar 2027`.
|
|
32
|
+
- Schedule and alternative amounts use the `amount` field and remain
|
|
33
|
+
locale-formatted display strings.
|
|
34
|
+
- `paymentOptions` is present on a schedule entry only when the SDK can currently
|
|
35
|
+
perform that payment. Informational future, on-site, and external steps remain
|
|
36
|
+
visible without payment options.
|
|
37
|
+
- A synthesized v9 full-payment alternative no longer copies the prepayment
|
|
38
|
+
deadline. An explicit backend total deadline can still be retained.
|
|
39
|
+
- v10 initializes Adyen only for the next payable online step and the
|
|
40
|
+
full-outstanding alternative.
|
|
41
|
+
- v9 initializes Stripe only for currently payable choices.
|
|
42
|
+
- Post-booking insurance now receives the opaque booking result:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
await sdk.live.quote.bookInsurance({ quote, booking });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Removed
|
|
49
|
+
|
|
50
|
+
- `BookingOutput.paymentSchedules`
|
|
51
|
+
- Public `BookingOutput.guestToken`
|
|
52
|
+
- ISO-like or locale-short date assumptions for booking payment output
|
|
53
|
+
|
|
54
|
+
The private v9 guest token remains attached to the live opaque booking object and
|
|
55
|
+
is used internally when completing insurance. It is not enumerable or
|
|
56
|
+
serializable.
|
|
57
|
+
|
|
58
|
+
## Backend Mapping
|
|
59
|
+
|
|
60
|
+
- v9 `prepayment` becomes `kind: "prepayment"`.
|
|
61
|
+
- v9 `rest` becomes `kind: "remaining_payment"`.
|
|
62
|
+
- v9 `total` becomes a `full_amount` alternative.
|
|
63
|
+
- v10 `INSTALLMENT` becomes `kind: "installment"`.
|
|
64
|
+
- v10 `DEPOSIT` becomes `kind: "deposit"`.
|
|
65
|
+
- v10 `financials.outstanding` becomes a `full_amount` alternative when it is a
|
|
66
|
+
distinct payable choice.
|
|
67
|
+
|
|
68
|
+
## Migration Impact
|
|
69
|
+
|
|
70
|
+
This is a breaking output and insurance-input change. Consumers must:
|
|
71
|
+
|
|
72
|
+
1. Replace reads of `paymentSchedules` with `payment.schedule` and
|
|
73
|
+
`payment.alternatives`.
|
|
74
|
+
2. Read `amount` instead of the former schedule `total`.
|
|
75
|
+
3. Treat schedule `paymentOptions` as optional.
|
|
76
|
+
4. Render `dueOn`, `paymentAt`, labels, amounts, and line amounts directly without
|
|
77
|
+
reparsing or reformatting them.
|
|
78
|
+
5. Pass the live `booking` object to `bookInsurance` instead of passing
|
|
79
|
+
`bookingNumber` and `guestToken`.
|
|
80
|
+
6. Keep the booking object in memory until optional v9 insurance booking is
|
|
81
|
+
complete; private credentials do not survive JSON serialization.
|
|
82
|
+
|
|
83
|
+
The search capability API is additive. Consumers with hardcoded backend period-key
|
|
84
|
+
tables can replace them with the new helpers.
|
|
85
|
+
|
|
86
|
+
See `versions/2.13.0/MIGRATION.md`, `../../search.md`, `../../booking.md`, and
|
|
87
|
+
`../../quote.md`.
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Migration: 2.12.0 to 2.13.0
|
|
2
|
+
|
|
3
|
+
2.13.0 introduces a breaking, shared booking-payment output for v9 and v10. The
|
|
4
|
+
new model is intentionally presentation-oriented: labels, amounts, deadlines,
|
|
5
|
+
payment locations, and breakdown lines are already translated and formatted for
|
|
6
|
+
the booking locale.
|
|
7
|
+
|
|
8
|
+
## 1. Replace the Flat Payment Schedule
|
|
9
|
+
|
|
10
|
+
Before 2.13.0:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
booking.paymentSchedules;
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
From 2.13.0:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
booking.payment.schedule;
|
|
20
|
+
booking.payment.alternatives;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`payment.schedule` contains contractual payment steps. `payment.alternatives`
|
|
24
|
+
contains distinct alternatives such as paying the complete outstanding balance.
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"bookingNumber": "B-2026-0001",
|
|
31
|
+
"payment": {
|
|
32
|
+
"schedule": [
|
|
33
|
+
{
|
|
34
|
+
"kind": "prepayment",
|
|
35
|
+
"label": "Anzahlung",
|
|
36
|
+
"amount": "76,00 €",
|
|
37
|
+
"dueOn": "Zahlbar bis zum 19. August 2026",
|
|
38
|
+
"paymentOptions": [
|
|
39
|
+
{
|
|
40
|
+
"kind": "bank_transfer",
|
|
41
|
+
"label": "Überweisung",
|
|
42
|
+
"holder": "Ferienvermietung Muster GmbH",
|
|
43
|
+
"iban": "DE02 1203 0000 0000 2020 51",
|
|
44
|
+
"remittanceText": "Buchungsnummer: B-2026-0001"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"kind": "remaining_payment",
|
|
50
|
+
"label": "Restzahlung",
|
|
51
|
+
"amount": "304,00 €",
|
|
52
|
+
"dueOn": "Zahlbar bis zum 6. Februar 2027"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"alternatives": [
|
|
56
|
+
{
|
|
57
|
+
"kind": "full_amount",
|
|
58
|
+
"label": "Gesamtzahlung",
|
|
59
|
+
"amount": "380,00 €",
|
|
60
|
+
"paymentOptions": [
|
|
61
|
+
{
|
|
62
|
+
"kind": "bank_transfer",
|
|
63
|
+
"label": "Überweisung",
|
|
64
|
+
"holder": "Ferienvermietung Muster GmbH",
|
|
65
|
+
"iban": "DE02 1203 0000 0000 2020 51",
|
|
66
|
+
"remittanceText": "Buchungsnummer: B-2026-0001"
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 2. Read `amount` Instead of `total`
|
|
76
|
+
|
|
77
|
+
The old schedule-level `total` field has been renamed to `amount`:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
for (const entry of booking.payment.schedule) {
|
|
81
|
+
renderAmount(entry.amount);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The value remains a localized display string. Do not parse it for arithmetic or
|
|
86
|
+
payment initiation.
|
|
87
|
+
|
|
88
|
+
Optional `lines` continue to contain translated labels and formatted amounts:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
for (const line of entry.lines ?? []) {
|
|
92
|
+
renderBreakdownLine(line.label, line.amount);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 3. Render Schedule and Alternative Entries
|
|
97
|
+
|
|
98
|
+
To render every payment entry:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const paymentEntries = [...booking.payment.schedule, ...booking.payment.alternatives];
|
|
102
|
+
|
|
103
|
+
for (const entry of paymentEntries) {
|
|
104
|
+
renderPaymentEntry(entry);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Use the stable `kind` only for programmatic behavior. Use `label` for visible
|
|
109
|
+
text.
|
|
110
|
+
|
|
111
|
+
Schedule kinds:
|
|
112
|
+
|
|
113
|
+
- `prepayment`: a named v9 down payment.
|
|
114
|
+
- `remaining_payment`: a named v9 remaining payment.
|
|
115
|
+
- `installment`: a v10 installment step.
|
|
116
|
+
- `deposit`: a v10 deposit step.
|
|
117
|
+
|
|
118
|
+
Alternative kinds:
|
|
119
|
+
|
|
120
|
+
- `full_amount`: settle the complete currently outstanding balance.
|
|
121
|
+
|
|
122
|
+
Do not infer v9 semantics from v10 step order. A v10 installment is not
|
|
123
|
+
automatically a prepayment or remaining payment.
|
|
124
|
+
|
|
125
|
+
## 4. Treat `paymentOptions` as Capability Data
|
|
126
|
+
|
|
127
|
+
`paymentOptions` is optional on scheduled steps. Its absence means the entry is
|
|
128
|
+
informational and is not currently payable through the SDK.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
for (const option of entry.paymentOptions ?? []) {
|
|
132
|
+
if (option.kind === "bank_transfer") {
|
|
133
|
+
renderBankTransfer(option);
|
|
134
|
+
} else {
|
|
135
|
+
renderSubmitButton(() => sdk.live.booking.submitPaymentOption(option));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Do not attach payment buttons to future, on-site, or external entries merely
|
|
141
|
+
because they appear in `payment.schedule`.
|
|
142
|
+
|
|
143
|
+
`full_amount` alternatives always contain a `paymentOptions` array. The array can
|
|
144
|
+
be empty when the backend supplies no executable method.
|
|
145
|
+
|
|
146
|
+
## 5. Render Dates and Payment Locations Directly
|
|
147
|
+
|
|
148
|
+
Before 2.13.0, `dueOn` was locale-short text even though older documentation
|
|
149
|
+
showed an ISO value. Consumers sometimes attempted to parse it as
|
|
150
|
+
`YYYY-MM-DD`.
|
|
151
|
+
|
|
152
|
+
From 2.13.0, `dueOn` is a complete localized phrase:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
Zahlbar bis zum 6. Februar 2027
|
|
156
|
+
Payable until February 6, 2027
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Render it directly:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
if (entry.dueOn) renderSupportingText(entry.dueOn);
|
|
163
|
+
if (entry.paymentAt) renderSupportingText(entry.paymentAt);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Do not prepend another due-date label and do not parse or reformat these fields.
|
|
167
|
+
`paymentAt` is currently populated by v10 when payment-step location information
|
|
168
|
+
is available.
|
|
169
|
+
|
|
170
|
+
## 6. Account for the Corrected v9 Schedule
|
|
171
|
+
|
|
172
|
+
Legacy v9 now emits both authoritative contractual steps:
|
|
173
|
+
|
|
174
|
+
- `prepayment` with its own amount and deadline.
|
|
175
|
+
- `remaining_payment` with its own amount and deadline.
|
|
176
|
+
|
|
177
|
+
The `full_amount` alternative is separate. When the SDK synthesizes it from
|
|
178
|
+
prepayment plus remaining payment, it has no deadline. The SDK no longer copies
|
|
179
|
+
the prepayment deadline onto that alternative.
|
|
180
|
+
|
|
181
|
+
Consequently, code must not derive a remaining-payment deadline from
|
|
182
|
+
`payment.alternatives`.
|
|
183
|
+
|
|
184
|
+
## 7. Account for the Expanded v10 Schedule
|
|
185
|
+
|
|
186
|
+
v10 now preserves all remaining backend payment steps in
|
|
187
|
+
`payment.schedule`, including:
|
|
188
|
+
|
|
189
|
+
- `ONLINE`
|
|
190
|
+
- `ON_SITE`
|
|
191
|
+
- `EXTERN`
|
|
192
|
+
|
|
193
|
+
Only the next eligible online step receives an initialized Adyen option. Later
|
|
194
|
+
steps remain available as informational entries. The complete outstanding amount
|
|
195
|
+
can appear separately under `payment.alternatives`.
|
|
196
|
+
|
|
197
|
+
The alternative amount is the current outstanding balance, not necessarily the
|
|
198
|
+
original booking total.
|
|
199
|
+
|
|
200
|
+
## 8. Migrate Post-Booking Insurance
|
|
201
|
+
|
|
202
|
+
Before 2.13.0:
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
await sdk.live.quote.bookInsurance({
|
|
206
|
+
quote,
|
|
207
|
+
bookingNumber: booking.bookingNumber,
|
|
208
|
+
guestToken: booking.guestToken,
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
From 2.13.0:
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
await sdk.live.quote.bookInsurance({
|
|
216
|
+
quote,
|
|
217
|
+
booking,
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`guestToken` is no longer public. For v9, it is stored as private state on the
|
|
222
|
+
opaque booking object and consumed internally by the SDK.
|
|
223
|
+
|
|
224
|
+
Keep the same live booking object until insurance booking is complete:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
const booking = await sdk.live.booking.book(input);
|
|
228
|
+
|
|
229
|
+
// Do not JSON round-trip `booking` before this call.
|
|
230
|
+
const insurance = await sdk.live.quote.bookInsurance({ quote, booking });
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Spreading, serializing, reconstructing, or transferring the booking object loses
|
|
234
|
+
its private backend context. If the application must cross a page reload or
|
|
235
|
+
process boundary, complete insurance before that boundary.
|
|
236
|
+
|
|
237
|
+
## 9. Update Payment-Option Selection
|
|
238
|
+
|
|
239
|
+
Before 2.13.0:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
const option = booking.paymentSchedules[0]?.paymentOptions.find(
|
|
243
|
+
(candidate) => candidate.kind !== "bank_transfer",
|
|
244
|
+
);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
From 2.13.0:
|
|
248
|
+
|
|
249
|
+
```ts
|
|
250
|
+
const option = [...booking.payment.schedule, ...booking.payment.alternatives]
|
|
251
|
+
.flatMap((entry) => entry.paymentOptions ?? [])
|
|
252
|
+
.find((candidate) => candidate.kind !== "bank_transfer");
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Continue passing the selected structured option unchanged to
|
|
256
|
+
`submitPaymentOption`.
|
|
257
|
+
|
|
258
|
+
## 10. Handle Optional Insurance Output
|
|
259
|
+
|
|
260
|
+
`insurancePaymentOptions` is omitted when no post-booking insurance payment is
|
|
261
|
+
available:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
for (const option of booking.insurancePaymentOptions ?? []) {
|
|
265
|
+
renderInsurancePaymentOption(option);
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
This keeps v10 and bookings without selected insurance minimal.
|
|
270
|
+
|
|
271
|
+
## 11. Replace Hardcoded Search Capability Tables
|
|
272
|
+
|
|
273
|
+
This migration is optional and additive. Search UI that needs to decide which
|
|
274
|
+
period controls to render can query backend support without constructing an SDK:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import {
|
|
278
|
+
getSupportedPeriodQueryKeys,
|
|
279
|
+
supportsFlexiblePeriodSearch,
|
|
280
|
+
type BackendKind,
|
|
281
|
+
} from "@v-office/website-sdk/capabilities/search";
|
|
282
|
+
|
|
283
|
+
const shouldRenderFlexiblePeriod = (backend: BackendKind) => supportsFlexiblePeriodSearch(backend);
|
|
284
|
+
|
|
285
|
+
const supportedPeriodKeys = getSupportedPeriodQueryKeys("v9");
|
|
286
|
+
supportedPeriodKeys.has("month"); // false
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Remove local v9/v10 period-key tables in favor of these helpers. Both helpers are
|
|
290
|
+
derived from the same core definitions used by SDK search parsing, so backend
|
|
291
|
+
support changes do not require consumers to update a copied matrix.
|
|
292
|
+
|
|
293
|
+
The returned `ReadonlySet` includes supported aliases such as `from`, `till`,
|
|
294
|
+
`nights_min`, and `nights_max`. It describes individual key support; normal
|
|
295
|
+
search validation still determines whether a complete combination of keys and
|
|
296
|
+
values is executable.
|
|
297
|
+
|
|
298
|
+
## Recommended Verification
|
|
299
|
+
|
|
300
|
+
1. Book a v9 reservation with distinct prepayment and remaining-payment dates.
|
|
301
|
+
2. Confirm both entries retain their own translated long-form deadline.
|
|
302
|
+
3. Confirm a synthesized v9 `full_amount` alternative has no deadline.
|
|
303
|
+
4. Confirm future v9 remaining payment has no payment button unless the SDK
|
|
304
|
+
supplies a payment option.
|
|
305
|
+
5. Book a v10 reservation with multiple online and on-site/external payment steps.
|
|
306
|
+
6. Confirm every remaining v10 step is rendered in backend order.
|
|
307
|
+
7. Confirm only the next payable online step has an Adyen option.
|
|
308
|
+
8. Confirm the full-payment alternative displays the outstanding balance without
|
|
309
|
+
an inferred deadline.
|
|
310
|
+
9. Render both supported locales and verify all amounts, dates, locations, labels,
|
|
311
|
+
and breakdown lines are presentation-ready.
|
|
312
|
+
10. Complete v9 insurance with the live booking object and verify the private
|
|
313
|
+
credential is not present in serialized output.
|
|
314
|
+
11. If replacing a local search capability table, confirm flexible-period controls
|
|
315
|
+
remain hidden for v9 and visible for v10.
|
|
@@ -124,6 +124,9 @@ The public output type is unchanged, but v10 search cards now reflect the REST p
|
|
|
124
124
|
Starting with 2.11.0, priced v10 items and alternative periods may also include
|
|
125
125
|
optional localized `discount` details. See `../../search.md`.
|
|
126
126
|
|
|
127
|
+
Starting with 2.12.0, legacy v9 maps the same optional shape from its aggregated
|
|
128
|
+
original total and discount name when the original total exceeds the final total.
|
|
129
|
+
|
|
127
130
|
## Backend Behavior
|
|
128
131
|
|
|
129
132
|
- Fixed-period and flexible searches are priced by the REST backend; occupancy is required for priced searches.
|
|
@@ -241,12 +241,12 @@ const toSections = ({ input, guestQuoteResult, locale, translations }) => Effect
|
|
|
241
241
|
locale,
|
|
242
242
|
translations
|
|
243
243
|
});
|
|
244
|
-
const
|
|
244
|
+
const sectionsOtherWithContent = (yield* toSectionsOther({
|
|
245
245
|
input,
|
|
246
246
|
guestQuoteResult,
|
|
247
247
|
locale,
|
|
248
248
|
translations
|
|
249
|
-
});
|
|
249
|
+
})).filter(hasSectionLineContent);
|
|
250
250
|
if (hasSectionLineContent(sectionsIncluded)) sections.push({
|
|
251
251
|
lines: [sectionsIncluded],
|
|
252
252
|
displayOrder: GuestQuoteBookingCardDisplayOrder.inclusive
|
|
@@ -255,8 +255,8 @@ const toSections = ({ input, guestQuoteResult, locale, translations }) => Effect
|
|
|
255
255
|
lines: [sectionsTax],
|
|
256
256
|
displayOrder: GuestQuoteBookingCardDisplayOrder.tax
|
|
257
257
|
});
|
|
258
|
-
if (
|
|
259
|
-
lines:
|
|
258
|
+
if (sectionsOtherWithContent.length > 0) sections.push({
|
|
259
|
+
lines: sectionsOtherWithContent,
|
|
260
260
|
displayOrder: GuestQuoteBookingCardDisplayOrder.other
|
|
261
261
|
});
|
|
262
262
|
return sections;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as VofficeUnitDataFieldSchemas, d as VofficeUnitDataPropertyMetadata, f as parseVofficeFacilityData, i as toLocalizedString, l as VofficeUnitDataPropertyCategoryLabelKeys, m as parseVofficeUnitData, n as toImages, o as rentalsAllFeedbacksQuery, p as parseVofficeFeedbackData, r as toAddress, s as rentalsAllWithoutFeedbacksQuery, t as toRentalHighlights, u as VofficeUnitDataPropertyCategoryValues } from "./to-rental-highlights-
|
|
1
|
+
import { c as VofficeUnitDataFieldSchemas, d as VofficeUnitDataPropertyMetadata, f as parseVofficeFacilityData, i as toLocalizedString, l as VofficeUnitDataPropertyCategoryLabelKeys, m as parseVofficeUnitData, n as toImages, o as rentalsAllFeedbacksQuery, p as parseVofficeFeedbackData, r as toAddress, s as rentalsAllWithoutFeedbacksQuery, t as toRentalHighlights, u as VofficeUnitDataPropertyCategoryValues } from "./to-rental-highlights-BVikT4Iz.mjs";
|
|
2
2
|
import { makeTranslate, renderLabeledAttributeValue, renderResolvedCustomAttribute, toCustomAttributeList, toResolvedCustomAttributeCategoryTranslationKey } from "@v-office/sdk-core";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
//#region src/legacy-v9/parser/rentals/to-description.ts
|
|
@@ -91,9 +91,10 @@ const toRentalAttributes = ({ locale, translations, attributes, customAttributes
|
|
|
91
91
|
for (const { key, metadata } of PROPERTY_METADATA_ENTRIES) {
|
|
92
92
|
const value = knownAttributes[key];
|
|
93
93
|
if (!canRenderLabeledAttributeValue$1(value)) continue;
|
|
94
|
+
const label = yield* translate(metadata.labelKey, key);
|
|
94
95
|
const attribute = renderLabeledAttributeValue({
|
|
95
96
|
key,
|
|
96
|
-
label
|
|
97
|
+
label,
|
|
97
98
|
locale,
|
|
98
99
|
value
|
|
99
100
|
});
|
|
@@ -154,9 +155,10 @@ const toRentalVicinity = ({ locale, translations, attributes }) => Effect.gen(fu
|
|
|
154
155
|
for (const { key, metadata } of LOCATION_METADATA_ENTRIES) {
|
|
155
156
|
const value = knownAttributes[key];
|
|
156
157
|
if (!canRenderLabeledAttributeValue(value)) continue;
|
|
158
|
+
const label = yield* translate(metadata.labelKey, key);
|
|
157
159
|
const item = renderLabeledAttributeValue({
|
|
158
160
|
key,
|
|
159
|
-
label
|
|
161
|
+
label,
|
|
160
162
|
locale,
|
|
161
163
|
value
|
|
162
164
|
});
|
|
@@ -200,7 +202,8 @@ const toReviews = ({ locale, translations, rental }) => Effect.gen(function* ()
|
|
|
200
202
|
}];
|
|
201
203
|
}) ?? [];
|
|
202
204
|
if (parsedItems.length === 0) return void 0;
|
|
203
|
-
const
|
|
205
|
+
const averageRating = parsedItems.reduce((ratingSum, item) => ratingSum + item.rating, 0) / parsedItems.length;
|
|
206
|
+
const summaryRating = roundRatingUp(averageRating);
|
|
204
207
|
const summaryRatingTemplate = yield* translations.translate(locale, "reviews.summary.rating");
|
|
205
208
|
const summaryCountTemplate = yield* translations.translate(locale, "reviews.summary.count");
|
|
206
209
|
const classification = toClassification(summaryRating);
|