@voyantjs/booking-requirements 0.2.0 → 0.3.1

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 CHANGED
@@ -2,10 +2,12 @@ import type { Module } from "@voyantjs/core";
2
2
  import type { HonoModule } from "@voyantjs/hono/module";
3
3
  import { bookingRequirementsService } from "./service.js";
4
4
  export type { BookingRequirementsRoutes } from "./routes.js";
5
+ export type { PublicBookingRequirementsRoutes } from "./routes-public.js";
5
6
  export declare const bookingRequirementsModule: Module;
6
7
  export declare const bookingRequirementsHonoModule: HonoModule;
8
+ export { publicBookingRequirementsRoutes } from "./routes-public.js";
7
9
  export type { BookingAnswer, BookingQuestionExtraTrigger, BookingQuestionOption, BookingQuestionOptionTrigger, BookingQuestionUnitTrigger, NewBookingAnswer, NewBookingQuestionExtraTrigger, NewBookingQuestionOption, NewBookingQuestionOptionTrigger, NewBookingQuestionUnitTrigger, NewOptionBookingQuestion, NewProductBookingQuestion, NewProductContactRequirement, OptionBookingQuestion, ProductBookingQuestion, ProductContactRequirement, } from "./schema.js";
8
10
  export { bookingAnswers, bookingAnswerTargetEnum, bookingQuestionExtraTriggers, bookingQuestionFieldTypeEnum, bookingQuestionOptions, bookingQuestionOptionTriggers, bookingQuestionTargetEnum, bookingQuestionTriggerModeEnum, bookingQuestionUnitTriggers, contactRequirementFieldEnum, contactRequirementScopeEnum, optionBookingQuestions, productBookingQuestions, productContactRequirements, } from "./schema.js";
