import { sql } from "drizzle-orm"; import { pgTable, text, varchar, integer, decimal, timestamp, boolean, uuid } from "drizzle-orm/pg-core"; import { relations } from "drizzle-orm"; import { createInsertSchema } from "drizzle-zod"; import { z } from "zod"; // Users table - customers only export const users = pgTable("users", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), username: varchar("username", { length: 100 }).notNull().unique(), email: varchar("email", { length: 255 }).notNull().unique(), password: text("password").notNull(), firstName: varchar("first_name", { length: 100 }).notNull(), lastName: varchar("last_name", { length: 100 }).notNull(), phone: varchar("phone", { length: 20 }).notNull(), street: text("street"), city: varchar("city", { length: 100 }), state: varchar("state", { length: 100 }), pinCode: varchar("pin_code", { length: 20 }), country: varchar("country", { length: 100 }), // Automatic location detection fields latitude: decimal("latitude", { precision: 10, scale: 8 }), longitude: decimal("longitude", { precision: 11, scale: 8 }), googleMapsUrl: text("google_maps_url"), locationDetectedAutomatically: boolean("location_detected_automatically").default(false), createdAt: timestamp("created_at").defaultNow(), }); // Sellers table - admin-created accounts export const sellers = pgTable("sellers", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), username: varchar("username", { length: 100 }).notNull().unique(), password: text("password").notNull(), plainTextPassword: text("plain_text_password"), // For admin access recovery createdAt: timestamp("created_at").defaultNow(), }); // Categories table - admin managed export const categories = pgTable("categories", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), name: varchar("name", { length: 100 }).notNull().unique(), icon: varchar("icon", { length: 50 }), imageUrl: varchar("image_url", { length: 500 }), createdAt: timestamp("created_at").defaultNow(), }); // Stores table - seller store information export const stores = pgTable("stores", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), sellerId: uuid("seller_id").references(() => sellers.id, { onDelete: "cascade" }).notNull(), name: varchar("name", { length: 200 }).notNull(), description: text("description"), bannerImage: text("banner_image"), faceImage: text("face_image"), createdAt: timestamp("created_at").defaultNow(), }); // Products table export const products = pgTable("products", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), sellerId: uuid("seller_id").references(() => sellers.id, { onDelete: "cascade" }).notNull(), categoryId: uuid("category_id").references(() => categories.id).notNull(), title: varchar("title", { length: 255 }).notNull(), description: text("description").notNull(), price: decimal("price", { precision: 10, scale: 2 }).notNull(), originalPrice: decimal("original_price", { precision: 10, scale: 2 }), stock: integer("stock").default(0), images: text("images").array(), isActive: boolean("is_active").default(true), createdAt: timestamp("created_at").defaultNow(), }); // Orders table export const orders = pgTable("orders", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), userId: uuid("user_id").references(() => users.id).notNull(), status: varchar("status", { length: 50 }).default("pending"), // pending, processing, shipped, delivered, cancelled paymentStatus: varchar("payment_status", { length: 50 }).default("unpaid"), // unpaid, paid subtotal: decimal("subtotal", { precision: 10, scale: 2 }).notNull(), tax: decimal("tax", { precision: 10, scale: 2 }).notNull(), shipping: decimal("shipping", { precision: 10, scale: 2 }).default("0.00"), total: decimal("total", { precision: 10, scale: 2 }).notNull(), shippingAddress: text("shipping_address").notNull(), paymentMethod: varchar("payment_method", { length: 50 }).default("cod").notNull(), // cod = Cash on Delivery, upi = UPI createdAt: timestamp("created_at").defaultNow(), }); // Order Items table export const orderItems = pgTable("order_items", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), orderId: uuid("order_id").references(() => orders.id, { onDelete: "cascade" }).notNull(), productId: uuid("product_id").references(() => products.id).notNull(), quantity: integer("quantity").notNull(), price: decimal("price", { precision: 10, scale: 2 }).notNull(), }); // Cart Items table export const cartItems = pgTable("cart_items", { id: uuid("id").primaryKey().default(sql`gen_random_uuid()`), userId: uuid("user_id").references(() => users.id, { onDelete: "cascade" }).notNull(), productId: uuid("product_id").references(() => products.id, { onDelete: "cascade" }).notNull(), quantity: integer("quantity").notNull().default(1), createdAt: timestamp("created_at").defaultNow(), }); // Relations export const usersRelations = relations(users, ({ many }) => ({ orders: many(orders), cartItems: many(cartItems), })); export const sellersRelations = relations(sellers, ({ one, many }) => ({ store: one(stores), products: many(products), })); export const storesRelations = relations(stores, ({ one }) => ({ seller: one(sellers, { fields: [stores.sellerId], references: [sellers.id], }), })); export const categoriesRelations = relations(categories, ({ many }) => ({ products: many(products), })); export const productsRelations = relations(products, ({ one, many }) => ({ seller: one(sellers, { fields: [products.sellerId], references: [sellers.id], }), category: one(categories, { fields: [products.categoryId], references: [categories.id], }), orderItems: many(orderItems), cartItems: many(cartItems), })); export const ordersRelations = relations(orders, ({ one, many }) => ({ user: one(users, { fields: [orders.userId], references: [users.id], }), orderItems: many(orderItems), })); export const orderItemsRelations = relations(orderItems, ({ one }) => ({ order: one(orders, { fields: [orderItems.orderId], references: [orders.id], }), product: one(products, { fields: [orderItems.productId], references: [products.id], }), })); export const cartItemsRelations = relations(cartItems, ({ one }) => ({ user: one(users, { fields: [cartItems.userId], references: [users.id], }), product: one(products, { fields: [cartItems.productId], references: [products.id], }), })); // Insert schemas export const insertUserSchema = createInsertSchema(users).omit({ id: true, createdAt: true, }).extend({ // Make manual address fields optional for automatic location detection street: z.string().optional(), city: z.string().optional(), state: z.string().optional(), pinCode: z.string().optional(), country: z.string().optional(), // Accept both numbers (from geolocation API) and strings (for database) latitude: z.union([z.number(), z.string()]).optional(), longitude: z.union([z.number(), z.string()]).optional(), }); export const insertSellerSchema = createInsertSchema(sellers).omit({ id: true, createdAt: true, }); export const insertCategorySchema = createInsertSchema(categories).omit({ id: true, createdAt: true, }); export const insertStoreSchema = createInsertSchema(stores).omit({ id: true, createdAt: true, }); export const insertProductSchema = createInsertSchema(products).omit({ id: true, createdAt: true, }); export const insertOrderSchema = createInsertSchema(orders).omit({ id: true, createdAt: true, }); export const insertOrderItemSchema = createInsertSchema(orderItems).omit({ id: true, }); export const insertCartItemSchema = createInsertSchema(cartItems).omit({ id: true, createdAt: true, }); // Types export type User = typeof users.$inferSelect; export type InsertUser = z.infer; export type Seller = typeof sellers.$inferSelect; export type InsertSeller = z.infer; export type Category = typeof categories.$inferSelect; export type InsertCategory = z.infer; export type Store = typeof stores.$inferSelect; export type InsertStore = z.infer; export type Product = typeof products.$inferSelect; export type InsertProduct = z.infer; export type Order = typeof orders.$inferSelect; export type InsertOrder = z.infer; export type OrderItem = typeof orderItems.$inferSelect; export type InsertOrderItem = z.infer; export type CartItem = typeof cartItems.$inferSelect; export type InsertCartItem = z.infer;