import { sql } from 'drizzle-orm' import { boolean, integer, pgTable, serial, text, timestamp, unique } from 'drizzle-orm/pg-core' export const restaurantTables = pgTable('restaurant_tables', { id: serial('id').primaryKey(), name: text('name').notNull(), seats: integer('seats').notNull(), }) export const reservations = pgTable( 'reservations', { id: serial('id').primaryKey(), tableId: integer('table_id') .notNull() .references(() => restaurantTables.id, { onDelete: 'cascade' }), customerName: text('customer_name').notNull(), customerEmail: text('customer_email').notNull(), partySize: integer('party_size').notNull(), reservationTime: timestamp('reservation_time', { withTimezone: true }).notNull(), // Captured from the reservation-duration setting at booking time, so a later // change to that setting doesn't retroactively change how long past bookings // are considered to occupy their table. durationMinutes: integer('duration_minutes').notNull().default(90), cancelToken: text('cancel_token') .notNull() .unique() .default(sql`gen_random_uuid()`), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }, (table) => [unique().on(table.tableId, table.reservationTime)], ) // Single-row table of restaurant-wide booking rules, editable by admins. export const restaurantSettings = pgTable('restaurant_settings', { id: serial('id').primaryKey(), reservationIntervalMinutes: integer('reservation_interval_minutes').notNull().default(15), reservationDurationMinutes: integer('reservation_duration_minutes').notNull().default(90), minLeadTimeMinutes: integer('min_lead_time_minutes').notNull().default(60), maxLeadTimeDays: integer('max_lead_time_days').notNull().default(60), }) // Better Auth's standard schema (staff accounts) — see https://www.better-auth.com/docs/concepts/database // `role`/`banned`/`banReason`/`banExpires` and `session.impersonatedBy` are added by the `admin` plugin. export const user = pgTable('user', { id: text('id').primaryKey(), name: text('name').notNull(), email: text('email').notNull().unique(), emailVerified: boolean('email_verified').notNull(), image: text('image'), createdAt: timestamp('created_at').notNull(), updatedAt: timestamp('updated_at').notNull(), role: text('role'), banned: boolean('banned'), banReason: text('ban_reason'), banExpires: timestamp('ban_expires'), }) export const session = pgTable('session', { id: text('id').primaryKey(), expiresAt: timestamp('expires_at').notNull(), token: text('token').notNull().unique(), createdAt: timestamp('created_at').notNull(), updatedAt: timestamp('updated_at').notNull(), ipAddress: text('ip_address'), userAgent: text('user_agent'), userId: text('user_id') .notNull() .references(() => user.id, { onDelete: 'cascade' }), impersonatedBy: text('impersonated_by'), }) export const account = pgTable('account', { id: text('id').primaryKey(), accountId: text('account_id').notNull(), providerId: text('provider_id').notNull(), userId: text('user_id') .notNull() .references(() => user.id, { onDelete: 'cascade' }), accessToken: text('access_token'), refreshToken: text('refresh_token'), idToken: text('id_token'), accessTokenExpiresAt: timestamp('access_token_expires_at'), refreshTokenExpiresAt: timestamp('refresh_token_expires_at'), scope: text('scope'), password: text('password'), createdAt: timestamp('created_at').notNull(), updatedAt: timestamp('updated_at').notNull(), }) export const verification = pgTable('verification', { id: text('id').primaryKey(), identifier: text('identifier').notNull(), value: text('value').notNull(), expiresAt: timestamp('expires_at').notNull(), createdAt: timestamp('created_at'), updatedAt: timestamp('updated_at'), }) export type RestaurantTable = typeof restaurantTables.$inferSelect export type Reservation = typeof reservations.$inferSelect export type NewReservation = typeof reservations.$inferInsert export type RestaurantSettings = typeof restaurantSettings.$inferSelect