90 lines
3.7 KiB
TypeScript
90 lines
3.7 KiB
TypeScript
|
|
import {
|
||
|
|
pgTable,
|
||
|
|
text,
|
||
|
|
boolean,
|
||
|
|
integer,
|
||
|
|
timestamp,
|
||
|
|
primaryKey,
|
||
|
|
index,
|
||
|
|
} from 'drizzle-orm/pg-core';
|
||
|
|
import { ports } from './ports';
|
||
|
|
import { clients } from './clients';
|
||
|
|
|
||
|
|
// Pipeline stages: open, details_sent, in_communication, visited, signed_eoi_nda, deposit_10pct, contract, completed
|
||
|
|
|
||
|
|
export const interests = pgTable(
|
||
|
|
'interests',
|
||
|
|
{
|
||
|
|
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||
|
|
portId: text('port_id')
|
||
|
|
.notNull()
|
||
|
|
.references(() => ports.id),
|
||
|
|
clientId: text('client_id')
|
||
|
|
.notNull()
|
||
|
|
.references(() => clients.id),
|
||
|
|
berthId: text('berth_id'), // nullable — FK to berths defined in berths.ts, added via relation
|
||
|
|
pipelineStage: text('pipeline_stage').notNull().default('open'),
|
||
|
|
leadCategory: text('lead_category'), // general_interest, specific_qualified, hot_lead
|
||
|
|
source: text('source'), // website, manual, referral, broker
|
||
|
|
eoiStatus: text('eoi_status'), // null, waiting_for_signatures, signed, expired
|
||
|
|
documensoId: text('documenso_id'),
|
||
|
|
contractStatus: text('contract_status'),
|
||
|
|
depositStatus: text('deposit_status'),
|
||
|
|
reservationStatus: text('reservation_status'),
|
||
|
|
dateFirstContact: timestamp('date_first_contact', { withTimezone: true }),
|
||
|
|
dateLastContact: timestamp('date_last_contact', { withTimezone: true }),
|
||
|
|
dateEoiSent: timestamp('date_eoi_sent', { withTimezone: true }),
|
||
|
|
dateEoiSigned: timestamp('date_eoi_signed', { withTimezone: true }),
|
||
|
|
dateContractSent: timestamp('date_contract_sent', { withTimezone: true }),
|
||
|
|
dateContractSigned: timestamp('date_contract_signed', { withTimezone: true }),
|
||
|
|
dateDepositReceived: timestamp('date_deposit_received', { withTimezone: true }),
|
||
|
|
reminderEnabled: boolean('reminder_enabled').notNull().default(false),
|
||
|
|
reminderDays: integer('reminder_days'),
|
||
|
|
reminderLastFired: timestamp('reminder_last_fired', { withTimezone: true }),
|
||
|
|
notes: text('notes'),
|
||
|
|
archivedAt: timestamp('archived_at', { withTimezone: true }),
|
||
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||
|
|
},
|
||
|
|
(table) => [
|
||
|
|
index('idx_interests_port').on(table.portId),
|
||
|
|
index('idx_interests_client').on(table.clientId),
|
||
|
|
index('idx_interests_berth').on(table.berthId),
|
||
|
|
index('idx_interests_stage').on(table.portId, table.pipelineStage),
|
||
|
|
index('idx_interests_archived').on(table.portId, table.archivedAt),
|
||
|
|
],
|
||
|
|
);
|
||
|
|
|
||
|
|
export const interestNotes = pgTable(
|
||
|
|
'interest_notes',
|
||
|
|
{
|
||
|
|
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||
|
|
interestId: text('interest_id')
|
||
|
|
.notNull()
|
||
|
|
.references(() => interests.id, { onDelete: 'cascade' }),
|
||
|
|
authorId: text('author_id').notNull(), // user ID
|
||
|
|
content: text('content').notNull(),
|
||
|
|
mentions: text('mentions').array(), // array of mentioned user IDs
|
||
|
|
isLocked: boolean('is_locked').notNull().default(false),
|
||
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||
|
|
},
|
||
|
|
(table) => [index('idx_in_interest').on(table.interestId)],
|
||
|
|
);
|
||
|
|
|
||
|
|
export const interestTags = pgTable(
|
||
|
|
'interest_tags',
|
||
|
|
{
|
||
|
|
interestId: text('interest_id')
|
||
|
|
.notNull()
|
||
|
|
.references(() => interests.id, { onDelete: 'cascade' }),
|
||
|
|
tagId: text('tag_id').notNull(), // references tags.id
|
||
|
|
},
|
||
|
|
(table) => [primaryKey({ columns: [table.interestId, table.tagId] })],
|
||
|
|
);
|
||
|
|
|
||
|
|
export type Interest = typeof interests.$inferSelect;
|
||
|
|
export type NewInterest = typeof interests.$inferInsert;
|
||
|
|
export type InterestNote = typeof interestNotes.$inferSelect;
|
||
|
|
export type NewInterestNote = typeof interestNotes.$inferInsert;
|