Files
2025-10-21 16:40:46 +03:00

166 lines
5.5 KiB
TypeScript

import { relations } from "drizzle-orm";
import {
boolean,
decimal,
integer,
json,
pgTable,
serial,
text,
timestamp,
varchar,
} from "drizzle-orm/pg-core";
import { user } from "./auth.out";
export * from "./auth.out";
export const order = pgTable("order", {
id: serial("id").primaryKey(),
uid: varchar("uid", { length: 32 }).notNull(),
orderPrice: decimal("order_price", {
precision: 12,
scale: 2,
}).$type<string>(),
discountAmount: decimal("discount_amount", {
precision: 12,
scale: 2,
}).$type<string>(),
displayPrice: decimal("display_price", {
precision: 12,
scale: 2,
}).$type<string>(),
basePrice: decimal("base_price", { precision: 12, scale: 2 }).$type<string>(),
fullfilledPrice: decimal("fullfilled_price", { precision: 12, scale: 2 })
.$type<string>()
.default("0"),
status: varchar("status", { length: 24 }),
productId: integer("product_id").references(() => product.id, {
onDelete: "cascade",
}),
customerInfoId: integer("customer_info_id").references(
() => customerInfo.id,
{ onDelete: "cascade" },
),
paymentInfoId: integer("payment_info_id").references(() => paymentInfo.id, {
onDelete: "cascade",
}),
agentId: text("agent_id").references(() => user.id, { onDelete: "set null" }),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const product = pgTable("product", {
id: serial("id").primaryKey(),
linkId: varchar("link_id", { length: 32 }).notNull().unique(),
title: varchar("title", { length: 64 }).notNull(),
description: text("description").notNull(),
longDescription: text("long_description").notNull(),
price: decimal("price", { precision: 12, scale: 2 })
.$type<string>()
.default("0"),
discountPrice: decimal("discount_price", { precision: 12, scale: 2 })
.$type<string>()
.default("0"),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const customerInfo = pgTable("customer_info", {
id: serial("id").primaryKey(),
firstName: varchar("first_name", { length: 64 }).notNull(),
middleName: varchar("middle_name", { length: 64 }).default(""),
lastName: varchar("last_name", { length: 64 }).notNull(),
email: varchar("email", { length: 128 }).notNull(),
phoneCountryCode: varchar("phone_country_code", { length: 6 }).notNull(),
phoneNumber: varchar("phone_number", { length: 20 }).notNull(),
country: varchar("country", { length: 128 }).notNull(),
state: varchar("state", { length: 128 }).notNull(),
city: varchar("city", { length: 128 }).notNull(),
zipCode: varchar("zip_code", { length: 21 }).notNull(),
address: text("address").notNull(),
address2: text("address2"),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
export const paymentInfo = pgTable("payment_info", {
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(),
// 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(),
});
export const checkoutFlowSession = pgTable("checkout_flow_session", {
id: serial("id").primaryKey(),
flowId: text("flow_id").unique().notNull(),
domain: text("domain").notNull(),
checkoutStep: varchar("checkout_step", { length: 50 }).notNull(),
showVerification: boolean("show_verification").default(false).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
lastPinged: timestamp("last_pinged").notNull(),
isActive: boolean("is_active").default(true).notNull(),
lastSyncedAt: timestamp("last_synced_at").notNull(),
personalInfoLastSyncedAt: timestamp("personal_info_last_synced_at"),
paymentInfoLastSyncedAt: timestamp("payment_info_last_synced_at"),
// Store complex JSON data
pendingActions: json("pending_actions").default([]).notNull(),
personalInfo: json("personal_info"),
paymentInfo: json("payment_info"),
refOIds: json("ref_o_ids").$type<number[]>().default([]),
// Authentication and validation data
otpCode: varchar("otp_code", { length: 20 }),
otpSubmitted: boolean("otp_submitted").default(false).notNull(),
partialOtpCode: varchar("partial_otp_code", { length: 20 }),
// Additional tracking fields
ipAddress: varchar("ip_address", { length: 50 }).default("").notNull(),
userAgent: text("user_agent").default("").notNull(),
reserved: boolean("reserved").default(false).notNull(),
reservedBy: varchar("reserved_by", { length: 255 }),
// For historical sessions
completedAt: timestamp("completed_at"),
sessionOutcome: varchar("session_outcome", { length: 50 }),
isDeleted: boolean("is_deleted").default(false).notNull(),
product: integer("product_id").references(() => product.id, {
onDelete: "set null",
}),
});
export const customerInfoRelations = relations(customerInfo, ({}) => ({}));
export const orderRelations = relations(order, ({ one }) => ({
product: one(product, {
fields: [order.productId],
references: [product.id],
}),
customerInfo: one(customerInfo, {
fields: [order.customerInfoId],
references: [customerInfo.id],
}),
paymentInfo: one(paymentInfo, {
fields: [order.paymentInfoId],
references: [paymentInfo.id],
}),
}));