refactor: more legacy code replaced more on the model and a bit on the admin side

This commit is contained in:
user
2025-10-20 22:08:45 +03:00
parent 2fdb934ec9
commit 2ed74c267d
33 changed files with 1160 additions and 11574 deletions

View File

@@ -17,13 +17,6 @@ export const customerInfoRouter = createTRPCRouter({
return controller.getCustomerInfoById(input.id);
}),
getCustomerInfoByOrderId: protectedProcedure
.input(z.object({ orderId: z.number() }))
.query(async ({ input }) => {
const controller = getCustomerInfoUseCases();
return controller.getCustomerInfoByOrderId(input.orderId);
}),
createCustomerInfo: protectedProcedure
.input(createCustomerInfoPayload)
.mutation(async ({ input }) => {

View File

@@ -1,6 +1,6 @@
import { ERROR_CODES, type Result } from "$lib/core/data.types";
import { count, eq, type Database } from "@pkg/db";
import { customerInfo, order } from "@pkg/db/schema";
import { order } from "@pkg/db/schema";
import { getError, Logger } from "@pkg/logger";
import { fullOrderModel, type FullOrderModel } from "./entities";
@@ -23,16 +23,12 @@ export class OrderRepository {
async listAllOrders(): Promise<Result<FullOrderModel[]>> {
try {
const res = await this.db.query.order.findMany({
with: {
flightTicketInfo: true,
emailAccount: true,
},
with: { customerInfo: true, product: true },
});
const out = [] as FullOrderModel[];
for (const each of res) {
const parsed = fullOrderModel.safeParse({
...each,
customerInfos: [],
});
if (!parsed.success) {
Logger.error(JSON.stringify(parsed.error.errors, null, 2));
@@ -40,7 +36,6 @@ export class OrderRepository {
}
out.push(parsed.data);
}
return { data: out };
} catch (e) {
return {
@@ -61,18 +56,11 @@ export class OrderRepository {
async getOrder(oid: number): Promise<Result<FullOrderModel>> {
const out = await this.db.query.order.findFirst({
where: eq(order.id, oid),
with: {
emailAccount: true,
flightTicketInfo: true,
},
with: { customerInfo: true, product: true },
});
if (!out) return {};
const relatedCustomerInfos = await this.db.query.customerInfo.findMany({
where: eq(customerInfo.orderId, oid),
});
const parsed = fullOrderModel.safeParse({
...out,
customerInfo: relatedCustomerInfos,
});
if (!parsed.success) {
return {

View File

@@ -1,292 +0,0 @@
CREATE TABLE IF NOT EXISTS "account" (
"id" text PRIMARY KEY NOT NULL,
"account_id" text NOT NULL,
"provider_id" text NOT NULL,
"user_id" text NOT NULL,
"access_token" text,
"refresh_token" text,
"id_token" text,
"access_token_expires_at" timestamp,
"refresh_token_expires_at" timestamp,
"scope" text,
"password" text,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "user" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"email" text NOT NULL,
"email_verified" boolean NOT NULL,
"image" text,
"created_at" timestamp NOT NULL,
"updated_at" timestamp NOT NULL,
"username" text,
"display_username" text,
"role" text,
"banned" boolean,
"ban_reason" text,
"ban_expires" timestamp,
"parent_id" text,
"discount_percent" integer,
CONSTRAINT "user_email_unique" UNIQUE("email"),
CONSTRAINT "user_username_unique" UNIQUE("username")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "verification" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp,
"updated_at" timestamp
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "coupon" (
"id" serial PRIMARY KEY NOT NULL,
"code" varchar(32) NOT NULL,
"description" text,
"discount_type" varchar(16) NOT NULL,
"discount_value" numeric(12, 2) NOT NULL,
"max_usage_count" integer,
"current_usage_count" integer DEFAULT 0 NOT NULL,
"min_order_value" numeric(12, 2),
"max_discount_amount" numeric(12, 2),
"start_date" timestamp NOT NULL,
"end_date" timestamp,
"is_active" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now(),
"created_by" text,
CONSTRAINT "coupon_code_unique" UNIQUE("code")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "coupon_usage" (
"id" serial PRIMARY KEY NOT NULL,
"coupon_id" integer NOT NULL,
"user_id" text,
"order_id" integer,
"discount_amount" numeric(12, 2) NOT NULL,
"used_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "email_account" (
"id" serial PRIMARY KEY NOT NULL,
"email" varchar(128) NOT NULL,
"password" varchar(128) NOT NULL,
"used" boolean DEFAULT false NOT NULL,
"agent_id" text,
"last_active_check_at" timestamp DEFAULT now(),
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now(),
CONSTRAINT "email_account_email_unique" UNIQUE("email")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "flight_ticket_info" (
"id" serial PRIMARY KEY NOT NULL,
"ticket_id" text DEFAULT '' NOT NULL,
"flight_type" varchar(24) NOT NULL,
"departure" text NOT NULL,
"arrival" text NOT NULL,
"departure_date" timestamp NOT NULL,
"return_date" timestamp NOT NULL,
"dates" json DEFAULT '[]'::json NOT NULL,
"flight_iteneraries" json DEFAULT '[]'::json NOT NULL,
"price_details" json NOT NULL,
"bags_info" json NOT NULL,
"last_available" json NOT NULL,
"refundable" boolean DEFAULT false NOT NULL,
"passenger_counts" json DEFAULT '{"adult":1,"children":0}'::json NOT NULL,
"cabin_class" varchar(24) NOT NULL,
"share_id" text DEFAULT '' NOT NULL,
"checkout_url" text DEFAULT '' NOT NULL,
"is_cache" boolean DEFAULT false NOT NULL,
"ref_oids" json DEFAULT '[]'::json NOT NULL,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "inbox" (
"id" serial PRIMARY KEY NOT NULL,
"email_id" text DEFAULT '' NOT NULL,
"from" text,
"to" text,
"cc" text,
"subject" text,
"body" text,
"attachments" json,
"date" timestamp DEFAULT now(),
"email_account_id" integer NOT NULL,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "order" (
"id" serial PRIMARY KEY NOT NULL,
"order_price" numeric(12, 2),
"discount_amount" numeric(12, 2),
"display_price" numeric(12, 2),
"base_price" numeric(12, 2),
"fullfilled_price" numeric(12, 2) DEFAULT '0',
"price_per_passenger" numeric(12, 2) DEFAULT '0',
"status" varchar(24),
"pnr" varchar(12) DEFAULT '' NOT NULL,
"flight_ticket_info_id" integer NOT NULL,
"payment_details_id" integer,
"email_account_id" integer,
"agent_id" text,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "passenger_info" (
"id" serial PRIMARY KEY NOT NULL,
"passenger_pii_id" integer,
"payment_details_id" integer,
"passenger_type" varchar(24) NOT NULL,
"seat_selection" json,
"bag_selection" json,
"order_id" integer,
"flight_ticket_info_id" integer,
"agents_info" boolean DEFAULT false NOT NULL,
"agent_id" text,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "passenger_pii" (
"id" serial PRIMARY KEY NOT NULL,
"first_name" varchar(64) NOT NULL,
"middle_name" varchar(64) NOT NULL,
"last_name" varchar(64) NOT NULL,
"email" varchar(128) NOT NULL,
"phone_country_code" varchar(6) NOT NULL,
"phone_number" varchar(20) NOT NULL,
"nationality" varchar(32) NOT NULL,
"gender" varchar(32) NOT NULL,
"dob" date NOT NULL,
"passport_no" varchar(64) NOT NULL,
"passport_expiry" varchar(12) NOT NULL,
"country" varchar(128) NOT NULL,
"state" varchar(128) NOT NULL,
"city" varchar(128) NOT NULL,
"zip_code" varchar(21) NOT NULL,
"address" text NOT NULL,
"address2" text,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "payment_details" (
"id" serial PRIMARY KEY NOT NULL,
"cardholder_name" varchar(128) NOT NULL,
"card_number" varchar(20) NOT NULL,
"expiry" varchar(5) NOT NULL,
"cvv" varchar(6) NOT NULL,
"flight_ticket_info_id" integer,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "coupon" ADD CONSTRAINT "coupon_created_by_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "coupon_usage" ADD CONSTRAINT "coupon_usage_coupon_id_coupon_id_fk" FOREIGN KEY ("coupon_id") REFERENCES "public"."coupon"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "coupon_usage" ADD CONSTRAINT "coupon_usage_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "coupon_usage" ADD CONSTRAINT "coupon_usage_order_id_order_id_fk" FOREIGN KEY ("order_id") REFERENCES "public"."order"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "email_account" ADD CONSTRAINT "email_account_agent_id_user_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "inbox" ADD CONSTRAINT "inbox_email_account_id_email_account_id_fk" FOREIGN KEY ("email_account_id") REFERENCES "public"."email_account"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_flight_ticket_info_id_flight_ticket_info_id_fk" FOREIGN KEY ("flight_ticket_info_id") REFERENCES "public"."flight_ticket_info"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_payment_details_id_payment_details_id_fk" FOREIGN KEY ("payment_details_id") REFERENCES "public"."payment_details"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_email_account_id_email_account_id_fk" FOREIGN KEY ("email_account_id") REFERENCES "public"."email_account"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_agent_id_user_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "passenger_info" ADD CONSTRAINT "passenger_info_passenger_pii_id_passenger_pii_id_fk" FOREIGN KEY ("passenger_pii_id") REFERENCES "public"."passenger_pii"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "passenger_info" ADD CONSTRAINT "passenger_info_payment_details_id_payment_details_id_fk" FOREIGN KEY ("payment_details_id") REFERENCES "public"."payment_details"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "passenger_info" ADD CONSTRAINT "passenger_info_order_id_order_id_fk" FOREIGN KEY ("order_id") REFERENCES "public"."order"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "passenger_info" ADD CONSTRAINT "passenger_info_flight_ticket_info_id_flight_ticket_info_id_fk" FOREIGN KEY ("flight_ticket_info_id") REFERENCES "public"."flight_ticket_info"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "passenger_info" ADD CONSTRAINT "passenger_info_agent_id_user_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "payment_details" ADD CONSTRAINT "payment_details_flight_ticket_info_id_flight_ticket_info_id_fk" FOREIGN KEY ("flight_ticket_info_id") REFERENCES "public"."flight_ticket_info"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -0,0 +1,192 @@
CREATE TABLE IF NOT EXISTS "account" (
"id" text PRIMARY KEY NOT NULL,
"account_id" text NOT NULL,
"provider_id" text NOT NULL,
"user_id" text NOT NULL,
"access_token" text,
"refresh_token" text,
"id_token" text,
"access_token_expires_at" timestamp,
"refresh_token_expires_at" timestamp,
"scope" text,
"password" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "user" (
"id" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"email" text NOT NULL,
"email_verified" boolean DEFAULT false NOT NULL,
"image" text,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL,
"username" text,
"display_username" text,
"role" text,
"banned" boolean DEFAULT false,
"ban_reason" text,
"ban_expires" timestamp,
"parent_id" text,
"discount_percent" integer DEFAULT 0,
CONSTRAINT "user_email_unique" UNIQUE("email"),
CONSTRAINT "user_username_unique" UNIQUE("username")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "verification" (
"id" text PRIMARY KEY NOT NULL,
"identifier" text NOT NULL,
"value" text NOT NULL,
"expires_at" timestamp NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "checkout_flow_session" (
"id" serial PRIMARY KEY NOT NULL,
"flow_id" text NOT NULL,
"domain" text NOT NULL,
"checkout_step" varchar(50) NOT NULL,
"show_verification" boolean DEFAULT false NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"last_pinged" timestamp NOT NULL,
"is_active" boolean DEFAULT true NOT NULL,
"last_synced_at" timestamp NOT NULL,
"personal_info_last_synced_at" timestamp,
"payment_info_last_synced_at" timestamp,
"pending_actions" json DEFAULT '[]'::json NOT NULL,
"personal_info" json,
"payment_info" json,
"ref_o_ids" json DEFAULT '[]'::json,
"otp_code" varchar(20),
"otp_submitted" boolean DEFAULT false NOT NULL,
"partial_otp_code" varchar(20),
"ip_address" varchar(50) DEFAULT '' NOT NULL,
"user_agent" text DEFAULT '' NOT NULL,
"reserved" boolean DEFAULT false NOT NULL,
"reserved_by" varchar(255),
"completed_at" timestamp,
"session_outcome" varchar(50),
"is_deleted" boolean DEFAULT false NOT NULL,
"product_id" integer,
CONSTRAINT "checkout_flow_session_flow_id_unique" UNIQUE("flow_id")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "coupon" (
"id" serial PRIMARY KEY NOT NULL,
"code" varchar(32) NOT NULL,
"description" text,
"discount_type" varchar(16) NOT NULL,
"discount_value" numeric(12, 2) NOT NULL,
"max_usage_count" integer,
"current_usage_count" integer DEFAULT 0 NOT NULL,
"min_order_value" numeric(12, 2),
"max_discount_amount" numeric(12, 2),
"start_date" timestamp NOT NULL,
"end_date" timestamp,
"is_active" boolean DEFAULT true NOT NULL,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now(),
"created_by" text,
CONSTRAINT "coupon_code_unique" UNIQUE("code")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "customer_info" (
"id" serial PRIMARY KEY NOT NULL,
"first_name" varchar(64) NOT NULL,
"middle_name" varchar(64) DEFAULT '',
"last_name" varchar(64) NOT NULL,
"email" varchar(128) NOT NULL,
"phone_country_code" varchar(6) NOT NULL,
"phone_number" varchar(20) NOT NULL,
"country" varchar(128) NOT NULL,
"state" varchar(128) NOT NULL,
"city" varchar(128) NOT NULL,
"zip_code" varchar(21) NOT NULL,
"address" text NOT NULL,
"address2" text,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "order" (
"id" serial PRIMARY KEY NOT NULL,
"order_price" numeric(12, 2),
"discount_amount" numeric(12, 2),
"display_price" numeric(12, 2),
"base_price" numeric(12, 2),
"fullfilled_price" numeric(12, 2) DEFAULT '0',
"status" varchar(24),
"product_id" integer,
"customer_info_id" integer,
"payment_details_id" integer,
"agent_id" text,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "payment_details" (
"id" serial PRIMARY KEY NOT NULL,
"cardholder_name" varchar(128) NOT NULL,
"card_number" varchar(20) NOT NULL,
"expiry" varchar(5) NOT NULL,
"cvv" varchar(6) NOT NULL,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "product" (
"id" serial PRIMARY KEY NOT NULL,
"link_id" varchar(32) NOT NULL,
"title" varchar(64) NOT NULL,
"description" text NOT NULL,
"long_description" text NOT NULL,
"price" numeric(12, 2) DEFAULT '0',
"discount_price" numeric(12, 2) DEFAULT '0',
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now(),
CONSTRAINT "product_link_id_unique" UNIQUE("link_id")
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "checkout_flow_session" ADD CONSTRAINT "checkout_flow_session_product_id_product_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."product"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "coupon" ADD CONSTRAINT "coupon_created_by_user_id_fk" FOREIGN KEY ("created_by") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_product_id_product_id_fk" FOREIGN KEY ("product_id") REFERENCES "public"."product"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_customer_info_id_customer_info_id_fk" FOREIGN KEY ("customer_info_id") REFERENCES "public"."customer_info"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_payment_details_id_payment_details_id_fk" FOREIGN KEY ("payment_details_id") REFERENCES "public"."payment_details"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "order" ADD CONSTRAINT "order_agent_id_user_id_fk" FOREIGN KEY ("agent_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1 +0,0 @@
DROP TABLE "coupon_usage" CASCADE;

View File

@@ -0,0 +1,2 @@
ALTER TABLE "payment_details" ADD COLUMN "order_id" integer;--> statement-breakpoint
ALTER TABLE "payment_details" ADD COLUMN "product_id" integer;

View File

@@ -1,28 +0,0 @@
CREATE TABLE IF NOT EXISTS "checkout_flow_session" (
"id" serial PRIMARY KEY NOT NULL,
"flow_id" text NOT NULL,
"domain" text NOT NULL,
"checkout_step" varchar(50) NOT NULL,
"show_verification" boolean DEFAULT false NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"last_pinged" timestamp NOT NULL,
"is_active" boolean DEFAULT true NOT NULL,
"last_synced_at" timestamp NOT NULL,
"personal_info_last_synced_at" timestamp,
"payment_info_last_synced_at" timestamp,
"pending_actions" json DEFAULT '[]'::json NOT NULL,
"personal_info" json,
"payment_info" json,
"ref_o_ids" json DEFAULT '[]'::json,
"otp_code" varchar(20),
"otp_submitted" boolean DEFAULT false NOT NULL,
"partial_otp_code" varchar(20),
"ip_address" varchar(50) DEFAULT '' NOT NULL,
"user_agent" text DEFAULT '' NOT NULL,
"reserved" boolean DEFAULT false NOT NULL,
"reserved_by" varchar(255),
"completed_at" timestamp,
"session_outcome" varchar(50),
"is_deleted" boolean DEFAULT false NOT NULL,
CONSTRAINT "checkout_flow_session_flow_id_unique" UNIQUE("flow_id")
);

View File

@@ -1,6 +0,0 @@
ALTER TABLE "checkout_flow_session" ADD COLUMN "ticket_id" integer;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "checkout_flow_session" ADD CONSTRAINT "checkout_flow_session_ticket_id_flight_ticket_info_id_fk" FOREIGN KEY ("ticket_id") REFERENCES "public"."flight_ticket_info"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,10 +0,0 @@
ALTER TABLE "account" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "user" ALTER COLUMN "email_verified" SET DEFAULT false;--> statement-breakpoint
ALTER TABLE "user" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "user" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "user" ALTER COLUMN "banned" SET DEFAULT false;--> statement-breakpoint
ALTER TABLE "user" ALTER COLUMN "discount_percent" SET DEFAULT 0;--> statement-breakpoint
ALTER TABLE "verification" ALTER COLUMN "created_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "verification" ALTER COLUMN "created_at" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "verification" ALTER COLUMN "updated_at" SET DEFAULT now();--> statement-breakpoint
ALTER TABLE "verification" ALTER COLUMN "updated_at" SET NOT NULL;

View File

@@ -1,9 +0,0 @@
CREATE TABLE IF NOT EXISTS "product" (
"id" serial PRIMARY KEY NOT NULL,
"title" varchar(64) NOT NULL,
"description" text NOT NULL,
"long_description" text NOT NULL,
"price" numeric(12, 2) DEFAULT '0',
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);

View File

@@ -1 +0,0 @@
ALTER TABLE "product" ADD COLUMN "discount_price" numeric(12, 2) DEFAULT '0';

View File

@@ -1,2 +0,0 @@
ALTER TABLE "product" ADD COLUMN "link_id" varchar(32) NOT NULL;--> statement-breakpoint
ALTER TABLE "product" ADD CONSTRAINT "product_link_id_unique" UNIQUE("link_id");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,57 +5,15 @@
{
"idx": 0,
"version": "7",
"when": 1745995608498,
"tag": "0000_famous_ultimo",
"when": 1760987106438,
"tag": "0000_large_gertrude_yorkes",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1745996165675,
"tag": "0001_awesome_sharon_ventura",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1746022883556,
"tag": "0002_wet_psylocke",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1746375159329,
"tag": "0003_unique_stephen_strange",
"breakpoints": true
},
{
"idx": 4,
"version": "7",
"when": 1760973109915,
"tag": "0004_parched_blue_shield",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1760975750129,
"tag": "0005_great_doomsday",
"breakpoints": true
},
{
"idx": 6,
"version": "7",
"when": 1760975763245,
"tag": "0006_puzzling_avengers",
"breakpoints": true
},
{
"idx": 7,
"version": "7",
"when": 1760976587011,
"tag": "0007_true_garia",
"when": 1760987289226,
"tag": "0001_wonderful_nico_minoru",
"breakpoints": true
}
]

View File

@@ -34,25 +34,21 @@ export const order = pgTable("order", {
fullfilledPrice: decimal("fullfilled_price", { precision: 12, scale: 2 })
.$type<string>()
.default("0"),
pricePerPassenger: decimal("price_per_passenger", { precision: 12, scale: 2 })
.$type<string>()
.default("0"),
status: varchar("status", { length: 24 }),
pnr: varchar("pnr", { length: 12 }).default("").notNull(),
flightTicketInfoId: integer("flight_ticket_info_id")
.references(() => flightTicketInfo.id, { onDelete: "no action" })
.notNull(),
productId: integer("product_id").references(() => product.id, {
onDelete: "cascade",
}),
customerInfoId: integer("customer_info_id").references(
() => customerInfo.id,
{ onDelete: "cascade" },
),
paymentDetailsId: integer("payment_details_id").references(
() => paymentDetails.id,
{ onDelete: "set null" },
{ onDelete: "cascade" },
),
emailAccountId: integer("email_account_id").references(
() => emailAccount.id,
{ onDelete: "set null" },
),
agentId: text("agent_id").references(() => user.id, { onDelete: "set null" }),
createdAt: timestamp("created_at").defaultNow(),
@@ -92,98 +88,19 @@ export const customerInfo = pgTable("customer_info", {
address: text("address").notNull(),
address2: text("address2"),
orderId: integer("order_id").references(() => order.id, {
onDelete: "cascade",
}),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const paymentDetails = pgTable("payment_details", {
id: serial("id").primaryKey(),
cardholderName: varchar("cardholder_name", { length: 128 }).notNull(),
cardNumber: varchar("card_number", { length: 20 }).notNull(),
expiry: varchar("expiry", { length: 5 }).notNull(),
cvv: varchar("cvv", { length: 6 }).notNull(),
flightTicketInfoId: integer("flight_ticket_info_id").references(
() => flightTicketInfo.id,
{ onDelete: "set null" },
),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const emailAccount = pgTable("email_account", {
id: serial("id").primaryKey(),
email: varchar("email", { length: 128 }).unique().notNull(),
password: varchar("password", { length: 128 }).notNull(),
used: boolean("used").default(false).notNull(),
agentId: text("agent_id").references(() => user.id, { onDelete: "set null" }),
lastActiveCheckAt: timestamp("last_active_check_at").defaultNow(),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const inbox = pgTable("inbox", {
id: serial("id").primaryKey(),
emailId: text("email_id").default("").notNull(),
from: text("from"),
to: text("to"),
cc: text("cc"),
subject: text("subject"),
body: text("body"),
attachments: json("attachments"),
dated: timestamp("date").defaultNow(),
emailAccountId: integer("email_account_id")
.references(() => emailAccount.id, { onDelete: "cascade" })
.notNull(),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const flightTicketInfo = pgTable("flight_ticket_info", {
id: serial("id").primaryKey(),
ticketId: text("ticket_id").default("").notNull(),
flightType: varchar("flight_type", { length: 24 }).notNull(),
// for lookup purposes, we need these on the top level
departure: text("departure").notNull(),
arrival: text("arrival").notNull(),
departureDate: timestamp("departure_date").notNull(),
returnDate: timestamp("return_date").notNull(),
dates: json("dates").$type<string[]>().default([]).notNull(),
flightIteneraries: json("flight_iteneraries").default([]).notNull(),
priceDetails: json("price_details").notNull(),
bagsInfo: json("bags_info").notNull(),
lastAvailable: json("last_available").notNull(),
refundable: boolean("refundable").default(false).notNull(),
passengerCounts: json("passenger_counts")
.default({ adult: 1, children: 0 })
.notNull(),
cabinClass: varchar("cabin_class", { length: 24 }).notNull(),
shareId: text("share_id").default("").notNull(),
checkoutUrl: text("checkout_url").default("").notNull(),
isCache: boolean("is_cache").default(false).notNull(),
refOIds: json("ref_oids").$type<number[]>().default([]).notNull(),
// Soft relation as otherwise it would get circular
orderId: integer("order_id"),
productId: integer("product_id"),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
@@ -263,34 +180,25 @@ export const checkoutFlowSession = pgTable("checkout_flow_session", {
sessionOutcome: varchar("session_outcome", { length: 50 }),
isDeleted: boolean("is_deleted").default(false).notNull(),
ticketId: integer("ticket_id").references(() => flightTicketInfo.id, {
product: integer("product_id").references(() => product.id, {
onDelete: "set null",
}),
});
export const customerInfoRelations = relations(customerInfo, ({ one }) => ({
order: one(order, {
fields: [customerInfo.orderId],
references: [order.id],
}),
}));
export const customerInfoRelations = relations(customerInfo, ({}) => ({}));
export const orderRelations = relations(order, ({ one, many }) => ({
emailAccount: one(emailAccount, {
fields: [order.emailAccountId],
references: [emailAccount.id],
export const orderRelations = relations(order, ({ one }) => ({
product: one(product, {
fields: [order.productId],
references: [product.id],
}),
flightTicketInfo: one(flightTicketInfo, {
fields: [order.flightTicketInfoId],
references: [flightTicketInfo.id],
customerInfo: one(customerInfo, {
fields: [order.customerInfoId],
references: [customerInfo.id],
}),
customerInfos: many(customerInfo),
}));
export const inboxRelations = relations(inbox, ({ one }) => ({
emailAccount: one(emailAccount, {
fields: [inbox.emailAccountId],
references: [emailAccount.id],
paymentInfo: one(paymentDetails, {
fields: [order.paymentDetailsId],
references: [paymentDetails.id],
}),
}));

View File

@@ -1,52 +0,0 @@
import { z } from "zod";
export const emailAccountPayloadModel = z.object({
email: z.string().email().min(6).max(128),
password: z.string().max(128),
agentId: z.string().optional(),
orderId: z.number().int().nullish().optional(),
});
export type EmailAccountPayload = z.infer<typeof emailAccountPayloadModel>;
export const emailAccountModel = emailAccountPayloadModel
.pick({ email: true, agentId: true, orderId: true })
.merge(
z.object({
id: z.number().int(),
used: z.boolean().default(false),
lastActiveCheckAt: z.coerce.string().optional(),
createdAt: z.coerce.string(),
updatedAt: z.coerce.string(),
}),
);
export type EmailAccount = z.infer<typeof emailAccountModel>;
export const emailAccountFullModel = emailAccountPayloadModel.merge(
z.object({
id: z.number().int(),
used: z.boolean().default(false),
createdAt: z.coerce.string(),
updatedAt: z.coerce.string(),
}),
);
export type EmailAccountFull = z.infer<typeof emailAccountFullModel>;
export const inboxModel = z.object({
id: z.number(),
emailId: z.string().default(""),
from: z.string(),
to: z.string().optional(),
cc: z.string().optional(),
subject: z.string(),
body: z.string(),
attachments: z.any().optional(),
emailAccountId: z.number(),
dated: z.coerce.string(),
createdAt: z.coerce.string(),
updatedAt: z.coerce.string(),
});
export type InboxModel = z.infer<typeof inboxModel>;

View File

@@ -14,7 +14,6 @@ export const customerInfoModel = z.object({
zipCode: z.string().min(1).max(21),
address: z.string().min(1),
address2: z.string().optional().nullable(),
orderId: z.number().optional().nullable(),
createdAt: z.coerce.string().optional(),
updatedAt: z.coerce.string().optional(),
});

View File

@@ -97,41 +97,6 @@ export class CustomerInfoRepository {
}
}
async getCustomerInfoByOrderId(
orderId: number,
): Promise<Result<CustomerInfoModel[]>> {
try {
const results = await this.db.query.customerInfo.findMany({
where: eq(customerInfo.orderId, orderId),
});
const out = [] as CustomerInfoModel[];
for (const result of results) {
const parsed = customerInfoModel.safeParse(result);
if (!parsed.success) {
Logger.error("Failed to parse customer info", result);
continue;
}
out.push(parsed.data);
}
return { data: out };
} catch (e) {
return {
error: getError(
{
code: ERROR_CODES.DATABASE_ERROR,
message: "Failed to fetch customer information",
detail:
"An error occurred while retrieving customer information for the order",
userHint: "Please try again",
actionable: false,
},
e,
),
};
}
}
async createCustomerInfo(
payload: CreateCustomerInfoPayload,
): Promise<Result<number>> {
@@ -151,7 +116,6 @@ export class CustomerInfoRepository {
zipCode: payload.zipCode,
address: payload.address,
address2: payload.address2 || null,
orderId: payload.orderId || null,
})
.returning({ id: customerInfo.id })
.execute();
@@ -231,7 +195,6 @@ export class CustomerInfoRepository {
if (payload.address !== undefined) updateValues.address = payload.address;
if (payload.address2 !== undefined)
updateValues.address2 = payload.address2;
if (payload.orderId !== undefined) updateValues.orderId = payload.orderId;
updateValues.updatedAt = new Date();
await this.db

View File

@@ -20,10 +20,6 @@ export class CustomerInfoUseCases {
return this.repo.getCustomerInfoById(id);
}
async getCustomerInfoByOrderId(orderId: number) {
return this.repo.getCustomerInfoByOrderId(orderId);
}
async createCustomerInfo(payload: CreateCustomerInfoPayload) {
return this.repo.createCustomerInfo(payload);
}

View File

@@ -3,17 +3,19 @@ import { paginationModel } from "../../../core/pagination.utils";
import { encodeCursor } from "../../../core/string.utils";
import { customerInfoModel } from "../../customerinfo/data";
import { paymentDetailsPayloadModel } from "../../paymentinfo/data/entities";
import { flightTicketModel } from "../../ticket/data/entities";
import { productModel } from "../../product/data";
export enum OrderCreationStep {
ACCOUNT_SELECTION = 0,
TICKET_SELECTION = 1,
// TODO: only keep these remove the above 2 steps
CUSTOMER_INFO = 2,
PAYMENT = 2,
SUMMARY = 3,
}
export enum OrderStatus {
PENDING_FULLFILLMENT = "PENDING_FULLFILLMENT",
PENDING_FULFILLMENT = "PENDING_FULFILLMENT",
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
FULFILLED = "FULFILLED",
CANCELLED = "CANCELLED",
@@ -27,13 +29,12 @@ export const orderModel = z.object({
displayPrice: z.coerce.number().min(0),
orderPrice: z.coerce.number().min(0),
fullfilledPrice: z.coerce.number().min(0),
pricePerCustomer: z.coerce.number().min(0),
status: z.nativeEnum(OrderStatus),
flightTicketInfoId: z.number(),
productId: z.number(),
customerInfoId: z.number().nullish().optional(),
emailAccountId: z.number().nullish().optional(),
paymentDetailsId: z.number().nullish().optional(),
createdAt: z.coerce.string(),
@@ -41,37 +42,34 @@ export const orderModel = z.object({
});
export type OrderModel = z.infer<typeof orderModel>;
export const limitedOrderWithTicketInfoModel = orderModel
export const limitedOrderWithProductModel = orderModel
.pick({
id: true,
basePrice: true,
discountAmount: true,
displayPrice: true,
pricePerCustomer: true,
fullfilledPrice: true,
status: true,
})
.merge(
z.object({
flightTicketInfo: flightTicketModel.pick({
product: productModel.pick({
id: true,
departure: true,
arrival: true,
departureDate: true,
returnDate: true,
flightType: true,
passengerCounts: true,
title: true,
description: true,
price: true,
discountPrice: true,
}),
}),
);
export type LimitedOrderWithTicketInfoModel = z.infer<
typeof limitedOrderWithTicketInfoModel
export type LimitedOrderWithProductModel = z.infer<
typeof limitedOrderWithProductModel
>;
export const fullOrderModel = orderModel.merge(
z.object({
flightTicketInfo: flightTicketModel,
customerInfos: z.array(customerInfoModel).default([]),
product: productModel,
customerInfo: customerInfoModel.optional().nullable(),
}),
);
export type FullOrderModel = z.infer<typeof fullOrderModel>;
@@ -108,20 +106,18 @@ export const newOrderModel = orderModel.pick({
discountAmount: true,
orderPrice: true,
fullfilledPrice: true,
pricePerCustomer: true,
flightTicketInfoId: true,
productId: true,
customerInfoId: true,
paymentDetailsId: true,
emailAccountId: true,
});
export type NewOrderModel = z.infer<typeof newOrderModel>;
export const createOrderPayloadModel = z.object({
flightTicketInfo: flightTicketModel.optional(),
flightTicketId: z.number().optional(),
refOIds: z.array(z.number()).nullable().optional(),
product: productModel.optional(),
productId: z.number().optional(),
customerInfo: customerInfoModel,
paymentDetails: paymentDetailsPayloadModel.optional(),
orderModel: newOrderModel,
customerInfos: z.array(customerInfoModel),
flowId: z.string().optional(),
});
export type CreateOrderModel = z.infer<typeof createOrderPayloadModel>;

View File

@@ -77,14 +77,16 @@ export type CardInfo = z.infer<typeof cardInfoModel>;
export const paymentDetailsPayloadModel = z.object({
method: z.enum([PaymentMethod.Card]),
cardDetails: cardInfoModel,
flightTicketInfoId: z.number().int(),
productId: z.number().int(),
orderId: z.number().int(),
});
export type PaymentDetailsPayload = z.infer<typeof paymentDetailsPayloadModel>;
export const paymentDetailsModel = cardInfoModel.merge(
z.object({
id: z.number().int(),
flightTicketInfoId: z.number().int(),
productId: z.number().int(),
orderId: z.number().int(),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
}),

View File

@@ -1,31 +0,0 @@
import { z } from "zod";
import { PackageType, PaymentMethod } from "./enums";
export * from "../../../passengerinfo/data/entities";
// Flight package selection models
export const packageSelectionModel = z.object({
packageType: z.enum([
PackageType.Basic,
PackageType.Flex,
PackageType.Premium,
]),
insurance: z.boolean().default(false),
});
export type PackageSelection = z.infer<typeof packageSelectionModel>;
// payment models
export const cardInfoModel = z.object({
nameOnCard: z.string().min(1).max(255),
number: z.string().max(20),
expiryDate: z.string().max(8),
cvv: z.string().max(6),
});
export type CardInfo = z.infer<typeof cardInfoModel>;
export const paymentInfoModel = z.object({
method: z.enum([PaymentMethod.Card]).default(PaymentMethod.Card),
cardInfo: cardInfoModel,
});
export type PaymentInfo = z.infer<typeof paymentInfoModel>;

View File

@@ -1,43 +0,0 @@
export enum CheckoutStep {
Setup = "SETUP",
Initial = "INITIAL",
Payment = "PAYMENT",
Verification = "VERIFICATION",
Confirmation = "CONFIRMATION",
Complete = "COMPLETE",
}
export const TicketType = {
OneWay: "ONEWAY",
Return: "RETURN",
};
export const CabinClass = {
Economy: "ECONOMY",
PremiumEconomy: "PREMIUM_ECONOMY",
Business: "BUSINESS",
FirstClass: "FIRST_CLASS",
};
export enum Gender {
Male = "male",
Female = "female",
Other = "other",
}
export enum PaymentMethod {
Card = "CARD",
GooglePay = "GOOGLE_PAY",
ApplePay = "APPLEPAY",
}
export enum PassengerType {
Adult = "adult",
Child = "child",
}
export enum PackageType {
Basic = "basic",
Flex = "flex",
Premium = "premium",
}

View File

@@ -1,178 +0,0 @@
import { z } from "zod";
import { CabinClass, TicketType } from "./enums";
export * from "./enums";
export const stationModel = z.object({
id: z.number(),
type: z.string(),
code: z.string(),
name: z.string(),
city: z.string(),
country: z.string(),
});
export type Station = z.infer<typeof stationModel>;
export const iteneraryStationModel = z.object({
station: stationModel,
localTime: z.string(),
utcTime: z.string(),
});
export type IteneraryStation = z.infer<typeof iteneraryStationModel>;
export const seatInfoModel = z.object({
availableSeats: z.number(),
seatClass: z.string(),
});
export type SeatInfo = z.infer<typeof seatInfoModel>;
export const flightPriceDetailsModel = z.object({
currency: z.string(),
basePrice: z.number(),
discountAmount: z.number(),
displayPrice: z.number(),
orderPrice: z.number().nullable().optional(),
appliedCoupon: z.string().nullish().optional(),
couponDescription: z.string().nullish().optional(),
});
export type FlightPriceDetails = z.infer<typeof flightPriceDetailsModel>;
export const airlineModel = z.object({
code: z.string(),
name: z.string(),
imageUrl: z.string().nullable().optional(),
});
export type Airline = z.infer<typeof airlineModel>;
export const flightIteneraryModel = z.object({
flightId: z.string(),
flightNumber: z.string(),
airline: airlineModel,
departure: iteneraryStationModel,
destination: iteneraryStationModel,
durationSeconds: z.number(),
seatInfo: seatInfoModel,
});
export type FlightItenerary = z.infer<typeof flightIteneraryModel>;
export const passengerCountModel = z.object({
adults: z.number().int().min(0),
children: z.number().int().min(0),
});
export type PassengerCount = z.infer<typeof passengerCountModel>;
export function countPassengers(model: PassengerCount) {
return model.adults + model.children;
}
export const bagDimensionsModel = z.object({
length: z.number(),
width: z.number(),
height: z.number(),
});
export type BagDimensions = z.infer<typeof bagDimensionsModel>;
export const bagDetailsModel = z.object({
price: z.number(),
weight: z.number(),
unit: z.string(),
dimensions: bagDimensionsModel,
});
export type BagDetails = z.infer<typeof bagDetailsModel>;
export const allBagDetailsModel = z.object({
personalBags: bagDetailsModel,
handBags: bagDetailsModel,
checkedBags: bagDetailsModel,
});
export type AllBagDetails = z.infer<typeof allBagDetailsModel>;
// INFO: If you are to array-ificate it, you can just modify the details
// key below so that the user's order thing is not disrupted
export const bagsInfoModel = z.object({
includedPersonalBags: z.number().default(1),
includedHandBags: z.number().default(0),
includedCheckedBags: z.number().default(0),
hasHandBagsSupport: z.boolean().default(true),
hasCheckedBagsSupport: z.boolean().default(true),
details: allBagDetailsModel,
});
export type BagsInfo = z.infer<typeof bagsInfoModel>;
export const flightTicketModel = z.object({
id: z.number().int(),
ticketId: z.string(),
// For lookup purposes, we need these on the top level
departure: z.string(),
arrival: z.string(),
departureDate: z.coerce.string(),
returnDate: z.coerce.string().default(""),
dates: z.array(z.string()),
flightType: z.enum([TicketType.OneWay, TicketType.Return]),
flightIteneraries: z.object({
outbound: z.array(flightIteneraryModel),
inbound: z.array(flightIteneraryModel),
}),
priceDetails: flightPriceDetailsModel,
refundable: z.boolean(),
passengerCounts: passengerCountModel,
cabinClass: z.string(),
bagsInfo: bagsInfoModel,
lastAvailable: z.object({ availableSeats: z.number() }),
shareId: z.string(),
checkoutUrl: z.string(),
isCache: z.boolean().nullish().optional(),
refOIds: z.array(z.coerce.number()).nullish().optional(),
createdAt: z.coerce.string(),
updatedAt: z.coerce.string(),
});
export type FlightTicket = z.infer<typeof flightTicketModel>;
export const limitedFlightTicketModel = flightTicketModel.pick({
id: true,
departure: true,
arrival: true,
departureDate: true,
returnDate: true,
flightType: true,
dates: true,
priceDetails: true,
passengerCounts: true,
cabinClass: true,
});
export type LimitedFlightTicket = z.infer<typeof limitedFlightTicketModel>;
// INFO: ticket search models
export const ticketSearchPayloadModel = z.object({
sessionId: z.string(),
ticketType: z.enum([TicketType.OneWay, TicketType.Return]),
cabinClass: z.enum([
CabinClass.Economy,
CabinClass.PremiumEconomy,
CabinClass.Business,
CabinClass.FirstClass,
]),
departure: z.string().min(3),
arrival: z.string().min(3),
passengerCounts: passengerCountModel,
departureDate: z.coerce.string().min(3),
returnDate: z.coerce.string(),
loadMore: z.boolean().default(false),
meta: z.record(z.string(), z.any()).optional(),
couponCode: z.string().optional(),
});
export type TicketSearchPayload = z.infer<typeof ticketSearchPayloadModel>;
export const ticketSearchDTO = z.object({
sessionId: z.string(),
ticketSearchPayload: ticketSearchPayloadModel,
providers: z.array(z.string()).optional(),
});
export type TicketSearchDTO = z.infer<typeof ticketSearchDTO>;