@voyantjs/availability 0.69.1 → 0.71.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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/routes-allocation.d.ts +2 -0
- package/dist/routes-allocation.d.ts.map +1 -1
- package/dist/service-allocation-automation.d.ts +13 -1
- package/dist/service-allocation-automation.d.ts.map +1 -1
- package/dist/service-allocation-automation.js +113 -0
- package/dist/service-allocation.d.ts +48 -0
- package/dist/service-allocation.d.ts.map +1 -1
- package/dist/service-allocation.js +205 -71
- package/dist/validation.d.ts +32 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +23 -0
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,6 @@ export { allocationAuditLog, allocationResources, availabilityCloseouts, availab
|
|
|
11
11
|
export { getSlotResourceAvailability, getSlotsResourceAvailability, type PlannedAllocation, type ResourceCapacityViolation, type SlotResourceAvailability, validateSlotAllocationCapacity, } from "./service-allocation.js";
|
|
12
12
|
export { type MaterializeSlotResourcesFromTemplatesOptions, materializeSlotResourcesFromTemplateDefaults, } from "./service-allocation-automation.js";
|
|
13
13
|
export { allocationExportFilename, buildAllocationPassengersCsv, buildAllocationRoomingCsv, } from "./service-allocation-exports.js";
|
|
14
|
-
export { allocationAuditLogQuerySchema, allocationAutomationSchema, assignTravelerAllocationSchema, availabilityCloseoutListQuerySchema, availabilityOverviewQuerySchema, availabilityPickupPointListQuerySchema, availabilityRuleListQuerySchema, availabilitySlotListQuerySchema, availabilitySlotPickupListQuerySchema, availabilityStartTimeListQuerySchema, customPickupAreaListQuerySchema, insertAllocationResourceSchema, insertAvailabilityCloseoutSchema, insertAvailabilityPickupPointSchema, insertAvailabilityRuleSchema, insertAvailabilitySlotPickupSchema, insertAvailabilitySlotSchema, insertAvailabilityStartTimeSchema, insertCustomPickupAreaSchema, insertLocationPickupTimeSchema, insertPickupGroupSchema, insertPickupLocationSchema, insertProductMeetingConfigSchema, locationPickupTimeListQuerySchema, pairSharingGroupSchema, pickupGroupListQuerySchema, pickupLocationListQuerySchema, productMeetingConfigListQuerySchema, updateAllocationResourceSchema, updateAvailabilityCloseoutSchema, updateAvailabilityPickupPointSchema, updateAvailabilityRuleSchema, updateAvailabilitySlotPickupSchema, updateAvailabilitySlotSchema, updateAvailabilityStartTimeSchema, updateCustomPickupAreaSchema, updateLocationPickupTimeSchema, updatePickupGroupSchema, updatePickupLocationSchema, updateProductMeetingConfigSchema, updateSharingGroupLabelSchema, updateTravelerSharingGroupSchema, upsertResourceTemplateSchema, } from "./validation.js";
|
|
14
|
+
export { allocationAuditLogQuerySchema, allocationAutomationSchema, assignTravelerAllocationSchema, availabilityCloseoutListQuerySchema, availabilityOverviewQuerySchema, availabilityPickupPointListQuerySchema, availabilityRuleListQuerySchema, availabilitySlotListQuerySchema, availabilitySlotPickupListQuerySchema, availabilityStartTimeListQuerySchema, customPickupAreaListQuerySchema, insertAllocationResourceSchema, insertAvailabilityCloseoutSchema, insertAvailabilityPickupPointSchema, insertAvailabilityRuleSchema, insertAvailabilitySlotPickupSchema, insertAvailabilitySlotSchema, insertAvailabilityStartTimeSchema, insertCustomPickupAreaSchema, insertLocationPickupTimeSchema, insertPickupGroupSchema, insertPickupLocationSchema, insertProductMeetingConfigSchema, locationPickupTimeListQuerySchema, pairSharingGroupSchema, pickupGroupListQuerySchema, pickupLocationListQuerySchema, productMeetingConfigListQuerySchema, type SeatLayoutCell, type SeatLayoutSpec, seatLayoutCellSchema, seatLayoutSpecSchema, updateAllocationResourceSchema, updateAvailabilityCloseoutSchema, updateAvailabilityPickupPointSchema, updateAvailabilityRuleSchema, updateAvailabilitySlotPickupSchema, updateAvailabilitySlotSchema, updateAvailabilityStartTimeSchema, updateCustomPickupAreaSchema, updateLocationPickupTimeSchema, updatePickupGroupSchema, updatePickupLocationSchema, updateProductMeetingConfigSchema, updateSharingGroupLabelSchema, updateTravelerSharingGroupSchema, upsertResourceTemplateSchema, } from "./validation.js";
|
|
15
15
|
export { availabilityService };
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAElD,YAAY,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAE9E,eAAO,MAAM,kBAAkB,EAAE,MAGhC,CAAA;AAED,eAAO,MAAM,sBAAsB,EAAE,UAIpC,CAAA;AAED,OAAO,EACL,+BAA+B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,KAAK,gCAAgC,EACrC,KAAK,+BAA+B,EACpC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,gCAAgC,EAChC,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,6BAA6B,EAC7B,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,8BAA8B,EAC9B,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,8BAA8B,GAC/B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,KAAK,4CAA4C,EACjD,4CAA4C,GAC7C,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,mCAAmC,EACnC,+BAA+B,EAC/B,sCAAsC,EACtC,+BAA+B,EAC/B,+BAA+B,EAC/B,qCAAqC,EACrC,oCAAoC,EACpC,+BAA+B,EAC/B,8BAA8B,EAC9B,gCAAgC,EAChC,mCAAmC,EACnC,4BAA4B,EAC5B,kCAAkC,EAClC,4BAA4B,EAC5B,iCAAiC,EACjC,4BAA4B,EAC5B,8BAA8B,EAC9B,uBAAuB,EACvB,0BAA0B,EAC1B,gCAAgC,EAChC,iCAAiC,EACjC,sBAAsB,EACtB,0BAA0B,EAC1B,6BAA6B,EAC7B,mCAAmC,EACnC,8BAA8B,EAC9B,gCAAgC,EAChC,mCAAmC,EACnC,4BAA4B,EAC5B,kCAAkC,EAClC,4BAA4B,EAC5B,iCAAiC,EACjC,4BAA4B,EAC5B,8BAA8B,EAC9B,uBAAuB,EACvB,0BAA0B,EAC1B,gCAAgC,EAChC,6BAA6B,EAC7B,gCAAgC,EAChC,4BAA4B,GAC7B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAElD,YAAY,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAE9E,eAAO,MAAM,kBAAkB,EAAE,MAGhC,CAAA;AAED,eAAO,MAAM,sBAAsB,EAAE,UAIpC,CAAA;AAED,OAAO,EACL,+BAA+B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,KAAK,gCAAgC,EACrC,KAAK,+BAA+B,EACpC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,wBAAwB,EACxB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,gCAAgC,EAChC,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,6BAA6B,EAC7B,iBAAiB,GAClB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,8BAA8B,EAC9B,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,8BAA8B,GAC/B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,KAAK,4CAA4C,EACjD,4CAA4C,GAC7C,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,mCAAmC,EACnC,+BAA+B,EAC/B,sCAAsC,EACtC,+BAA+B,EAC/B,+BAA+B,EAC/B,qCAAqC,EACrC,oCAAoC,EACpC,+BAA+B,EAC/B,8BAA8B,EAC9B,gCAAgC,EAChC,mCAAmC,EACnC,4BAA4B,EAC5B,kCAAkC,EAClC,4BAA4B,EAC5B,iCAAiC,EACjC,4BAA4B,EAC5B,8BAA8B,EAC9B,uBAAuB,EACvB,0BAA0B,EAC1B,gCAAgC,EAChC,iCAAiC,EACjC,sBAAsB,EACtB,0BAA0B,EAC1B,6BAA6B,EAC7B,mCAAmC,EACnC,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,8BAA8B,EAC9B,gCAAgC,EAChC,mCAAmC,EACnC,4BAA4B,EAC5B,kCAAkC,EAClC,4BAA4B,EAC5B,iCAAiC,EACjC,4BAA4B,EAC5B,8BAA8B,EAC9B,uBAAuB,EACvB,0BAA0B,EAC1B,gCAAgC,EAChC,6BAA6B,EAC7B,gCAAgC,EAChC,4BAA4B,GAC7B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -15,5 +15,5 @@ export { allocationAuditLog, allocationResources, availabilityCloseouts, availab
|
|
|
15
15
|
export { getSlotResourceAvailability, getSlotsResourceAvailability, validateSlotAllocationCapacity, } from "./service-allocation.js";
|
|
16
16
|
export { materializeSlotResourcesFromTemplateDefaults, } from "./service-allocation-automation.js";
|
|
17
17
|
export { allocationExportFilename, buildAllocationPassengersCsv, buildAllocationRoomingCsv, } from "./service-allocation-exports.js";
|
|
18
|
-
export { allocationAuditLogQuerySchema, allocationAutomationSchema, assignTravelerAllocationSchema, availabilityCloseoutListQuerySchema, availabilityOverviewQuerySchema, availabilityPickupPointListQuerySchema, availabilityRuleListQuerySchema, availabilitySlotListQuerySchema, availabilitySlotPickupListQuerySchema, availabilityStartTimeListQuerySchema, customPickupAreaListQuerySchema, insertAllocationResourceSchema, insertAvailabilityCloseoutSchema, insertAvailabilityPickupPointSchema, insertAvailabilityRuleSchema, insertAvailabilitySlotPickupSchema, insertAvailabilitySlotSchema, insertAvailabilityStartTimeSchema, insertCustomPickupAreaSchema, insertLocationPickupTimeSchema, insertPickupGroupSchema, insertPickupLocationSchema, insertProductMeetingConfigSchema, locationPickupTimeListQuerySchema, pairSharingGroupSchema, pickupGroupListQuerySchema, pickupLocationListQuerySchema, productMeetingConfigListQuerySchema, updateAllocationResourceSchema, updateAvailabilityCloseoutSchema, updateAvailabilityPickupPointSchema, updateAvailabilityRuleSchema, updateAvailabilitySlotPickupSchema, updateAvailabilitySlotSchema, updateAvailabilityStartTimeSchema, updateCustomPickupAreaSchema, updateLocationPickupTimeSchema, updatePickupGroupSchema, updatePickupLocationSchema, updateProductMeetingConfigSchema, updateSharingGroupLabelSchema, updateTravelerSharingGroupSchema, upsertResourceTemplateSchema, } from "./validation.js";
|
|
18
|
+
export { allocationAuditLogQuerySchema, allocationAutomationSchema, assignTravelerAllocationSchema, availabilityCloseoutListQuerySchema, availabilityOverviewQuerySchema, availabilityPickupPointListQuerySchema, availabilityRuleListQuerySchema, availabilitySlotListQuerySchema, availabilitySlotPickupListQuerySchema, availabilityStartTimeListQuerySchema, customPickupAreaListQuerySchema, insertAllocationResourceSchema, insertAvailabilityCloseoutSchema, insertAvailabilityPickupPointSchema, insertAvailabilityRuleSchema, insertAvailabilitySlotPickupSchema, insertAvailabilitySlotSchema, insertAvailabilityStartTimeSchema, insertCustomPickupAreaSchema, insertLocationPickupTimeSchema, insertPickupGroupSchema, insertPickupLocationSchema, insertProductMeetingConfigSchema, locationPickupTimeListQuerySchema, pairSharingGroupSchema, pickupGroupListQuerySchema, pickupLocationListQuerySchema, productMeetingConfigListQuerySchema, seatLayoutCellSchema, seatLayoutSpecSchema, updateAllocationResourceSchema, updateAvailabilityCloseoutSchema, updateAvailabilityPickupPointSchema, updateAvailabilityRuleSchema, updateAvailabilitySlotPickupSchema, updateAvailabilitySlotSchema, updateAvailabilityStartTimeSchema, updateCustomPickupAreaSchema, updateLocationPickupTimeSchema, updatePickupGroupSchema, updatePickupLocationSchema, updateProductMeetingConfigSchema, updateSharingGroupLabelSchema, updateTravelerSharingGroupSchema, upsertResourceTemplateSchema, } from "./validation.js";
|
|
19
19
|
export { availabilityService };
|
|
@@ -19,6 +19,7 @@ export declare const availabilityAllocationRoutes: import("hono/hono-base").Hono
|
|
|
19
19
|
id: string;
|
|
20
20
|
bookingNumber: string;
|
|
21
21
|
status: string;
|
|
22
|
+
bookingSequence: number;
|
|
22
23
|
paymentStatus: import("./service-allocation.js").AllocationPaymentStatus;
|
|
23
24
|
contactFirstName: string | null;
|
|
24
25
|
contactLastName: string | null;
|
|
@@ -31,6 +32,7 @@ export declare const availabilityAllocationRoutes: import("hono/hono-base").Hono
|
|
|
31
32
|
bookingId: string;
|
|
32
33
|
bookingNumber: string;
|
|
33
34
|
bookingStatus: string;
|
|
35
|
+
bookingSequence: number;
|
|
34
36
|
paymentStatus: import("./service-allocation.js").AllocationPaymentStatus;
|
|
35
37
|
firstName: string;
|
|
36
38
|
lastName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-allocation.d.ts","sourceRoot":"","sources":["../src/routes-allocation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAsC7C,eAAO,MAAM,4BAA4B
|
|
1
|
+
{"version":3,"file":"routes-allocation.d.ts","sourceRoot":"","sources":["../src/routes-allocation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAsC7C,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDA2LrC,CAAA"}
|
|
@@ -2,7 +2,7 @@ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
|
2
2
|
import type { z } from "zod";
|
|
3
3
|
import { type AllocationResource } from "./schema.js";
|
|
4
4
|
import { type AllocationMutationOptions } from "./service-allocation.js";
|
|
5
|
-
import type
|
|
5
|
+
import { type allocationAutomationSchema, type SeatLayoutCell, type SeatLayoutSpec, type upsertResourceTemplateSchema } from "./validation.js";
|
|
6
6
|
export type UpsertResourceTemplateInput = z.infer<typeof upsertResourceTemplateSchema>;
|
|
7
7
|
export type AllocationAutomationInput = z.infer<typeof allocationAutomationSchema>;
|
|
8
8
|
export interface ResourceTemplate {
|
|
@@ -74,4 +74,16 @@ export declare function materializeSlotResourcesFromTemplateDefaults(db: Postgre
|
|
|
74
74
|
created: number;
|
|
75
75
|
resources: AllocationResource[];
|
|
76
76
|
}>;
|
|
77
|
+
export declare function parseLayoutSpecFromFlags(flags: Record<string, unknown> | null): SeatLayoutSpec | null;
|
|
78
|
+
/**
|
|
79
|
+
* Derive window/aisle/middle from a seat's neighbours in the same row.
|
|
80
|
+
*
|
|
81
|
+
* - Touching an aisle or door cell → "aisle" (the seat is on the aisle side)
|
|
82
|
+
* - Touching the row boundary or a void cell → "window"
|
|
83
|
+
* - Surrounded by other seats → "middle"
|
|
84
|
+
*
|
|
85
|
+
* Aisle takes precedence so the "window" tag is reserved for actual outer
|
|
86
|
+
* seats; a 2-1 row's lone middle seat ends up "aisle" on both sides.
|
|
87
|
+
*/
|
|
88
|
+
export declare function positionFromCells(cells: ReadonlyArray<SeatLayoutCell>, index: number): "window" | "aisle" | "middle";
|
|
77
89
|
//# sourceMappingURL=service-allocation-automation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-allocation-automation.d.ts","sourceRoot":"","sources":["../src/service-allocation-automation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQ5B,OAAO,EACL,KAAK,kBAAkB,EAIxB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,KAAK,yBAAyB,EAK/B,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"service-allocation-automation.d.ts","sourceRoot":"","sources":["../src/service-allocation-automation.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { and, eq, sql } from "drizzle-orm";
|
|
|
2
2
|
import { planRoomAllocation, planVehicleSeatAllocation, } from "./auto-allocator.js";
|
|
3
3
|
import { allocationResources, availabilitySlots, productOptionResourceTemplates, } from "./schema.js";
|
|
4
4
|
import { AllocationServiceError, getSlotAllocationManifest, recordAllocationAudit, } from "./service-allocation.js";
|
|
5
|
+
import { seatLayoutSpecSchema, } from "./validation.js";
|
|
5
6
|
/**
|
|
6
7
|
* Emit `ARRAY[$1, $2, …]::text[]` so Postgres doesn't try to cast a
|
|
7
8
|
* tuple to `text[]`. See `sqlTextArray` in service-allocation.ts and
|
|
@@ -334,6 +335,10 @@ export async function materializeSlotResourcesFromTemplateDefaults(db, slotId, o
|
|
|
334
335
|
return { created: resources.length, resources };
|
|
335
336
|
}
|
|
336
337
|
async function materializeVehicleSeatGroup(db, slotId, group, startingSequence) {
|
|
338
|
+
const layoutSpec = parseLayoutSpecFromFlags(group.flags);
|
|
339
|
+
if (layoutSpec) {
|
|
340
|
+
return materializeVehicleSeatGroupFromSpec(db, slotId, group, startingSequence, layoutSpec);
|
|
341
|
+
}
|
|
337
342
|
const layout = group.layout ?? "2-2";
|
|
338
343
|
const seatsPerRow = parseLayoutSeatsPerRow(layout);
|
|
339
344
|
const vehiclesNeeded = Math.max(1, Math.ceil(group.pax_count / Math.max(1, group.capacity)));
|
|
@@ -402,6 +407,114 @@ async function materializeVehicleSeatGroup(db, slotId, group, startingSequence)
|
|
|
402
407
|
}
|
|
403
408
|
return { resources, vehicleCount: vehiclesNeeded };
|
|
404
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Materialize using an explicit 2D layoutSpec. Each row's seat cells become
|
|
412
|
+
* a vehicle_seat (skipping aisle/door/void). Window/aisle/middle is computed
|
|
413
|
+
* from neighbouring cells, so a coach door in the middle row collapses to a
|
|
414
|
+
* gap on the visual map (renderer side) without affecting seat numbering.
|
|
415
|
+
*/
|
|
416
|
+
async function materializeVehicleSeatGroupFromSpec(db, slotId, group, startingSequence, layoutSpec) {
|
|
417
|
+
const seatsPerVehicle = layoutSpec.rows.reduce((sum, row) => sum + row.cells.filter((cell) => cell === "seat").length, 0);
|
|
418
|
+
if (seatsPerVehicle === 0)
|
|
419
|
+
return { resources: [], vehicleCount: 0 };
|
|
420
|
+
const vehiclesNeeded = Math.max(1, Math.ceil(group.pax_count / seatsPerVehicle));
|
|
421
|
+
const resources = [];
|
|
422
|
+
let sequence = startingSequence;
|
|
423
|
+
for (let vehicleIndex = 0; vehicleIndex < vehiclesNeeded; vehicleIndex++) {
|
|
424
|
+
sequence += 1;
|
|
425
|
+
const [parent] = await db
|
|
426
|
+
.insert(allocationResources)
|
|
427
|
+
.values({
|
|
428
|
+
slotId,
|
|
429
|
+
kind: "vehicle",
|
|
430
|
+
refType: group.ref_type,
|
|
431
|
+
refId: group.ref_id,
|
|
432
|
+
label: renderNamePattern(group.name_pattern || "Vehicle {sequence}", {
|
|
433
|
+
sequence: String(sequence),
|
|
434
|
+
option: group.option_name ?? "",
|
|
435
|
+
index: String(vehicleIndex + 1),
|
|
436
|
+
}),
|
|
437
|
+
capacity: seatsPerVehicle,
|
|
438
|
+
flags: {
|
|
439
|
+
...(group.flags ?? {}),
|
|
440
|
+
layoutSpec,
|
|
441
|
+
templateOptionId: group.option_id,
|
|
442
|
+
},
|
|
443
|
+
sortOrder: sequence,
|
|
444
|
+
})
|
|
445
|
+
.returning();
|
|
446
|
+
if (!parent)
|
|
447
|
+
continue;
|
|
448
|
+
resources.push(parent);
|
|
449
|
+
let seatIndex = 0;
|
|
450
|
+
for (let rowIndex = 0; rowIndex < layoutSpec.rows.length; rowIndex++) {
|
|
451
|
+
const rowCells = layoutSpec.rows[rowIndex]?.cells ?? [];
|
|
452
|
+
const rowNumber = rowIndex + 1;
|
|
453
|
+
let column = 0;
|
|
454
|
+
for (let cellIndex = 0; cellIndex < rowCells.length; cellIndex++) {
|
|
455
|
+
const cell = rowCells[cellIndex];
|
|
456
|
+
if (cell !== "seat")
|
|
457
|
+
continue;
|
|
458
|
+
column += 1;
|
|
459
|
+
const columnName = columnLetter(column);
|
|
460
|
+
const position = positionFromCells(rowCells, cellIndex);
|
|
461
|
+
const [seat] = await db
|
|
462
|
+
.insert(allocationResources)
|
|
463
|
+
.values({
|
|
464
|
+
slotId,
|
|
465
|
+
kind: "vehicle_seat",
|
|
466
|
+
refType: group.ref_type,
|
|
467
|
+
refId: group.ref_id,
|
|
468
|
+
label: renderNamePattern("Seat {row}{column}", {
|
|
469
|
+
sequence: String(seatIndex + 1),
|
|
470
|
+
row: String(rowNumber),
|
|
471
|
+
column: columnName,
|
|
472
|
+
seat: `${rowNumber}${columnName}`,
|
|
473
|
+
}),
|
|
474
|
+
capacity: 1,
|
|
475
|
+
flags: { row: rowNumber, column: columnName, position },
|
|
476
|
+
parentId: parent.id,
|
|
477
|
+
sortOrder: seatIndex,
|
|
478
|
+
})
|
|
479
|
+
.returning();
|
|
480
|
+
if (seat)
|
|
481
|
+
resources.push(seat);
|
|
482
|
+
seatIndex += 1;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return { resources, vehicleCount: vehiclesNeeded };
|
|
487
|
+
}
|
|
488
|
+
export function parseLayoutSpecFromFlags(flags) {
|
|
489
|
+
const raw = flags?.layoutSpec;
|
|
490
|
+
if (!raw)
|
|
491
|
+
return null;
|
|
492
|
+
const parsed = seatLayoutSpecSchema.safeParse(raw);
|
|
493
|
+
return parsed.success ? parsed.data : null;
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Derive window/aisle/middle from a seat's neighbours in the same row.
|
|
497
|
+
*
|
|
498
|
+
* - Touching an aisle or door cell → "aisle" (the seat is on the aisle side)
|
|
499
|
+
* - Touching the row boundary or a void cell → "window"
|
|
500
|
+
* - Surrounded by other seats → "middle"
|
|
501
|
+
*
|
|
502
|
+
* Aisle takes precedence so the "window" tag is reserved for actual outer
|
|
503
|
+
* seats; a 2-1 row's lone middle seat ends up "aisle" on both sides.
|
|
504
|
+
*/
|
|
505
|
+
export function positionFromCells(cells, index) {
|
|
506
|
+
const prev = index > 0 ? cells[index - 1] : undefined;
|
|
507
|
+
const next = index < cells.length - 1 ? cells[index + 1] : undefined;
|
|
508
|
+
if (prev === "aisle" || prev === "door")
|
|
509
|
+
return "aisle";
|
|
510
|
+
if (next === "aisle" || next === "door")
|
|
511
|
+
return "aisle";
|
|
512
|
+
if (prev === undefined || prev === "void")
|
|
513
|
+
return "window";
|
|
514
|
+
if (next === undefined || next === "void")
|
|
515
|
+
return "window";
|
|
516
|
+
return "middle";
|
|
517
|
+
}
|
|
405
518
|
function toResourceTemplate(row) {
|
|
406
519
|
return {
|
|
407
520
|
id: row.id,
|
|
@@ -25,6 +25,13 @@ export interface AllocationManifestTraveler {
|
|
|
25
25
|
bookingId: string;
|
|
26
26
|
bookingNumber: string;
|
|
27
27
|
bookingStatus: string;
|
|
28
|
+
/**
|
|
29
|
+
* Per-slot booking ordinal (1-based) derived from each booking's
|
|
30
|
+
* createdAt. All travelers on the same booking share the same number,
|
|
31
|
+
* so the operator can scan the resource grid and spot at a glance
|
|
32
|
+
* which chips belong together.
|
|
33
|
+
*/
|
|
34
|
+
bookingSequence: number;
|
|
28
35
|
/** Aggregated payment status of the parent booking (see derivePaymentStatus). */
|
|
29
36
|
paymentStatus: AllocationPaymentStatus;
|
|
30
37
|
firstName: string;
|
|
@@ -47,6 +54,8 @@ export interface AllocationManifestBooking {
|
|
|
47
54
|
id: string;
|
|
48
55
|
bookingNumber: string;
|
|
49
56
|
status: string;
|
|
57
|
+
/** Per-slot ordinal (1-based) by createdAt; same number as the travelers on this booking. */
|
|
58
|
+
bookingSequence: number;
|
|
50
59
|
/** Aggregated payment status of the booking (see derivePaymentStatus). */
|
|
51
60
|
paymentStatus: AllocationPaymentStatus;
|
|
52
61
|
contactFirstName: string | null;
|
|
@@ -225,6 +234,45 @@ export declare function recordAllocationAudit(db: SqlExecutor, input: {
|
|
|
225
234
|
before?: Record<string, unknown> | null;
|
|
226
235
|
after?: Record<string, unknown> | null;
|
|
227
236
|
}): Promise<void>;
|
|
237
|
+
export interface BookingRow {
|
|
238
|
+
id: string;
|
|
239
|
+
booking_number: string;
|
|
240
|
+
status: string;
|
|
241
|
+
created_at: string | Date | null;
|
|
242
|
+
paid_at: string | Date | null;
|
|
243
|
+
contact_first_name: string | null;
|
|
244
|
+
contact_last_name: string | null;
|
|
245
|
+
contact_email: string | null;
|
|
246
|
+
contact_phone: string | null;
|
|
247
|
+
sell_currency: string | null;
|
|
248
|
+
pax: number | null;
|
|
249
|
+
sell_amount_cents: number | null;
|
|
250
|
+
invoice_total_cents: number | null;
|
|
251
|
+
invoice_paid_cents: number | null;
|
|
252
|
+
schedules_paid_cents: number | null;
|
|
253
|
+
}
|
|
228
254
|
export type AllocationPaymentStatus = "paid" | "partial" | "unpaid";
|
|
255
|
+
/**
|
|
256
|
+
* Roll up a booking's payment state into a single paid / partial / unpaid
|
|
257
|
+
* status for the allocation chip's color coding. Signals checked in order:
|
|
258
|
+
*
|
|
259
|
+
* 1. Free booking (`sell_amount_cents <= 0`) → `paid` (nothing owed).
|
|
260
|
+
* 2. `bookings.paid_at` is set → `paid` (operator marked the booking
|
|
261
|
+
* settled; this is authoritative regardless of invoice plumbing).
|
|
262
|
+
* 3. Sum of `booking_payment_schedules.amount_cents WHERE status='paid'`
|
|
263
|
+
* covers `sell_amount_cents` → `paid` (deposit-milestone flows that
|
|
264
|
+
* never run a final invoice).
|
|
265
|
+
* 4. That schedule sum is positive → `partial`.
|
|
266
|
+
* 5. No invoices issued (`invoice_total_cents = 0`) → `unpaid`.
|
|
267
|
+
* 6. `invoice_paid_cents <= 0` → `unpaid`.
|
|
268
|
+
* 7. `invoice_paid_cents >= invoice_total_cents` → `paid`.
|
|
269
|
+
* 8. Otherwise → `partial`.
|
|
270
|
+
*
|
|
271
|
+
* The schedule and `paid_at` checks were added because the invoice-only
|
|
272
|
+
* rule mis-colored booked-and-settled trips as red whenever the operator
|
|
273
|
+
* billed via schedules without issuing an invoice, or recorded settlement
|
|
274
|
+
* on the schedule rather than a `payments` row (issue #1079).
|
|
275
|
+
*/
|
|
276
|
+
export declare function derivePaymentStatus(row: BookingRow): AllocationPaymentStatus;
|
|
229
277
|
export {};
|
|
230
278
|
//# sourceMappingURL=service-allocation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-allocation.d.ts","sourceRoot":"","sources":["../src/service-allocation.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service-allocation.d.ts","sourceRoot":"","sources":["../src/service-allocation.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,13 @@ export async function getSlotAllocationManifest(db, slotId) {
|
|
|
43
43
|
const bookingIds = bookingRows.map((row) => row.id);
|
|
44
44
|
const travelerRows = await loadSlotTravelerRows(db, bookingIds);
|
|
45
45
|
const bookingById = new Map(bookingRows.map((row) => [row.id, row]));
|
|
46
|
+
// Assign 1-based slot-local sequence by booking createdAt. The SQL above
|
|
47
|
+
// already orders by `created_at` then `booking_number`, so iterating in
|
|
48
|
+
// array order is the same as iterating in chronological order.
|
|
49
|
+
const sequenceByBookingId = new Map();
|
|
50
|
+
for (const [index, row] of bookingRows.entries()) {
|
|
51
|
+
sequenceByBookingId.set(row.id, index + 1);
|
|
52
|
+
}
|
|
46
53
|
const travelersByBooking = new Map();
|
|
47
54
|
for (const row of travelerRows) {
|
|
48
55
|
const booking = bookingById.get(row.booking_id);
|
|
@@ -51,6 +58,7 @@ export async function getSlotAllocationManifest(db, slotId) {
|
|
|
51
58
|
bookingId: row.booking_id,
|
|
52
59
|
bookingNumber: booking?.booking_number ?? "",
|
|
53
60
|
bookingStatus: booking?.status ?? "unknown",
|
|
61
|
+
bookingSequence: sequenceByBookingId.get(row.booking_id) ?? 0,
|
|
54
62
|
paymentStatus: booking ? derivePaymentStatus(booking) : "unpaid",
|
|
55
63
|
firstName: row.first_name,
|
|
56
64
|
lastName: row.last_name,
|
|
@@ -72,10 +80,11 @@ export async function getSlotAllocationManifest(db, slotId) {
|
|
|
72
80
|
list.push(traveler);
|
|
73
81
|
travelersByBooking.set(row.booking_id, list);
|
|
74
82
|
}
|
|
75
|
-
const bookings = bookingRows.map((row) => ({
|
|
83
|
+
const bookings = bookingRows.map((row, index) => ({
|
|
76
84
|
id: row.id,
|
|
77
85
|
bookingNumber: row.booking_number,
|
|
78
86
|
status: row.status,
|
|
87
|
+
bookingSequence: index + 1,
|
|
79
88
|
paymentStatus: derivePaymentStatus(row),
|
|
80
89
|
contactFirstName: row.contact_first_name,
|
|
81
90
|
contactLastName: row.contact_last_name,
|
|
@@ -682,92 +691,217 @@ function serializeSlot(slot) {
|
|
|
682
691
|
};
|
|
683
692
|
}
|
|
684
693
|
/**
|
|
685
|
-
* Roll up a booking's
|
|
686
|
-
* status for the allocation chip's color coding.
|
|
694
|
+
* Roll up a booking's payment state into a single paid / partial / unpaid
|
|
695
|
+
* status for the allocation chip's color coding. Signals checked in order:
|
|
696
|
+
*
|
|
697
|
+
* 1. Free booking (`sell_amount_cents <= 0`) → `paid` (nothing owed).
|
|
698
|
+
* 2. `bookings.paid_at` is set → `paid` (operator marked the booking
|
|
699
|
+
* settled; this is authoritative regardless of invoice plumbing).
|
|
700
|
+
* 3. Sum of `booking_payment_schedules.amount_cents WHERE status='paid'`
|
|
701
|
+
* covers `sell_amount_cents` → `paid` (deposit-milestone flows that
|
|
702
|
+
* never run a final invoice).
|
|
703
|
+
* 4. That schedule sum is positive → `partial`.
|
|
704
|
+
* 5. No invoices issued (`invoice_total_cents = 0`) → `unpaid`.
|
|
705
|
+
* 6. `invoice_paid_cents <= 0` → `unpaid`.
|
|
706
|
+
* 7. `invoice_paid_cents >= invoice_total_cents` → `paid`.
|
|
707
|
+
* 8. Otherwise → `partial`.
|
|
687
708
|
*
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
* - Some paid, some still due → `partial`.
|
|
693
|
-
* - Nothing paid → `unpaid`.
|
|
709
|
+
* The schedule and `paid_at` checks were added because the invoice-only
|
|
710
|
+
* rule mis-colored booked-and-settled trips as red whenever the operator
|
|
711
|
+
* billed via schedules without issuing an invoice, or recorded settlement
|
|
712
|
+
* on the schedule rather than a `payments` row (issue #1079).
|
|
694
713
|
*/
|
|
695
|
-
function derivePaymentStatus(row) {
|
|
714
|
+
export function derivePaymentStatus(row) {
|
|
696
715
|
const sellAmount = row.sell_amount_cents ?? 0;
|
|
697
716
|
if (sellAmount <= 0)
|
|
698
717
|
return "paid";
|
|
718
|
+
if (row.paid_at != null)
|
|
719
|
+
return "paid";
|
|
720
|
+
const schedulesPaid = row.schedules_paid_cents ?? 0;
|
|
721
|
+
if (schedulesPaid >= sellAmount)
|
|
722
|
+
return "paid";
|
|
699
723
|
const invoiceTotal = row.invoice_total_cents ?? 0;
|
|
700
724
|
const invoicePaid = row.invoice_paid_cents ?? 0;
|
|
701
|
-
if (invoiceTotal
|
|
702
|
-
return "unpaid";
|
|
703
|
-
if (invoicePaid <= 0)
|
|
704
|
-
return "unpaid";
|
|
705
|
-
if (invoicePaid >= invoiceTotal)
|
|
725
|
+
if (invoicePaid >= invoiceTotal && invoiceTotal > 0)
|
|
706
726
|
return "paid";
|
|
707
|
-
|
|
727
|
+
if (schedulesPaid > 0 || invoicePaid > 0)
|
|
728
|
+
return "partial";
|
|
729
|
+
return "unpaid";
|
|
708
730
|
}
|
|
709
731
|
async function loadSlotBookingRows(db, slotId) {
|
|
710
|
-
// `
|
|
711
|
-
//
|
|
712
|
-
//
|
|
713
|
-
//
|
|
714
|
-
//
|
|
732
|
+
// `invoices` and `booking_payment_schedules` are LEFT JOIN aggregations that
|
|
733
|
+
// may reference tables missing in catalog-less / finance-less deploys.
|
|
734
|
+
// We try four query shapes in order of decreasing data, falling through on
|
|
735
|
+
// any "undefined_table" (Postgres 42P01). The ordering matters: if invoices
|
|
736
|
+
// exists but schedules doesn't, we still want to preserve invoice data
|
|
737
|
+
// (and vice versa) — so we try the invoices-only and schedules-only paths
|
|
738
|
+
// separately rather than collapsing both joins together.
|
|
715
739
|
try {
|
|
716
|
-
return await
|
|
717
|
-
SELECT DISTINCT
|
|
718
|
-
b.id,
|
|
719
|
-
b.booking_number,
|
|
720
|
-
b.status,
|
|
721
|
-
b.contact_first_name,
|
|
722
|
-
b.contact_last_name,
|
|
723
|
-
b.contact_email,
|
|
724
|
-
b.contact_phone,
|
|
725
|
-
b.sell_currency,
|
|
726
|
-
b.pax,
|
|
727
|
-
b.sell_amount_cents,
|
|
728
|
-
COALESCE(inv.total_cents, 0) AS invoice_total_cents,
|
|
729
|
-
COALESCE(inv.paid_cents, 0) AS invoice_paid_cents
|
|
730
|
-
FROM bookings b
|
|
731
|
-
JOIN booking_allocations ba ON ba.booking_id = b.id
|
|
732
|
-
LEFT JOIN (
|
|
733
|
-
SELECT
|
|
734
|
-
booking_id,
|
|
735
|
-
SUM(total_cents) AS total_cents,
|
|
736
|
-
SUM(paid_cents) AS paid_cents
|
|
737
|
-
FROM invoices
|
|
738
|
-
WHERE status <> 'void'
|
|
739
|
-
GROUP BY booking_id
|
|
740
|
-
) inv ON inv.booking_id = b.id
|
|
741
|
-
WHERE ba.availability_slot_id = ${slotId}
|
|
742
|
-
AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
|
|
743
|
-
AND ba.status IN ('held', 'confirmed', 'fulfilled')
|
|
744
|
-
ORDER BY b.booking_number
|
|
745
|
-
`);
|
|
740
|
+
return await loadSlotBookingRowsBothJoins(db, slotId);
|
|
746
741
|
}
|
|
747
742
|
catch (error) {
|
|
748
743
|
if (!isUndefinedTableError(error))
|
|
749
744
|
throw error;
|
|
750
|
-
const rows = await executeRows(db, sql `
|
|
751
|
-
SELECT DISTINCT
|
|
752
|
-
b.id,
|
|
753
|
-
b.booking_number,
|
|
754
|
-
b.status,
|
|
755
|
-
b.contact_first_name,
|
|
756
|
-
b.contact_last_name,
|
|
757
|
-
b.contact_email,
|
|
758
|
-
b.contact_phone,
|
|
759
|
-
b.sell_currency,
|
|
760
|
-
b.pax,
|
|
761
|
-
b.sell_amount_cents
|
|
762
|
-
FROM bookings b
|
|
763
|
-
JOIN booking_allocations ba ON ba.booking_id = b.id
|
|
764
|
-
WHERE ba.availability_slot_id = ${slotId}
|
|
765
|
-
AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
|
|
766
|
-
AND ba.status IN ('held', 'confirmed', 'fulfilled')
|
|
767
|
-
ORDER BY b.booking_number
|
|
768
|
-
`);
|
|
769
|
-
return rows.map((row) => ({ ...row, invoice_total_cents: 0, invoice_paid_cents: 0 }));
|
|
770
745
|
}
|
|
746
|
+
// Drop the schedules join (preserves invoice rollups when schedules is missing).
|
|
747
|
+
try {
|
|
748
|
+
return await loadSlotBookingRowsInvoicesOnly(db, slotId);
|
|
749
|
+
}
|
|
750
|
+
catch (error) {
|
|
751
|
+
if (!isUndefinedTableError(error))
|
|
752
|
+
throw error;
|
|
753
|
+
}
|
|
754
|
+
// Drop the invoices join (preserves schedule rollups when invoices is missing).
|
|
755
|
+
try {
|
|
756
|
+
return await loadSlotBookingRowsSchedulesOnly(db, slotId);
|
|
757
|
+
}
|
|
758
|
+
catch (error) {
|
|
759
|
+
if (!isUndefinedTableError(error))
|
|
760
|
+
throw error;
|
|
761
|
+
}
|
|
762
|
+
// Final fallback: both tables missing — bare bookings query.
|
|
763
|
+
return loadSlotBookingRowsBare(db, slotId);
|
|
764
|
+
}
|
|
765
|
+
async function loadSlotBookingRowsBothJoins(db, slotId) {
|
|
766
|
+
return executeRows(db, sql `
|
|
767
|
+
SELECT DISTINCT
|
|
768
|
+
b.id,
|
|
769
|
+
b.booking_number,
|
|
770
|
+
b.status,
|
|
771
|
+
b.created_at,
|
|
772
|
+
b.paid_at,
|
|
773
|
+
b.contact_first_name,
|
|
774
|
+
b.contact_last_name,
|
|
775
|
+
b.contact_email,
|
|
776
|
+
b.contact_phone,
|
|
777
|
+
b.sell_currency,
|
|
778
|
+
b.pax,
|
|
779
|
+
b.sell_amount_cents,
|
|
780
|
+
COALESCE(inv.total_cents, 0) AS invoice_total_cents,
|
|
781
|
+
COALESCE(inv.paid_cents, 0) AS invoice_paid_cents,
|
|
782
|
+
COALESCE(sch.paid_cents, 0) AS schedules_paid_cents
|
|
783
|
+
FROM bookings b
|
|
784
|
+
JOIN booking_allocations ba ON ba.booking_id = b.id
|
|
785
|
+
LEFT JOIN (
|
|
786
|
+
SELECT
|
|
787
|
+
booking_id,
|
|
788
|
+
SUM(total_cents) AS total_cents,
|
|
789
|
+
SUM(paid_cents) AS paid_cents
|
|
790
|
+
FROM invoices
|
|
791
|
+
WHERE status <> 'void'
|
|
792
|
+
GROUP BY booking_id
|
|
793
|
+
) inv ON inv.booking_id = b.id
|
|
794
|
+
LEFT JOIN (
|
|
795
|
+
SELECT
|
|
796
|
+
booking_id,
|
|
797
|
+
SUM(amount_cents) AS paid_cents
|
|
798
|
+
FROM booking_payment_schedules
|
|
799
|
+
WHERE status = 'paid'
|
|
800
|
+
GROUP BY booking_id
|
|
801
|
+
) sch ON sch.booking_id = b.id
|
|
802
|
+
WHERE ba.availability_slot_id = ${slotId}
|
|
803
|
+
AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
|
|
804
|
+
AND ba.status IN ('held', 'confirmed', 'fulfilled')
|
|
805
|
+
ORDER BY b.created_at, b.booking_number
|
|
806
|
+
`);
|
|
807
|
+
}
|
|
808
|
+
async function loadSlotBookingRowsInvoicesOnly(db, slotId) {
|
|
809
|
+
return executeRows(db, sql `
|
|
810
|
+
SELECT DISTINCT
|
|
811
|
+
b.id,
|
|
812
|
+
b.booking_number,
|
|
813
|
+
b.status,
|
|
814
|
+
b.created_at,
|
|
815
|
+
b.paid_at,
|
|
816
|
+
b.contact_first_name,
|
|
817
|
+
b.contact_last_name,
|
|
818
|
+
b.contact_email,
|
|
819
|
+
b.contact_phone,
|
|
820
|
+
b.sell_currency,
|
|
821
|
+
b.pax,
|
|
822
|
+
b.sell_amount_cents,
|
|
823
|
+
COALESCE(inv.total_cents, 0) AS invoice_total_cents,
|
|
824
|
+
COALESCE(inv.paid_cents, 0) AS invoice_paid_cents,
|
|
825
|
+
0 AS schedules_paid_cents
|
|
826
|
+
FROM bookings b
|
|
827
|
+
JOIN booking_allocations ba ON ba.booking_id = b.id
|
|
828
|
+
LEFT JOIN (
|
|
829
|
+
SELECT
|
|
830
|
+
booking_id,
|
|
831
|
+
SUM(total_cents) AS total_cents,
|
|
832
|
+
SUM(paid_cents) AS paid_cents
|
|
833
|
+
FROM invoices
|
|
834
|
+
WHERE status <> 'void'
|
|
835
|
+
GROUP BY booking_id
|
|
836
|
+
) inv ON inv.booking_id = b.id
|
|
837
|
+
WHERE ba.availability_slot_id = ${slotId}
|
|
838
|
+
AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
|
|
839
|
+
AND ba.status IN ('held', 'confirmed', 'fulfilled')
|
|
840
|
+
ORDER BY b.created_at, b.booking_number
|
|
841
|
+
`);
|
|
842
|
+
}
|
|
843
|
+
async function loadSlotBookingRowsSchedulesOnly(db, slotId) {
|
|
844
|
+
return executeRows(db, sql `
|
|
845
|
+
SELECT DISTINCT
|
|
846
|
+
b.id,
|
|
847
|
+
b.booking_number,
|
|
848
|
+
b.status,
|
|
849
|
+
b.created_at,
|
|
850
|
+
b.paid_at,
|
|
851
|
+
b.contact_first_name,
|
|
852
|
+
b.contact_last_name,
|
|
853
|
+
b.contact_email,
|
|
854
|
+
b.contact_phone,
|
|
855
|
+
b.sell_currency,
|
|
856
|
+
b.pax,
|
|
857
|
+
b.sell_amount_cents,
|
|
858
|
+
0 AS invoice_total_cents,
|
|
859
|
+
0 AS invoice_paid_cents,
|
|
860
|
+
COALESCE(sch.paid_cents, 0) AS schedules_paid_cents
|
|
861
|
+
FROM bookings b
|
|
862
|
+
JOIN booking_allocations ba ON ba.booking_id = b.id
|
|
863
|
+
LEFT JOIN (
|
|
864
|
+
SELECT
|
|
865
|
+
booking_id,
|
|
866
|
+
SUM(amount_cents) AS paid_cents
|
|
867
|
+
FROM booking_payment_schedules
|
|
868
|
+
WHERE status = 'paid'
|
|
869
|
+
GROUP BY booking_id
|
|
870
|
+
) sch ON sch.booking_id = b.id
|
|
871
|
+
WHERE ba.availability_slot_id = ${slotId}
|
|
872
|
+
AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
|
|
873
|
+
AND ba.status IN ('held', 'confirmed', 'fulfilled')
|
|
874
|
+
ORDER BY b.created_at, b.booking_number
|
|
875
|
+
`);
|
|
876
|
+
}
|
|
877
|
+
async function loadSlotBookingRowsBare(db, slotId) {
|
|
878
|
+
const rows = await executeRows(db, sql `
|
|
879
|
+
SELECT DISTINCT
|
|
880
|
+
b.id,
|
|
881
|
+
b.booking_number,
|
|
882
|
+
b.status,
|
|
883
|
+
b.created_at,
|
|
884
|
+
b.paid_at,
|
|
885
|
+
b.contact_first_name,
|
|
886
|
+
b.contact_last_name,
|
|
887
|
+
b.contact_email,
|
|
888
|
+
b.contact_phone,
|
|
889
|
+
b.sell_currency,
|
|
890
|
+
b.pax,
|
|
891
|
+
b.sell_amount_cents
|
|
892
|
+
FROM bookings b
|
|
893
|
+
JOIN booking_allocations ba ON ba.booking_id = b.id
|
|
894
|
+
WHERE ba.availability_slot_id = ${slotId}
|
|
895
|
+
AND b.status IN ('draft', 'on_hold', 'confirmed', 'in_progress', 'completed')
|
|
896
|
+
AND ba.status IN ('held', 'confirmed', 'fulfilled')
|
|
897
|
+
ORDER BY b.created_at, b.booking_number
|
|
898
|
+
`);
|
|
899
|
+
return rows.map((row) => ({
|
|
900
|
+
...row,
|
|
901
|
+
invoice_total_cents: 0,
|
|
902
|
+
invoice_paid_cents: 0,
|
|
903
|
+
schedules_paid_cents: 0,
|
|
904
|
+
}));
|
|
771
905
|
}
|
|
772
906
|
function isUndefinedTableError(error) {
|
|
773
907
|
return (typeof error === "object" &&
|
package/dist/validation.d.ts
CHANGED
|
@@ -22,6 +22,38 @@ export declare const pickupTimingModeSchema: z.ZodEnum<{
|
|
|
22
22
|
export declare const allocationResourceKindSchema: z.ZodString;
|
|
23
23
|
export declare const allocationResourceFlagsSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
24
24
|
export declare const travelerAllocationMapSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
25
|
+
/**
|
|
26
|
+
* Explicit 2D seat layout for vehicle_seat templates. Each row is a list of
|
|
27
|
+
* cells the materializer walks:
|
|
28
|
+
*
|
|
29
|
+
* - `seat` → creates one vehicle_seat resource
|
|
30
|
+
* - `aisle` → renders as a horizontal gap between seat blocks
|
|
31
|
+
* - `door` → renders as a wider gap (mid-coach door is common)
|
|
32
|
+
* - `void` → empty cell (wheelchair spot, toilet, kitchen, wheel well)
|
|
33
|
+
*
|
|
34
|
+
* Stored on the template's `flags.layoutSpec`. When present, the materializer
|
|
35
|
+
* ignores the legacy `layout` string + `capacity` (capacity is derived from
|
|
36
|
+
* the number of "seat" cells). The renderer in @voyantjs/allocation-ui mirrors
|
|
37
|
+
* the same grid so the visual seat map matches what the operator drew.
|
|
38
|
+
*/
|
|
39
|
+
export declare const seatLayoutCellSchema: z.ZodEnum<{
|
|
40
|
+
aisle: "aisle";
|
|
41
|
+
void: "void";
|
|
42
|
+
seat: "seat";
|
|
43
|
+
door: "door";
|
|
44
|
+
}>;
|
|
45
|
+
export type SeatLayoutCell = z.infer<typeof seatLayoutCellSchema>;
|
|
46
|
+
export declare const seatLayoutSpecSchema: z.ZodObject<{
|
|
47
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
48
|
+
cells: z.ZodArray<z.ZodEnum<{
|
|
49
|
+
aisle: "aisle";
|
|
50
|
+
void: "void";
|
|
51
|
+
seat: "seat";
|
|
52
|
+
door: "door";
|
|
53
|
+
}>>;
|
|
54
|
+
}, z.core.$strip>>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
export type SeatLayoutSpec = z.infer<typeof seatLayoutSpecSchema>;
|
|
25
57
|
export declare const availabilityRuleCoreSchema: z.ZodObject<{
|
|
26
58
|
productId: z.ZodString;
|
|
27
59
|
optionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,eAAO,MAAM,4BAA4B;;;;;EAAsD,CAAA;AAC/F,eAAO,MAAM,iBAAiB;;;;EAA4D,CAAA;AAC1F,eAAO,MAAM,qBAAqB;;;;EAA2C,CAAA;AAC7E,eAAO,MAAM,sBAAsB;;;EAA8C,CAAA;AACjF,eAAO,MAAM,4BAA4B,aAAmC,CAAA;AAC5E,eAAO,MAAM,6BAA6B,wCAAoC,CAAA;AAC9E,eAAO,MAAM,2BAA2B,uCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,eAAO,MAAM,4BAA4B;;;;;EAAsD,CAAA;AAC/F,eAAO,MAAM,iBAAiB;;;;EAA4D,CAAA;AAC1F,eAAO,MAAM,qBAAqB;;;;EAA2C,CAAA;AAC7E,eAAO,MAAM,sBAAsB;;;EAA8C,CAAA;AACjF,eAAO,MAAM,4BAA4B,aAAmC,CAAA;AAC5E,eAAO,MAAM,6BAA6B,wCAAoC,CAAA;AAC9E,eAAO,MAAM,2BAA2B,uCAAmC,CAAA;AAE3E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB;;;;;EAA4C,CAAA;AAC7E,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEjE,eAAO,MAAM,oBAAoB;;;;;;;;;iBAS/B,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAKjE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;iBAYrC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;iBAAuC,CAAA;AAChF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;iBAK1C,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;;;;;;;iBAS1C,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;;;iBAAkC,CAAA;AAChF,eAAO,MAAM,iCAAiC;;;;;;;;;iBAA4C,CAAA;AAC1F,eAAO,MAAM,oCAAoC;;;;;;;;;;;;iBAK/C,CAAA;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuBrC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAuC,CAAA;AAChF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;iBAU1C,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;iBAG5C,CAAA;AAEF,eAAO,MAAM,+BAA+B;;;iBAG1C,CAAA;AAEF,eAAO,MAAM,8BAA8B;;;;;;iBAMzC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;iBAAiC,CAAA;AAC9E,eAAO,MAAM,gCAAgC;;;;;;iBAA2C,CAAA;AACxF,eAAO,MAAM,mCAAmC;;;;;;iBAI9C,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;iBASvC,CAAA;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;;;kBAMvC,CAAA;AAEJ,eAAO,MAAM,8BAA8B;;;iBAGzC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;iBAE3C,CAAA;AAEF,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAA;AAEF,eAAO,MAAM,6BAA6B;;iBAExC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;iBAQvC,CAAA;AAEF,eAAO,MAAM,0BAA0B;;iBAErC,CAAA;AAEF,eAAO,MAAM,6BAA6B;;iBAExC,CAAA;AAEF,eAAO,MAAM,iCAAiC;;;;;;;iBAO5C,CAAA;AAEF,eAAO,MAAM,mCAAmC;;;;;;;iBAAoC,CAAA;AACpF,eAAO,MAAM,mCAAmC;;;;;;;iBAA8C,CAAA;AAC9F,eAAO,MAAM,sCAAsC;;;;;;;;;;;iBAIjD,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;iBAK3C,CAAA;AAEF,eAAO,MAAM,kCAAkC;;;;;iBAAmC,CAAA;AAClF,eAAO,MAAM,kCAAkC;;;;;iBAA6C,CAAA;AAC5F,eAAO,MAAM,qCAAqC;;;;;iBAGhD,CAAA;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;iBAczC,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;iBAAiC,CAAA;AAC9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;iBAA2C,CAAA;AACxF,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;iBAM9C,CAAA;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;iBAOhC,CAAA;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;iBAAwB,CAAA;AAC5D,eAAO,MAAM,uBAAuB;;;;;;;;;;;iBAAkC,CAAA;AACtE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;iBAIrC,CAAA;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;iBASnC,CAAA;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;;iBAA2B,CAAA;AAClE,eAAO,MAAM,0BAA0B;;;;;;;;;iBAAqC,CAAA;AAC5E,eAAO,MAAM,6BAA6B;;;;;;;;;;;iBAIxC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;iBAWvC,CAAA;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;iBAA+B,CAAA;AAC1E,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;iBAAyC,CAAA;AACpF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;iBAK5C,CAAA;AAEF,eAAO,MAAM,0BAA0B;;;;;;iBAMrC,CAAA;AAEF,eAAO,MAAM,4BAA4B;;;;;;iBAA6B,CAAA;AACtE,eAAO,MAAM,4BAA4B;;;;;;iBAAuC,CAAA;AAChF,eAAO,MAAM,+BAA+B;;;;;;;;;;iBAG1C,CAAA"}
|
package/dist/validation.js
CHANGED
|
@@ -11,6 +11,29 @@ export const pickupTimingModeSchema = z.enum(["fixed_time", "offset_from_start"]
|
|
|
11
11
|
export const allocationResourceKindSchema = z.string().trim().min(1).max(80);
|
|
12
12
|
export const allocationResourceFlagsSchema = z.record(z.string(), z.unknown());
|
|
13
13
|
export const travelerAllocationMapSchema = z.record(z.string(), z.string());
|
|
14
|
+
/**
|
|
15
|
+
* Explicit 2D seat layout for vehicle_seat templates. Each row is a list of
|
|
16
|
+
* cells the materializer walks:
|
|
17
|
+
*
|
|
18
|
+
* - `seat` → creates one vehicle_seat resource
|
|
19
|
+
* - `aisle` → renders as a horizontal gap between seat blocks
|
|
20
|
+
* - `door` → renders as a wider gap (mid-coach door is common)
|
|
21
|
+
* - `void` → empty cell (wheelchair spot, toilet, kitchen, wheel well)
|
|
22
|
+
*
|
|
23
|
+
* Stored on the template's `flags.layoutSpec`. When present, the materializer
|
|
24
|
+
* ignores the legacy `layout` string + `capacity` (capacity is derived from
|
|
25
|
+
* the number of "seat" cells). The renderer in @voyantjs/allocation-ui mirrors
|
|
26
|
+
* the same grid so the visual seat map matches what the operator drew.
|
|
27
|
+
*/
|
|
28
|
+
export const seatLayoutCellSchema = z.enum(["seat", "aisle", "door", "void"]);
|
|
29
|
+
export const seatLayoutSpecSchema = z.object({
|
|
30
|
+
rows: z
|
|
31
|
+
.array(z.object({
|
|
32
|
+
cells: z.array(seatLayoutCellSchema).min(1).max(20),
|
|
33
|
+
}))
|
|
34
|
+
.min(1)
|
|
35
|
+
.max(40),
|
|
36
|
+
});
|
|
14
37
|
const isoDateSchema = z.string().date();
|
|
15
38
|
const isoDateTimeSchema = z.string().datetime();
|
|
16
39
|
export const availabilityRuleCoreSchema = z.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/availability",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -44,13 +44,13 @@
|
|
|
44
44
|
"drizzle-orm": "^0.45.2",
|
|
45
45
|
"hono": "^4.12.10",
|
|
46
46
|
"zod": "^4.3.6",
|
|
47
|
-
"@voyantjs/core": "0.
|
|
48
|
-
"@voyantjs/db": "0.
|
|
49
|
-
"@voyantjs/hono": "0.
|
|
47
|
+
"@voyantjs/core": "0.71.0",
|
|
48
|
+
"@voyantjs/db": "0.71.0",
|
|
49
|
+
"@voyantjs/hono": "0.71.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"typescript": "^6.0.2",
|
|
53
|
-
"@voyantjs/products": "0.
|
|
53
|
+
"@voyantjs/products": "0.71.0",
|
|
54
54
|
"@voyantjs/voyant-typescript-config": "0.1.0"
|
|
55
55
|
},
|
|
56
56
|
"files": [
|