9
- export { bookingAnswerListQuerySchema, bookingAnswerTargetSchema, bookingQuestionExtraTriggerListQuerySchema, bookingQuestionFieldTypeSchema, bookingQuestionOptionListQuerySchema, bookingQuestionOptionTriggerListQuerySchema, bookingQuestionTargetSchema, bookingQuestionTriggerModeSchema, bookingQuestionUnitTriggerListQuerySchema, contactRequirementFieldSchema, contactRequirementScopeSchema, insertBookingAnswerSchema, insertBookingQuestionExtraTriggerSchema, insertBookingQuestionOptionSchema, insertBookingQuestionOptionTriggerSchema, insertBookingQuestionUnitTriggerSchema, insertOptionBookingQuestionSchema, insertProductBookingQuestionSchema, insertProductContactRequirementSchema, optionBookingQuestionListQuerySchema, productBookingQuestionListQuerySchema, productContactRequirementListQuerySchema, updateBookingAnswerSchema, updateBookingQuestionExtraTriggerSchema, updateBookingQuestionOptionSchema, updateBookingQuestionOptionTriggerSchema, updateBookingQuestionUnitTriggerSchema, updateOptionBookingQuestionSchema, updateProductBookingQuestionSchema, updateProductContactRequirementSchema, } from "./validation.js";
11
+ export { bookingAnswerListQuerySchema, bookingAnswerTargetSchema, bookingQuestionExtraTriggerListQuerySchema, bookingQuestionFieldTypeSchema, bookingQuestionOptionListQuerySchema, bookingQuestionOptionTriggerListQuerySchema, bookingQuestionTargetSchema, bookingQuestionTriggerModeSchema, bookingQuestionUnitTriggerListQuerySchema, contactRequirementFieldSchema, contactRequirementScopeSchema, insertBookingAnswerSchema, insertBookingQuestionExtraTriggerSchema, insertBookingQuestionOptionSchema, insertBookingQuestionOptionTriggerSchema, insertBookingQuestionUnitTriggerSchema, insertOptionBookingQuestionSchema, insertProductBookingQuestionSchema, insertProductContactRequirementSchema, optionBookingQuestionListQuerySchema, productBookingQuestionListQuerySchema, productContactRequirementListQuerySchema, publicTransportRequirementSummarySchema, publicTransportRequirementsQuerySchema, publicTransportRequirementsSchema, transportRequirementFieldSchema, updateBookingAnswerSchema, updateBookingQuestionExtraTriggerSchema, updateBookingQuestionOptionSchema, updateBookingQuestionOptionTriggerSchema, updateBookingQuestionUnitTriggerSchema, updateOptionBookingQuestionSchema, updateProductBookingQuestionSchema, updateProductContactRequirementSchema, } from "./validation.js";
10
12
  export { bookingRequirementsService };
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -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,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAEzD,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAE5D,eAAO,MAAM,yBAAyB,EAAE,MAEvC,CAAA;AAED,eAAO,MAAM,6BAA6B,EAAE,UAG3C,CAAA;AAED,YAAY,EACV,aAAa,EACb,2BAA2B,EAC3B,qBAAqB,EACrB,4BAA4B,EAC5B,0BAA0B,EAC1B,gBAAgB,EAChB,8BAA8B,EAC9B,wBAAwB,EACxB,+BAA+B,EAC/B,6BAA6B,EAC7B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EACtB,6BAA6B,EAC7B,yBAAyB,EACzB,8BAA8B,EAC9B,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,0CAA0C,EAC1C,8BAA8B,EAC9B,oCAAoC,EACpC,2CAA2C,EAC3C,2BAA2B,EAC3B,gCAAgC,EAChC,yCAAyC,EACzC,6BAA6B,EAC7B,6BAA6B,EAC7B,yBAAyB,EACzB,uCAAuC,EACvC,iCAAiC,EACjC,wCAAwC,EACxC,sCAAsC,EACtC,iCAAiC,EACjC,kCAAkC,EAClC,qCAAqC,EACrC,oCAAoC,EACpC,qCAAqC,EACrC,wCAAwC,EACxC,yBAAyB,EACzB,uCAAuC,EACvC,iCAAiC,EACjC,wCAAwC,EACxC,sCAAsC,EACtC,iCAAiC,EACjC,kCAAkC,EAClC,qCAAqC,GACtC,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,0BAA0B,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;AAIvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AAEzD,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAC5D,YAAY,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAA;AAEzE,eAAO,MAAM,yBAAyB,EAAE,MAEvC,CAAA;AAED,eAAO,MAAM,6BAA6B,EAAE,UAI3C,CAAA;AAED,OAAO,EAAE,+BAA+B,EAAE,MAAM,oBAAoB,CAAA;AACpE,YAAY,EACV,aAAa,EACb,2BAA2B,EAC3B,qBAAqB,EACrB,4BAA4B,EAC5B,0BAA0B,EAC1B,gBAAgB,EAChB,8BAA8B,EAC9B,wBAAwB,EACxB,+BAA+B,EAC/B,6BAA6B,EAC7B,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EACtB,6BAA6B,EAC7B,yBAAyB,EACzB,8BAA8B,EAC9B,2BAA2B,EAC3B,2BAA2B,EAC3B,2BAA2B,EAC3B,sBAAsB,EACtB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,EACzB,0CAA0C,EAC1C,8BAA8B,EAC9B,oCAAoC,EACpC,2CAA2C,EAC3C,2BAA2B,EAC3B,gCAAgC,EAChC,yCAAyC,EACzC,6BAA6B,EAC7B,6BAA6B,EAC7B,yBAAyB,EACzB,uCAAuC,EACvC,iCAAiC,EACjC,wCAAwC,EACxC,sCAAsC,EACtC,iCAAiC,EACjC,kCAAkC,EAClC,qCAAqC,EACrC,oCAAoC,EACpC,qCAAqC,EACrC,wCAAwC,EACxC,uCAAuC,EACvC,sCAAsC,EACtC,iCAAiC,EACjC,+BAA+B,EAC/B,yBAAyB,EACzB,uCAAuC,EACvC,iCAAiC,EACjC,wCAAwC,EACxC,sCAAsC,EACtC,iCAAiC,EACjC,kCAAkC,EAClC,qCAAqC,GACtC,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,0BAA0B,EAAE,CAAA"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { bookingRequirementsRoutes } from "./routes.js";
2
+ import { publicBookingRequirementsRoutes } from "./routes-public.js";
2
3
  import { bookingRequirementsService } from "./service.js";
