@voyantjs/bookings 0.81.1 → 0.81.5
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.
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* quantities **stay as the operator picked them** (1 DBL room is
|
|
19
19
|
* still 1 line, not 2).
|
|
20
20
|
*
|
|
21
|
-
* The `
|
|
22
|
-
* intent so the resolver knows when to
|
|
23
|
-
* respect an explicit choice ("manual" /
|
|
21
|
+
* The `pricingUnitSource` and `inventoryUnitSource` enums on the
|
|
22
|
+
* traveler track operator intent so the resolver knows when to
|
|
23
|
+
* re-derive ("auto") versus respect an explicit choice ("manual" /
|
|
24
|
+
* "none" for No room).
|
|
24
25
|
*
|
|
25
26
|
* No React, no DB, no HTTP — just the assignment math.
|
|
26
27
|
*
|
|
@@ -30,6 +31,8 @@ export type TravelerRole = "lead" | "adult" | "child" | "infant";
|
|
|
30
31
|
export type AssignmentRoleHint = "adult" | "child" | "infant";
|
|
31
32
|
export type BookingDraftUnitAssignmentSource = "auto" | "manual" | "none";
|
|
32
33
|
export interface BookingDraftTraveler {
|
|
34
|
+
/** Stable client-side traveler key used by wire-format travelerKeys links. */
|
|
35
|
+
clientTravelerKey?: string | null;
|
|
33
36
|
personId: string | null;
|
|
34
37
|
firstName: string;
|
|
35
38
|
lastName: string;
|
|
@@ -38,26 +41,29 @@ export interface BookingDraftTraveler {
|
|
|
38
41
|
preferredLanguage: string;
|
|
39
42
|
role: TravelerRole;
|
|
40
43
|
dateOfBirth: string | null;
|
|
44
|
+
/** option_unit_id of the person pricing tier this traveler is billed as. */
|
|
45
|
+
pricingUnitId: string | null;
|
|
46
|
+
/** option_unit_id of the room/vehicle this traveler occupies, when applicable. */
|
|
47
|
+
inventoryUnitId: string | null;
|
|
41
48
|
/**
|
|
42
|
-
*
|
|
43
|
-
* For person-priced products it carries the traveler's pricing
|
|
44
|
-
* tier; for accommodation products it carries the selected
|
|
45
|
-
* room/inventory unit. Source of intent disambiguated by
|
|
46
|
-
* `roomUnitAssignmentSource` below.
|
|
47
|
-
*/
|
|
48
|
-
roomUnitId: string | null;
|
|
49
|
-
/**
|
|
50
|
-
* Tracks operator intent around the legacy `roomUnitId` field.
|
|
49
|
+
* Tracks operator intent around `pricingUnitId`.
|
|
51
50
|
*
|
|
52
51
|
* - `auto`: derived from product shape, DOB, role hints, and
|
|
53
52
|
* selected quantity. Eligible for re-derivation on every render.
|
|
54
|
-
* - `manual`: operator explicitly clicked a category
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* - `none`:
|
|
58
|
-
* regardless of unit demand.
|
|
53
|
+
* - `manual`: operator explicitly clicked a category button. The
|
|
54
|
+
* resolver respects the value when it's in the current unit set;
|
|
55
|
+
* otherwise it re-derives.
|
|
56
|
+
* - `none`: no pricing unit should be assigned.
|
|
59
57
|
*/
|
|
60
|
-
|
|
58
|
+
pricingUnitSource?: BookingDraftUnitAssignmentSource;
|
|
59
|
+
/**
|
|
60
|
+
* Tracks operator intent around `inventoryUnitId`.
|
|
61
|
+
*
|
|
62
|
+
* - `auto`: derived from selected quantity and product shape.
|
|
63
|
+
* - `manual`: operator explicitly clicked a room/vehicle control.
|
|
64
|
+
* - `none`: operator explicitly picked "No room". Stays null.
|
|
65
|
+
*/
|
|
66
|
+
inventoryUnitSource?: BookingDraftUnitAssignmentSource;
|
|
61
67
|
}
|
|
62
68
|
export interface PricingAssignmentUnit {
|
|
63
69
|
/** Option the unit belongs to. Null for product-level units. */
|
|
@@ -82,8 +88,8 @@ export interface ResolvedBookingDraft<TTraveler extends BookingDraftTraveler> {
|
|
|
82
88
|
/**
|
|
83
89
|
* For each unit that ended up assigned, the indexes (into the input
|
|
84
90
|
* traveler array) of travelers mapped to it. Used at submit time to
|
|
85
|
-
* stamp `
|
|
86
|
-
* link items to travelers through `booking_item_travelers`.
|
|
91
|
+
* stamp stable `travelerKeys` on `booking_item` lines so the server
|
|
92
|
+
* can link items to travelers through `booking_item_travelers`.
|
|
87
93
|
*/
|
|
88
94
|
travelerIndexesByUnitId: Record<string, number[]>;
|
|
89
95
|
}
|
|
@@ -101,6 +107,7 @@ export interface ResolvableExtraLine {
|
|
|
101
107
|
unitSellAmountCents?: number | null;
|
|
102
108
|
totalSellAmountCents?: number | null;
|
|
103
109
|
clientLineKey?: string | null;
|
|
110
|
+
travelerKeys?: string[] | null;
|
|
104
111
|
travelerIndexes?: number[] | null;
|
|
105
112
|
}
|
|
106
113
|
/**
|
|
@@ -149,9 +156,9 @@ export declare function matchUnitByRoleHint<TUnit extends PricingAssignmentUnit>
|
|
|
149
156
|
* traveler room assignments still update `travelerIndexesByUnitId`
|
|
150
157
|
* so `booking_item_travelers` rows can be created.
|
|
151
158
|
*
|
|
152
|
-
* Respects
|
|
153
|
-
* - `none` →
|
|
154
|
-
* - `manual` →
|
|
159
|
+
* Respects assignment sources:
|
|
160
|
+
* - `none` → the corresponding field stays null
|
|
161
|
+
* - `manual` → the existing unit is kept when valid for the chosen option
|
|
155
162
|
* - `auto` → re-derived against current options
|
|
156
163
|
*/
|
|
157
164
|
export declare function resolveBookingDraft<TTraveler extends BookingDraftTraveler>(options: {
|
|
@@ -162,28 +169,34 @@ export declare function resolveBookingDraft<TTraveler extends BookingDraftTravel
|
|
|
162
169
|
}): ResolvedBookingDraft<TTraveler>;
|
|
163
170
|
/**
|
|
164
171
|
* Normalize per-person extras to charged traveler quantity and
|
|
165
|
-
* stamp
|
|
172
|
+
* stamp traveler links + `clientLineKey` so the server can link
|
|
166
173
|
* each extra line to the travelers it applies to via
|
|
167
174
|
* `booking_item_travelers`.
|
|
168
175
|
*
|
|
169
176
|
* Per-person mode (`pricingMode === "per_person"` or
|
|
170
177
|
* `pricedPerPerson === true`): quantity multiplied by travelerCount,
|
|
171
|
-
* `
|
|
178
|
+
* `travelerKeys` set to all travelers when stable keys are supplied;
|
|
179
|
+
* otherwise `travelerIndexes` is set as a deprecated fallback.
|
|
172
180
|
* Non-per-person lines pass through with `clientLineKey` only.
|
|
173
181
|
*/
|
|
174
182
|
export declare function resolveBookingExtraLines<TLine extends ResolvableExtraLine>(options: {
|
|
175
183
|
extraLines: readonly TLine[];
|
|
176
184
|
travelerCount: number;
|
|
185
|
+
travelerKeys?: readonly (string | null | undefined)[];
|
|
177
186
|
}): TLine[];
|
|
178
187
|
/**
|
|
179
188
|
* Project a resolved draft's traveler list into the wire-format
|
|
180
189
|
* `BookingCreateTravelerInput[]` shape the dialog submits. Derives
|
|
181
|
-
* the `travelerCategory` from DOB / role
|
|
182
|
-
*
|
|
190
|
+
* the `travelerCategory` from DOB / role.
|
|
191
|
+
*
|
|
192
|
+
* `roomUnitId` is a deprecated compatibility alias for the pricing tier
|
|
193
|
+
* option unit. Inventory placement is expressed only by item lines and their
|
|
194
|
+
* `travelerKeys`; the server accepts this field but does not persist it.
|
|
183
195
|
*/
|
|
184
196
|
export declare function travelersToRows(value: {
|
|
185
197
|
travelers: readonly BookingDraftTraveler[];
|
|
186
198
|
}, now?: Date): Array<{
|
|
199
|
+
clientTravelerKey: string | null;
|
|
187
200
|
personId: string | null;
|
|
188
201
|
firstName: string;
|
|
189
202
|
lastName: string;
|
|
@@ -205,6 +218,7 @@ export declare function travelersToRows(value: {
|
|
|
205
218
|
* implicitly maps to.
|
|
206
219
|
*/
|
|
207
220
|
export interface VerifiableTraveler {
|
|
221
|
+
clientTravelerKey?: string | null;
|
|
208
222
|
isPrimary?: boolean | null;
|
|
209
223
|
travelerCategory?: "adult" | "child" | "infant" | "senior" | "other" | null;
|
|
210
224
|
}
|
|
@@ -215,6 +229,7 @@ export interface VerifiableTraveler {
|
|
|
215
229
|
export interface VerifiableItemLine {
|
|
216
230
|
optionUnitId: string;
|
|
217
231
|
quantity: number;
|
|
232
|
+
travelerKeys?: string[] | null;
|
|
218
233
|
travelerIndexes?: number[] | null;
|
|
219
234
|
}
|
|
220
235
|
export interface BookingDraftMismatch {
|
|
@@ -243,10 +258,12 @@ export interface VerifyBookingDraftResult {
|
|
|
243
258
|
* no legitimate clients trip the warning.
|
|
244
259
|
*
|
|
245
260
|
* Notes on the reconstruction:
|
|
246
|
-
* - The wire format doesn't carry per-traveler
|
|
247
|
-
* join-table model encodes
|
|
248
|
-
* so we reconstruct
|
|
249
|
-
*
|
|
261
|
+
* - The wire format doesn't carry split per-traveler assignment
|
|
262
|
+
* fields (the join-table model encodes them through
|
|
263
|
+
* `itemLines[].travelerKeys`), so we reconstruct the relevant
|
|
264
|
+
* pricing or inventory unit by walking item lines and matching
|
|
265
|
+
* them to traveler keys. Deprecated `travelerIndexes` remain a
|
|
266
|
+
* fallback for older clients.
|
|
250
267
|
* - DOB doesn't round-trip on the wire today either; we feed the
|
|
251
268
|
* resolver the `travelerCategory` as a role hint so age-banded
|
|
252
269
|
* options can still be re-derived.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing-assignment.d.ts","sourceRoot":"","sources":["../src/pricing-assignment.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pricing-assignment.d.ts","sourceRoot":"","sources":["../src/pricing-assignment.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
* quantities **stay as the operator picked them** (1 DBL room is
|
|
19
19
|
* still 1 line, not 2).
|
|
20
20
|
*
|
|
21
|
-
* The `
|
|
22
|
-
* intent so the resolver knows when to
|
|
23
|
-
* respect an explicit choice ("manual" /
|
|
21
|
+
* The `pricingUnitSource` and `inventoryUnitSource` enums on the
|
|
22
|
+
* traveler track operator intent so the resolver knows when to
|
|
23
|
+
* re-derive ("auto") versus respect an explicit choice ("manual" /
|
|
24
|
+
* "none" for No room).
|
|
24
25
|
*
|
|
25
26
|
* No React, no DB, no HTTP — just the assignment math.
|
|
26
27
|
*
|
|
@@ -169,9 +170,9 @@ function roleHintForTraveler(traveler) {
|
|
|
169
170
|
* traveler room assignments still update `travelerIndexesByUnitId`
|
|
170
171
|
* so `booking_item_travelers` rows can be created.
|
|
171
172
|
*
|
|
172
|
-
* Respects
|
|
173
|
-
* - `none` →
|
|
174
|
-
* - `manual` →
|
|
173
|
+
* Respects assignment sources:
|
|
174
|
+
* - `none` → the corresponding field stays null
|
|
175
|
+
* - `manual` → the existing unit is kept when valid for the chosen option
|
|
175
176
|
* - `auto` → re-derived against current options
|
|
176
177
|
*/
|
|
177
178
|
export function resolveBookingDraft(options) {
|
|
@@ -193,6 +194,12 @@ export function resolveBookingDraft(options) {
|
|
|
193
194
|
else
|
|
194
195
|
unitsByOption.set(key, [unit]);
|
|
195
196
|
}
|
|
197
|
+
const primaryInventoryByOption = new Map();
|
|
198
|
+
for (const [key, optionUnits] of unitsByOption) {
|
|
199
|
+
const inventoryUnit = optionUnits.find(isInventoryUnit);
|
|
200
|
+
if (inventoryUnit)
|
|
201
|
+
primaryInventoryByOption.set(key, inventoryUnit);
|
|
202
|
+
}
|
|
196
203
|
// An option is "person-priced" when it has at least one person unit
|
|
197
204
|
// and no inventory unit (room/vehicle). That's the excursion shape:
|
|
198
205
|
// line quantities derive from travelers, not from the stepper's
|
|
@@ -217,52 +224,96 @@ export function resolveBookingDraft(options) {
|
|
|
217
224
|
}
|
|
218
225
|
const assignedForDefaulting = new Map();
|
|
219
226
|
for (const traveler of travelers) {
|
|
220
|
-
|
|
227
|
+
const inventorySource = traveler.inventoryUnitSource ?? "auto";
|
|
228
|
+
const pricingSource = traveler.pricingUnitSource ?? "auto";
|
|
229
|
+
const assignedUnitId = inventorySource !== "none" && traveler.inventoryUnitId
|
|
230
|
+
? traveler.inventoryUnitId
|
|
231
|
+
: pricingSource !== "none"
|
|
232
|
+
? traveler.pricingUnitId
|
|
233
|
+
: null;
|
|
234
|
+
if (!assignedUnitId)
|
|
221
235
|
continue;
|
|
222
|
-
const key = unitToOption.get(
|
|
236
|
+
const key = unitToOption.get(assignedUnitId);
|
|
223
237
|
if (!key)
|
|
224
238
|
continue;
|
|
225
239
|
assignedForDefaulting.set(key, (assignedForDefaulting.get(key) ?? 0) + 1);
|
|
226
240
|
}
|
|
227
241
|
const optionDemand = Array.from(totalByOption.entries());
|
|
228
242
|
const pickOptionWithDemand = () => optionDemand.find(([candidate, total]) => (assignedForDefaulting.get(candidate) ?? 0) < total)?.[0] ?? optionDemand[0]?.[0];
|
|
229
|
-
const
|
|
230
|
-
const
|
|
243
|
+
const resolvePricingUnitForTraveler = (traveler, key) => pickUnitForAge((unitsByOption.get(key) ?? []).filter(isPersonUnit), computeAgeYears(traveler.dateOfBirth, now), roleHintForTraveler(traveler));
|
|
244
|
+
const resolveTargetOption = (traveler) => {
|
|
245
|
+
const inventorySource = traveler.inventoryUnitSource ?? "auto";
|
|
246
|
+
if (inventorySource !== "none" && traveler.inventoryUnitId) {
|
|
247
|
+
const inventoryUnit = unitById.get(traveler.inventoryUnitId);
|
|
248
|
+
const key = unitToOption.get(traveler.inventoryUnitId);
|
|
249
|
+
if (key && inventoryUnit && isInventoryUnit(inventoryUnit))
|
|
250
|
+
return { key, fromDemand: false };
|
|
251
|
+
}
|
|
252
|
+
const pricingSource = traveler.pricingUnitSource ?? "auto";
|
|
253
|
+
if (pricingSource !== "none" && traveler.pricingUnitId) {
|
|
254
|
+
const pricingUnit = unitById.get(traveler.pricingUnitId);
|
|
255
|
+
const key = unitToOption.get(traveler.pricingUnitId);
|
|
256
|
+
if (key && pricingUnit && isPersonUnit(pricingUnit))
|
|
257
|
+
return { key, fromDemand: false };
|
|
258
|
+
}
|
|
231
259
|
const key = pickOptionWithDemand();
|
|
232
|
-
|
|
233
|
-
return { ...traveler, roomUnitId: null, roomUnitAssignmentSource: "auto" };
|
|
234
|
-
const unit = resolveUnitForTraveler(traveler, key);
|
|
235
|
-
if (!unit)
|
|
236
|
-
return { ...traveler, roomUnitId: null, roomUnitAssignmentSource: "auto" };
|
|
237
|
-
assignedForDefaulting.set(key, (assignedForDefaulting.get(key) ?? 0) + 1);
|
|
238
|
-
return {
|
|
239
|
-
...traveler,
|
|
240
|
-
roomUnitId: unit.optionUnitId,
|
|
241
|
-
roomUnitAssignmentSource: "auto",
|
|
242
|
-
};
|
|
260
|
+
return key ? { key, fromDemand: true } : null;
|
|
243
261
|
};
|
|
244
262
|
const nextTravelers = travelers.map((traveler) => {
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
263
|
+
const target = resolveTargetOption(traveler);
|
|
264
|
+
const pricingSource = traveler.pricingUnitSource ?? "auto";
|
|
265
|
+
const inventorySource = traveler.inventoryUnitSource ?? "auto";
|
|
266
|
+
if (!target) {
|
|
267
|
+
return {
|
|
268
|
+
...traveler,
|
|
269
|
+
pricingUnitId: null,
|
|
270
|
+
inventoryUnitId: null,
|
|
271
|
+
pricingUnitSource: pricingSource === "none" ? "none" : "auto",
|
|
272
|
+
inventoryUnitSource: inventorySource === "none" ? "none" : "auto",
|
|
273
|
+
};
|
|
248
274
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
275
|
+
const targetKey = target.key;
|
|
276
|
+
const currentPricingUnit = traveler.pricingUnitId
|
|
277
|
+
? unitById.get(traveler.pricingUnitId)
|
|
278
|
+
: undefined;
|
|
279
|
+
const currentPricingKey = traveler.pricingUnitId
|
|
280
|
+
? unitToOption.get(traveler.pricingUnitId)
|
|
281
|
+
: undefined;
|
|
282
|
+
const keepManualPricing = pricingSource === "manual" &&
|
|
283
|
+
currentPricingUnit &&
|
|
284
|
+
isPersonUnit(currentPricingUnit) &&
|
|
285
|
+
currentPricingKey === targetKey;
|
|
286
|
+
const nextPricingUnit = pricingSource === "none"
|
|
287
|
+
? null
|
|
288
|
+
: keepManualPricing
|
|
289
|
+
? currentPricingUnit
|
|
290
|
+
: (resolvePricingUnitForTraveler(traveler, targetKey) ?? null);
|
|
291
|
+
const currentInventoryUnit = traveler.inventoryUnitId
|
|
292
|
+
? unitById.get(traveler.inventoryUnitId)
|
|
293
|
+
: undefined;
|
|
294
|
+
const currentInventoryKey = traveler.inventoryUnitId
|
|
295
|
+
? unitToOption.get(traveler.inventoryUnitId)
|
|
296
|
+
: undefined;
|
|
297
|
+
const keepManualInventory = inventorySource === "manual" &&
|
|
298
|
+
currentInventoryUnit &&
|
|
299
|
+
isInventoryUnit(currentInventoryUnit) &&
|
|
300
|
+
currentInventoryKey === targetKey;
|
|
301
|
+
const targetInventoryUnit = primaryInventoryByOption.get(targetKey) ?? null;
|
|
302
|
+
const nextInventoryUnit = inventorySource === "none"
|
|
303
|
+
? null
|
|
304
|
+
: keepManualInventory
|
|
305
|
+
? currentInventoryUnit
|
|
306
|
+
: targetInventoryUnit;
|
|
307
|
+
if (target.fromDemand && (nextPricingUnit || nextInventoryUnit)) {
|
|
308
|
+
assignedForDefaulting.set(targetKey, (assignedForDefaulting.get(targetKey) ?? 0) + 1);
|
|
264
309
|
}
|
|
265
|
-
return
|
|
310
|
+
return {
|
|
311
|
+
...traveler,
|
|
312
|
+
pricingUnitId: nextPricingUnit?.optionUnitId ?? null,
|
|
313
|
+
inventoryUnitId: nextInventoryUnit?.optionUnitId ?? null,
|
|
314
|
+
pricingUnitSource: pricingSource === "none" ? "none" : keepManualPricing ? "manual" : "auto",
|
|
315
|
+
inventoryUnitSource: inventorySource === "none" ? "none" : keepManualInventory ? "manual" : "auto",
|
|
316
|
+
};
|
|
266
317
|
});
|
|
267
318
|
const next = {};
|
|
268
319
|
const travelerIndexesByUnitId = {};
|
|
@@ -275,22 +326,39 @@ export function resolveBookingDraft(options) {
|
|
|
275
326
|
const key = unitToOption.get(unitId);
|
|
276
327
|
if (!key || personPricedOptions.has(key))
|
|
277
328
|
continue;
|
|
278
|
-
|
|
329
|
+
const submittedUnit = unitById.get(unitId);
|
|
330
|
+
const targetUnitId = submittedUnit && isInventoryUnit(submittedUnit)
|
|
331
|
+
? unitId
|
|
332
|
+
: (primaryInventoryByOption.get(key)?.optionUnitId ?? unitId);
|
|
333
|
+
next[targetUnitId] = (next[targetUnitId] ?? 0) + quantity;
|
|
279
334
|
}
|
|
280
335
|
const assignedByOption = new Map();
|
|
281
336
|
for (const [index, traveler] of nextTravelers.entries()) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const
|
|
337
|
+
const pricingSource = traveler.pricingUnitSource ?? "auto";
|
|
338
|
+
const inventorySource = traveler.inventoryUnitSource ?? "auto";
|
|
339
|
+
const pricingKey = pricingSource !== "none" && traveler.pricingUnitId
|
|
340
|
+
? unitToOption.get(traveler.pricingUnitId)
|
|
341
|
+
: undefined;
|
|
342
|
+
const inventoryKey = inventorySource !== "none" && traveler.inventoryUnitId
|
|
343
|
+
? unitToOption.get(traveler.inventoryUnitId)
|
|
344
|
+
: undefined;
|
|
345
|
+
const key = inventoryKey ?? pricingKey;
|
|
285
346
|
if (!key)
|
|
286
347
|
continue;
|
|
287
|
-
const unitIndexes = travelerIndexesByUnitId[traveler.roomUnitId] ?? [];
|
|
288
|
-
unitIndexes.push(index);
|
|
289
|
-
travelerIndexesByUnitId[traveler.roomUnitId] = unitIndexes;
|
|
290
348
|
if (personPricedOptions.has(key)) {
|
|
291
|
-
|
|
349
|
+
if (!traveler.pricingUnitId || pricingSource === "none")
|
|
350
|
+
continue;
|
|
351
|
+
const unitIndexes = travelerIndexesByUnitId[traveler.pricingUnitId] ?? [];
|
|
352
|
+
unitIndexes.push(index);
|
|
353
|
+
travelerIndexesByUnitId[traveler.pricingUnitId] = unitIndexes;
|
|
354
|
+
next[traveler.pricingUnitId] = (next[traveler.pricingUnitId] ?? 0) + 1;
|
|
292
355
|
assignedByOption.set(key, (assignedByOption.get(key) ?? 0) + 1);
|
|
293
356
|
}
|
|
357
|
+
else if (traveler.inventoryUnitId && inventorySource !== "none") {
|
|
358
|
+
const unitIndexes = travelerIndexesByUnitId[traveler.inventoryUnitId] ?? [];
|
|
359
|
+
unitIndexes.push(index);
|
|
360
|
+
travelerIndexesByUnitId[traveler.inventoryUnitId] = unitIndexes;
|
|
361
|
+
}
|
|
294
362
|
}
|
|
295
363
|
// Person-priced residual: operator picked N seats but only added M
|
|
296
364
|
// travelers (M < N) → put the leftover on the option's adult unit
|
|
@@ -311,17 +379,20 @@ export function resolveBookingDraft(options) {
|
|
|
311
379
|
}
|
|
312
380
|
/**
|
|
313
381
|
* Normalize per-person extras to charged traveler quantity and
|
|
314
|
-
* stamp
|
|
382
|
+
* stamp traveler links + `clientLineKey` so the server can link
|
|
315
383
|
* each extra line to the travelers it applies to via
|
|
316
384
|
* `booking_item_travelers`.
|
|
317
385
|
*
|
|
318
386
|
* Per-person mode (`pricingMode === "per_person"` or
|
|
319
387
|
* `pricedPerPerson === true`): quantity multiplied by travelerCount,
|
|
320
|
-
* `
|
|
388
|
+
* `travelerKeys` set to all travelers when stable keys are supplied;
|
|
389
|
+
* otherwise `travelerIndexes` is set as a deprecated fallback.
|
|
321
390
|
* Non-per-person lines pass through with `clientLineKey` only.
|
|
322
391
|
*/
|
|
323
392
|
export function resolveBookingExtraLines(options) {
|
|
324
393
|
const travelerIndexes = Array.from({ length: options.travelerCount }, (_, index) => index);
|
|
394
|
+
const travelerKeys = (options.travelerKeys ?? []).filter((key) => typeof key === "string" && key.trim().length > 0);
|
|
395
|
+
const useTravelerKeys = travelerKeys.length === options.travelerCount;
|
|
325
396
|
return options.extraLines.map((line) => {
|
|
326
397
|
const perPerson = line.pricingMode === "per_person" || line.pricedPerPerson === true;
|
|
327
398
|
if (!perPerson) {
|
|
@@ -338,18 +409,22 @@ export function resolveBookingExtraLines(options) {
|
|
|
338
409
|
totalSellAmountCents: line.unitSellAmountCents == null
|
|
339
410
|
? line.totalSellAmountCents
|
|
340
411
|
: line.unitSellAmountCents * quantity,
|
|
341
|
-
travelerIndexes,
|
|
412
|
+
...(useTravelerKeys ? { travelerKeys } : { travelerIndexes }),
|
|
342
413
|
};
|
|
343
414
|
});
|
|
344
415
|
}
|
|
345
416
|
/**
|
|
346
417
|
* Project a resolved draft's traveler list into the wire-format
|
|
347
418
|
* `BookingCreateTravelerInput[]` shape the dialog submits. Derives
|
|
348
|
-
* the `travelerCategory` from DOB / role
|
|
349
|
-
*
|
|
419
|
+
* the `travelerCategory` from DOB / role.
|
|
420
|
+
*
|
|
421
|
+
* `roomUnitId` is a deprecated compatibility alias for the pricing tier
|
|
422
|
+
* option unit. Inventory placement is expressed only by item lines and their
|
|
423
|
+
* `travelerKeys`; the server accepts this field but does not persist it.
|
|
350
424
|
*/
|
|
351
425
|
export function travelersToRows(value, now = new Date()) {
|
|
352
426
|
return value.travelers.map((traveler) => ({
|
|
427
|
+
clientTravelerKey: traveler.clientTravelerKey?.trim() || null,
|
|
353
428
|
personId: traveler.personId,
|
|
354
429
|
firstName: traveler.firstName.trim(),
|
|
355
430
|
lastName: traveler.lastName.trim(),
|
|
@@ -359,7 +434,7 @@ export function travelersToRows(value, now = new Date()) {
|
|
|
359
434
|
participantType: "traveler",
|
|
360
435
|
travelerCategory: deriveDraftPaxBand(traveler, now),
|
|
361
436
|
isPrimary: traveler.role === "lead",
|
|
362
|
-
roomUnitId: traveler.
|
|
437
|
+
roomUnitId: traveler.pricingUnitSource === "none" ? null : traveler.pricingUnitId,
|
|
363
438
|
}));
|
|
364
439
|
}
|
|
365
440
|
/**
|
|
@@ -375,10 +450,12 @@ export function travelersToRows(value, now = new Date()) {
|
|
|
375
450
|
* no legitimate clients trip the warning.
|
|
376
451
|
*
|
|
377
452
|
* Notes on the reconstruction:
|
|
378
|
-
* - The wire format doesn't carry per-traveler
|
|
379
|
-
* join-table model encodes
|
|
380
|
-
* so we reconstruct
|
|
381
|
-
*
|
|
453
|
+
* - The wire format doesn't carry split per-traveler assignment
|
|
454
|
+
* fields (the join-table model encodes them through
|
|
455
|
+
* `itemLines[].travelerKeys`), so we reconstruct the relevant
|
|
456
|
+
* pricing or inventory unit by walking item lines and matching
|
|
457
|
+
* them to traveler keys. Deprecated `travelerIndexes` remain a
|
|
458
|
+
* fallback for older clients.
|
|
382
459
|
* - DOB doesn't round-trip on the wire today either; we feed the
|
|
383
460
|
* resolver the `travelerCategory` as a role hint so age-banded
|
|
384
461
|
* options can still be re-derived.
|
|
@@ -388,12 +465,27 @@ export function verifyBookingDraft(input) {
|
|
|
388
465
|
return { ok: true, mismatches: [] };
|
|
389
466
|
}
|
|
390
467
|
// Walk the submitted itemLines to recover the per-traveler unit
|
|
391
|
-
// assignment the client intended.
|
|
392
|
-
//
|
|
393
|
-
//
|
|
468
|
+
// assignment the client intended. Prefer stable `travelerKeys`
|
|
469
|
+
// when present; fall back to deprecated `travelerIndexes` for
|
|
470
|
+
// legacy clients. If neither is present, we can't verify
|
|
471
|
+
// per-traveler assignment — just compare aggregate quantities.
|
|
472
|
+
// Booking-create schema validation rejects unknown traveler keys
|
|
473
|
+
// before this verifier runs.
|
|
474
|
+
const unitById = new Map(input.units.map((unit) => [unit.optionUnitId, unit]));
|
|
475
|
+
const travelerIndexByKey = new Map();
|
|
476
|
+
for (const [index, traveler] of input.travelers.entries()) {
|
|
477
|
+
const key = traveler.clientTravelerKey?.trim();
|
|
478
|
+
if (key && !travelerIndexByKey.has(key))
|
|
479
|
+
travelerIndexByKey.set(key, index);
|
|
480
|
+
}
|
|
394
481
|
const unitByTravelerIndex = new Map();
|
|
395
482
|
for (const line of input.itemLines) {
|
|
396
|
-
|
|
483
|
+
const travelerKeys = (line.travelerKeys ?? []).filter((key) => key.trim().length > 0);
|
|
484
|
+
const keyedIndexes = travelerKeys
|
|
485
|
+
.map((key) => travelerIndexByKey.get(key.trim()))
|
|
486
|
+
.filter((index) => typeof index === "number");
|
|
487
|
+
const indexes = travelerKeys.length > 0 ? keyedIndexes : (line.travelerIndexes ?? []);
|
|
488
|
+
for (const idx of indexes) {
|
|
397
489
|
unitByTravelerIndex.set(idx, line.optionUnitId);
|
|
398
490
|
}
|
|
399
491
|
}
|
|
@@ -405,6 +497,7 @@ export function verifyBookingDraft(input) {
|
|
|
405
497
|
? cat
|
|
406
498
|
: "adult";
|
|
407
499
|
const assigned = unitByTravelerIndex.get(i);
|
|
500
|
+
const assignedUnit = assigned ? unitById.get(assigned) : undefined;
|
|
408
501
|
return {
|
|
409
502
|
personId: null,
|
|
410
503
|
firstName: "",
|
|
@@ -423,8 +516,10 @@ export function verifyBookingDraft(input) {
|
|
|
423
516
|
// value as ground truth. Otherwise the day-tour bug shape
|
|
424
517
|
// (3 travelers all manually frozen to Adult) would round-trip
|
|
425
518
|
// through the verifier unchanged.
|
|
426
|
-
|
|
427
|
-
|
|
519
|
+
pricingUnitId: assigned && assignedUnit && isPersonUnit(assignedUnit) ? assigned : null,
|
|
520
|
+
inventoryUnitId: assigned && assignedUnit && isInventoryUnit(assignedUnit) ? assigned : null,
|
|
521
|
+
pricingUnitSource: "auto",
|
|
522
|
+
inventoryUnitSource: "auto",
|
|
428
523
|
};
|
|
429
524
|
});
|
|
430
525
|
// Aggregate submitted quantities for resolver input. For
|
package/dist/validation.d.ts
CHANGED
|
@@ -333,6 +333,8 @@ export declare const convertProductSchema: z.ZodObject<{
|
|
|
333
333
|
description: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
334
334
|
unitSellAmountCents: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
335
335
|
totalSellAmountCents: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
336
|
+
travelerKeys: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
337
|
+
travelerIndexes: z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodNumber>>>;
|
|
336
338
|
}, z.core.$strip>>>;
|
|
337
339
|
}, z.core.$strip>;
|
|
338
340
|
/**
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAuCvB,eAAO,MAAM,0BAA0B;;;;;;;;iBAQrC,CAAA;AAyCF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAoB,CAAA;AACpD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA8B,CAAA;AAE9D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW5B,CAAA;AAEJ,eAAO,MAAM,0BAA0B;;;;;;;;EAQrC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;EAA0B,CAAA;AAE/D,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBjC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;iBASvC,CAAA;AAEF,eAAO,MAAM,+BAA+B;;iBAE1C,CAAA;AAEF,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/dist/validation.js
CHANGED
|
@@ -198,6 +198,8 @@ export const convertProductSchema = z
|
|
|
198
198
|
description: z.string().max(5000).optional().nullable(),
|
|
199
199
|
unitSellAmountCents: z.number().int().min(0).optional().nullable(),
|
|
200
200
|
totalSellAmountCents: z.number().int().min(0).optional().nullable(),
|
|
201
|
+
travelerKeys: z.array(z.string().min(1).max(255)).optional().nullable(),
|
|
202
|
+
travelerIndexes: z.array(z.number().int().min(0)).optional().nullable(),
|
|
201
203
|
}))
|
|
202
204
|
.optional(),
|
|
203
205
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/bookings",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -84,15 +84,15 @@
|
|
|
84
84
|
"drizzle-orm": "^0.45.2",
|
|
85
85
|
"hono": "^4.12.10",
|
|
86
86
|
"zod": "^4.3.6",
|
|
87
|
-
"@voyantjs/action-ledger": "0.81.
|
|
88
|
-
"@voyantjs/core": "0.81.
|
|
89
|
-
"@voyantjs/db": "0.81.
|
|
90
|
-
"@voyantjs/hono": "0.81.
|
|
91
|
-
"@voyantjs/utils": "0.81.
|
|
87
|
+
"@voyantjs/action-ledger": "0.81.5",
|
|
88
|
+
"@voyantjs/core": "0.81.5",
|
|
89
|
+
"@voyantjs/db": "0.81.5",
|
|
90
|
+
"@voyantjs/hono": "0.81.5",
|
|
91
|
+
"@voyantjs/utils": "0.81.5"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"typescript": "^6.0.2",
|
|
95
|
-
"@voyantjs/products": "0.81.
|
|
95
|
+
"@voyantjs/products": "0.81.5",
|
|
96
96
|
"@voyantjs/voyant-typescript-config": "0.1.0"
|
|
97
97
|
},
|
|
98
98
|
"files": [
|