3
4
  export const bookingRequirementsModule = {
4
5
  name: "booking-requirements",
@@ -6,7 +7,9 @@ export const bookingRequirementsModule = {
6
7
  export const bookingRequirementsHonoModule = {
7
8
  module: bookingRequirementsModule,
8
9
  routes: bookingRequirementsRoutes,
10
+ publicRoutes: publicBookingRequirementsRoutes,
9
11
  };
12
+ export { publicBookingRequirementsRoutes } from "./routes-public.js";
10
13
  export { bookingAnswers, bookingAnswerTargetEnum, bookingQuestionExtraTriggers, bookingQuestionFieldTypeEnum, bookingQuestionOptions, bookingQuestionOptionTriggers, bookingQuestionTargetEnum, bookingQuestionTriggerModeEnum, bookingQuestionUnitTriggers, contactRequirementFieldEnum, contactRequirementScopeEnum, optionBookingQuestions, productBookingQuestions, productContactRequirements, } from "./schema.js";
11
- export { bookingAnswerListQuerySchema, bookingAnswerTargetSchema, bookingQuestionExtraTriggerListQuerySchema, bookingQuestionFieldTypeSchema, bookingQuestionOptionListQuerySchema, bookingQuestionOptionTriggerListQuerySchema, bookingQuestionTargetSchema, bookingQuestionTriggerModeSchema, bookingQuestionUnitTriggerListQuerySchema, contactRequirementFieldSchema, contactRequirementScopeSchema, insertBookingAnswerSchema, insertBookingQuestionExtraTriggerSchema, insertBookingQuestionOptionSchema, insertBookingQuestionOptionTriggerSchema, insertBookingQuestionUnitTriggerSchema, insertOptionBookingQuestionSchema, insertProductBookingQuestionSchema, insertProductContactRequirementSchema, optionBookingQuestionListQuerySchema, productBookingQuestionListQuerySchema, productContactRequirementListQuerySchema, updateBookingAnswerSchema, updateBookingQuestionExtraTriggerSchema, updateBookingQuestionOptionSchema, updateBookingQuestionOptionTriggerSchema, updateBookingQuestionUnitTriggerSchema, updateOptionBookingQuestionSchema, updateProductBookingQuestionSchema, updateProductContactRequirementSchema, } from "./validation.js";
14
+ export { bookingAnswerListQuerySchema, bookingAnswerTargetSchema, bookingQuestionExtraTriggerListQuerySchema, bookingQuestionFieldTypeSchema, bookingQuestionOptionListQuerySchema, bookingQuestionOptionTriggerListQuerySchema, bookingQuestionTargetSchema, bookingQuestionTriggerModeSchema, bookingQuestionUnitTriggerListQuerySchema, contactRequirementFieldSchema, contactRequirementScopeSchema, insertBookingAnswerSchema, insertBookingQuestionExtraTriggerSchema, insertBookingQuestionOptionSchema, insertBookingQuestionOptionTriggerSchema, insertBookingQuestionUnitTriggerSchema, insertOptionBookingQuestionSchema, insertProductBookingQuestionSchema, insertProductContactRequirementSchema, optionBookingQuestionListQuerySchema, productBookingQuestionListQuerySchema, productContactRequirementListQuerySchema, publicTransportRequirementSummarySchema, publicTransportRequirementsQuerySchema, publicTransportRequirementsSchema, transportRequirementFieldSchema, updateBookingAnswerSchema, updateBookingQuestionExtraTriggerSchema, updateBookingQuestionOptionSchema, updateBookingQuestionOptionTriggerSchema, updateBookingQuestionUnitTriggerSchema, updateOptionBookingQuestionSchema, updateProductBookingQuestionSchema, updateProductContactRequirementSchema, } from "./validation.js";
12
15
  export { bookingRequirementsService };
@@ -0,0 +1,59 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ type Env = {
3
+ Variables: {
4
+ db: PostgresJsDatabase;
5
+ userId?: string;
6
+ };
7
+ };
8
+ export declare const publicBookingRequirementsRoutes: import("hono/hono-base").HonoBase<Env, {
9
+ "/products/:productId/transport-requirements": {
10
+ $get: {
11
+ input: {
12
+ param: {
13
+ productId: string;
14
+ };
15
+ };
16
+ output: {
17
+ error: string;
18
+ };
19
+ outputFormat: "json";
20
+ status: 404;
21
+ } | {
22
+ input: {
23
+ param: {
24
+ productId: string;
25
+ };
26
+ };
27
+ output: {
28
+ data: {
29
+ productId: string;
30
+ optionId: string | null;
31
+ hasTransport: boolean;
32
+ requiresPassengerDocuments: boolean;
33
+ requiresPassport: boolean;
34
+ requiresNationality: boolean;
35
+ requiresDateOfBirth: boolean;
36
+ requiredFields: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
37
+ fieldsByScope: {
38
+ booking: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
39
+ lead_traveler: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
40
+ participant: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
41
+ booker: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
42
+ };
43
+ requirements: {
44
+ fieldKey: "date_of_birth" | "nationality" | "passport_number" | "passport_expiry";
45
+ scope: "booking" | "lead_traveler" | "participant" | "booker";
46
+ isRequired: boolean;
47
+ perParticipant: boolean;
48
+ notes: string | null;
49
+ }[];
50
+ };
51
+ };
52
+ outputFormat: "json";
53
+ status: import("hono/utils/http-status").ContentfulStatusCode;
54
+ };
55
+ };
56
+ }, "/", "/products/:productId/transport-requirements">;
57
+ export type PublicBookingRequirementsRoutes = typeof publicBookingRequirementsRoutes;
58
+ export {};
59
+ //# sourceMappingURL=routes-public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAMjE,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAmB3C,CAAA;AAED,MAAM,MAAM,+BAA+B,GAAG,OAAO,+BAA+B,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { Hono } from "hono";
2
+ import { bookingRequirementsService } from "./service.js";
3
+ import { publicTransportRequirementsQuerySchema } from "./validation.js";
4
+ export const publicBookingRequirementsRoutes = new Hono().get("/products/:productId/transport-requirements", async (c) => {
5
+ const query = publicTransportRequirementsQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
6
+ const result = await bookingRequirementsService.getPublicTransportRequirements(c.get("db"), c.req.param("productId"), query);
7
+ if (!result) {
8
+ return c.json({ error: "Product not found" }, 404);
9
+ }
10
+ return c.json({ data: result });
11
+ });
@@ -0,0 +1,71 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import type { BookingAnswerListQuery, CreateBookingAnswerInput, UpdateBookingAnswerInput } from "./service-shared.js";
3
+ export declare function listBookingAnswers(db: PostgresJsDatabase, query: BookingAnswerListQuery): Promise<{
4
+ data: {
5
+ id: string;
6
+ bookingId: string;
7
+ productBookingQuestionId: string;
8
+ bookingParticipantId: string | null;
9
+ bookingExtraId: string | null;
10
+ target: "booking" | "participant" | "extra";
11
+ valueText: string | null;
12
+ valueNumber: number | null;
13
+ valueBoolean: boolean | null;
14
+ valueJson: Record<string, unknown> | string[] | null;
15
+ notes: string | null;
16
+ createdAt: Date;
17
+ updatedAt: Date;
18
+ }[];
19
+ total: number;
20
+ limit: number;
21
+ offset: number;
22
+ }>;
23
+ export declare function getBookingAnswerById(db: PostgresJsDatabase, id: string): Promise<{
24
+ id: string;
25
+ bookingId: string;
26
+ productBookingQuestionId: string;
27
+ bookingParticipantId: string | null;
28
+ bookingExtraId: string | null;
29
+ target: "booking" | "participant" | "extra";
30
+ valueText: string | null;
31
+ valueNumber: number | null;
32
+ valueBoolean: boolean | null;
33
+ valueJson: Record<string, unknown> | string[] | null;
34
+ notes: string | null;
35
+ createdAt: Date;
36
+ updatedAt: Date;
37
+ } | null>;
38
+ export declare function createBookingAnswer(db: PostgresJsDatabase, data: CreateBookingAnswerInput): Promise<{
39
+ id: string;
40
+ notes: string | null;
41
+ createdAt: Date;
42
+ updatedAt: Date;
43
+ target: "booking" | "participant" | "extra";
44
+ productBookingQuestionId: string;
45
+ bookingId: string;
46
+ bookingParticipantId: string | null;
47
+ bookingExtraId: string | null;
48
+ valueText: string | null;
49
+ valueNumber: number | null;
50
+ valueBoolean: boolean | null;
51
+ valueJson: Record<string, unknown> | string[] | null;
52
+ } | null>;
53
+ export declare function updateBookingAnswer(db: PostgresJsDatabase, id: string, data: UpdateBookingAnswerInput): Promise<{
54
+ id: string;
55
+ bookingId: string;
56
+ productBookingQuestionId: string;
57
+ bookingParticipantId: string | null;
58
+ bookingExtraId: string | null;
59
+ target: "booking" | "participant" | "extra";
60
+ valueText: string | null;
61
+ valueNumber: number | null;
62
+ valueBoolean: boolean | null;
63
+ valueJson: Record<string, unknown> | string[] | null;
64
+ notes: string | null;
65
+ createdAt: Date;
66
+ updatedAt: Date;
67
+ } | null>;
68
+ export declare function deleteBookingAnswer(db: PostgresJsDatabase, id: string): Promise<{
69
+ id: string;
70
+ } | null>;
71
+ //# sourceMappingURL=service-answers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-answers.d.ts","sourceRoot":"","sources":["../src/service-answers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EACV,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,qBAAqB,CAAA;AAG5B,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,sBAAsB;;;;;;;;;;;;;;;;;;;GAsB7F;AAED,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;;;;;;;;;;;;;UAG5E;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,wBAAwB;;;;;;;;;;;;;;UAG/F;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,kBAAkB,EACtB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,wBAAwB;;;;;;;;;;;;;;UAQ/B;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM;;UAM3E"}
@@ -0,0 +1,47 @@
1
+ import { and, desc, eq, sql } from "drizzle-orm";
2
+ import { bookingAnswers } from "./schema.js";
3
+ import { paginate } from "./service-shared.js";
4
+ export async function listBookingAnswers(db, query) {
5
+ const conditions = [];
6
+ if (query.bookingId)
7
+ conditions.push(eq(bookingAnswers.bookingId, query.bookingId));
8
+ if (query.productBookingQuestionId)
9
+ conditions.push(eq(bookingAnswers.productBookingQuestionId, query.productBookingQuestionId));
10
+ if (query.bookingParticipantId)
11
+ conditions.push(eq(bookingAnswers.bookingParticipantId, query.bookingParticipantId));
12
+ if (query.bookingExtraId)
13
+ conditions.push(eq(bookingAnswers.bookingExtraId, query.bookingExtraId));
14
+ if (query.target)
15
+ conditions.push(eq(bookingAnswers.target, query.target));
16
+ const where = conditions.length ? and(...conditions) : undefined;
17
+ return paginate(db
18
+ .select()
19
+ .from(bookingAnswers)
20
+ .where(where)
21
+ .limit(query.limit)
22
+ .offset(query.offset)
23
+ .orderBy(desc(bookingAnswers.updatedAt)), db.select({ count: sql `count(*)::int` }).from(bookingAnswers).where(where), query.limit, query.offset);
24
+ }
25
+ export async function getBookingAnswerById(db, id) {
26
+ const [row] = await db.select().from(bookingAnswers).where(eq(bookingAnswers.id, id)).limit(1);
27
+ return row ?? null;
28
+ }
29
+ export async function createBookingAnswer(db, data) {
30
+ const [row] = await db.insert(bookingAnswers).values(data).returning();
31
+ return row ?? null;
32
+ }
33
+ export async function updateBookingAnswer(db, id, data) {
34
+ const [row] = await db
35
+ .update(bookingAnswers)
36
+ .set({ ...data, updatedAt: new Date() })
37
+ .where(eq(bookingAnswers.id, id))
38
+ .returning();
39
+ return row ?? null;
40
+ }
41
+ export async function deleteBookingAnswer(db, id) {
42
+ const [row] = await db
43
+ .delete(bookingAnswers)
44
+ .where(eq(bookingAnswers.id, id))
45
+ .returning({ id: bookingAnswers.id });
46
+ return row ?? null;
47
+ }
@@ -0,0 +1,29 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import type { PublicTransportRequirementsQuery } from "./service-shared.js";
3
+ declare const transportFieldKeys: readonly ["date_of_birth", "nationality", "passport_number", "passport_expiry"];
4
+ type TransportFieldKey = (typeof transportFieldKeys)[number];
5
+ export declare function getPublicTransportRequirements(db: PostgresJsDatabase, productId: string, query: PublicTransportRequirementsQuery): Promise<{
6
+ productId: string;
7
+ optionId: string | null;
8
+ hasTransport: boolean;
9
+ requiresPassengerDocuments: boolean;
10
+ requiresPassport: boolean;
11
+ requiresNationality: boolean;
12
+ requiresDateOfBirth: boolean;
13
+ requiredFields: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
14
+ fieldsByScope: {
15
+ booking: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
16
+ lead_traveler: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
17
+ participant: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
18
+ booker: ("date_of_birth" | "nationality" | "passport_number" | "passport_expiry")[];
19
+ };
20
+ requirements: {
21
+ fieldKey: TransportFieldKey;
22
+ scope: "booking" | "lead_traveler" | "participant" | "booker";
23
+ isRequired: boolean;
24
+ perParticipant: boolean;
25
+ notes: string | null;
26
+ }[];
27
+ } | null>;
28
+ export {};
29
+ //# sourceMappingURL=service-public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAA;AAE3E,QAAA,MAAM,kBAAkB,iFAKd,CAAA;AAEV,KAAK,iBAAiB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAgB5D,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,kBAAkB,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,gCAAgC;;;;;;;;;;;;;;;;kBAiET,iBAAiB;;;;;;UAOhD"}
@@ -0,0 +1,66 @@
1
+ import { productCapabilities, products } from "@voyantjs/products/schema";
2
+ import { and, asc, eq, isNull, or } from "drizzle-orm";
3
+ import { productContactRequirements } from "./schema.js";
4
+ const transportFieldKeys = [
5
+ "date_of_birth",
6
+ "nationality",
7
+ "passport_number",
8
+ "passport_expiry",
9
+ ];
10
+ function uniqueSorted(values) {
11
+ return Array.from(new Set(values)).sort();
12
+ }
13
+ function summarizeFields(rows, scope) {
14
+ return uniqueSorted(rows.filter((row) => row.scope === scope).map((row) => row.fieldKey));
15
+ }
16
+ export async function getPublicTransportRequirements(db, productId, query) {
17
+ const [product, capabilityRows, requirementRows] = await Promise.all([
18
+ db
19
+ .select()
20
+ .from(products)
21
+ .where(eq(products.id, productId))
22
+ .limit(1)
23
+ .then((rows) => rows[0] ?? null),
24
+ db
25
+ .select({ capability: productCapabilities.capability })
26
+ .from(productCapabilities)
27
+ .where(and(eq(productCapabilities.productId, productId), eq(productCapabilities.enabled, true)))
28
+ .orderBy(asc(productCapabilities.capability)),
29
+ db
30
+ .select()
31
+ .from(productContactRequirements)
32
+ .where(and(eq(productContactRequirements.productId, productId), eq(productContactRequirements.active, true), query.optionId
33
+ ? or(eq(productContactRequirements.optionId, query.optionId), isNull(productContactRequirements.optionId))
34
+ : isNull(productContactRequirements.optionId)))
35
+ .orderBy(asc(productContactRequirements.sortOrder), asc(productContactRequirements.createdAt)),
36
+ ]);
37
+ if (!product) {
38
+ return null;
39
+ }
40
+ const relevantRows = requirementRows.filter((row) => transportFieldKeys.includes(row.fieldKey));
41
+ const requiredRows = relevantRows.filter((row) => row.isRequired);
42
+ const capabilitySet = new Set(capabilityRows.map((row) => row.capability));
43
+ return {
44
+ productId,
45
+ optionId: query.optionId ?? null,
46
+ hasTransport: product.bookingMode === "transfer" || capabilitySet.has("transport"),
47
+ requiresPassengerDocuments: requiredRows.length > 0,
48
+ requiresPassport: requiredRows.some((row) => row.fieldKey === "passport_number" || row.fieldKey === "passport_expiry"),
49
+ requiresNationality: requiredRows.some((row) => row.fieldKey === "nationality"),
50
+ requiresDateOfBirth: requiredRows.some((row) => row.fieldKey === "date_of_birth"),
51
+ requiredFields: uniqueSorted(requiredRows.map((row) => row.fieldKey)),
52
+ fieldsByScope: {
53
+ booking: summarizeFields(relevantRows, "booking"),
54
+ lead_traveler: summarizeFields(relevantRows, "lead_traveler"),
55
+ participant: summarizeFields(relevantRows, "participant"),
56
+ booker: summarizeFields(relevantRows, "booker"),
57
+ },
58
+ requirements: relevantRows.map((row) => ({
59
+ fieldKey: row.fieldKey,
60
+ scope: row.scope,
61
+ isRequired: row.isRequired,
62
+ perParticipant: row.perParticipant,
63
+ notes: row.notes ?? null,
64
+ })),
65
+ };
66
+ }