feat(companies): add companies, memberships, addresses, notes, tags schema
This commit is contained in:
143
src/lib/db/schema/companies.ts
Normal file
143
src/lib/db/schema/companies.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import {
|
||||
pgTable,
|
||||
text,
|
||||
timestamp,
|
||||
boolean,
|
||||
index,
|
||||
uniqueIndex,
|
||||
primaryKey,
|
||||
} from 'drizzle-orm/pg-core';
|
||||
import { sql } from 'drizzle-orm';
|
||||
import { ports } from './ports';
|
||||
import { clients } from './clients';
|
||||
|
||||
export const companies = pgTable(
|
||||
'companies',
|
||||
{
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
portId: text('port_id')
|
||||
.notNull()
|
||||
.references(() => ports.id),
|
||||
name: text('name').notNull(),
|
||||
legalName: text('legal_name'),
|
||||
taxId: text('tax_id'),
|
||||
registrationNumber: text('registration_number'),
|
||||
incorporationCountry: text('incorporation_country'),
|
||||
incorporationDate: timestamp('incorporation_date', { withTimezone: true, mode: 'date' }),
|
||||
status: text('status').notNull().default('active'), // 'active' | 'dissolved'
|
||||
billingEmail: text('billing_email'),
|
||||
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_companies_port').on(table.portId),
|
||||
uniqueIndex('idx_companies_name_unique').on(table.portId, sql`lower(${table.name})`),
|
||||
index('idx_companies_taxid')
|
||||
.on(table.portId, table.taxId)
|
||||
.where(sql`${table.taxId} IS NOT NULL`),
|
||||
],
|
||||
);
|
||||
|
||||
export const companyMemberships = pgTable(
|
||||
'company_memberships',
|
||||
{
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
companyId: text('company_id')
|
||||
.notNull()
|
||||
.references(() => companies.id, { onDelete: 'cascade' }),
|
||||
clientId: text('client_id')
|
||||
.notNull()
|
||||
.references(() => clients.id, { onDelete: 'cascade' }),
|
||||
role: text('role').notNull(), // director | officer | broker | representative | legal_counsel | employee | shareholder | other
|
||||
roleDetail: text('role_detail'),
|
||||
startDate: timestamp('start_date', { withTimezone: true, mode: 'date' }).notNull(),
|
||||
endDate: timestamp('end_date', { withTimezone: true, mode: 'date' }),
|
||||
isPrimary: boolean('is_primary').notNull().default(false),
|
||||
notes: text('notes'),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
},
|
||||
(table) => [
|
||||
index('idx_cm_company').on(table.companyId),
|
||||
index('idx_cm_client').on(table.clientId),
|
||||
index('idx_cm_active')
|
||||
.on(table.companyId, table.clientId)
|
||||
.where(sql`${table.endDate} IS NULL`),
|
||||
uniqueIndex('unique_cm_exact').on(table.companyId, table.clientId, table.role, table.startDate),
|
||||
],
|
||||
);
|
||||
|
||||
export const companyAddresses = pgTable(
|
||||
'company_addresses',
|
||||
{
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
companyId: text('company_id')
|
||||
.notNull()
|
||||
.references(() => companies.id, { onDelete: 'cascade' }),
|
||||
portId: text('port_id')
|
||||
.notNull()
|
||||
.references(() => ports.id, { onDelete: 'cascade' }),
|
||||
label: text('label').notNull().default('Primary'),
|
||||
streetAddress: text('street_address'),
|
||||
city: text('city'),
|
||||
stateProvince: text('state_province'),
|
||||
postalCode: text('postal_code'),
|
||||
country: text('country'),
|
||||
isPrimary: boolean('is_primary').notNull().default(true),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
},
|
||||
(table) => [
|
||||
index('idx_compa_company').on(table.companyId),
|
||||
index('idx_compa_port').on(table.portId),
|
||||
uniqueIndex('idx_compa_primary')
|
||||
.on(table.companyId)
|
||||
.where(sql`${table.isPrimary} = true`),
|
||||
],
|
||||
);
|
||||
|
||||
export const companyNotes = pgTable(
|
||||
'company_notes',
|
||||
{
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
companyId: text('company_id')
|
||||
.notNull()
|
||||
.references(() => companies.id, { onDelete: 'cascade' }),
|
||||
authorId: text('author_id').notNull(),
|
||||
content: text('content').notNull(),
|
||||
mentions: text('mentions').array(),
|
||||
isLocked: boolean('is_locked').notNull().default(false),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
},
|
||||
(table) => [index('idx_compn_company').on(table.companyId)],
|
||||
);
|
||||
|
||||
export const companyTags = pgTable(
|
||||
'company_tags',
|
||||
{
|
||||
companyId: text('company_id')
|
||||
.notNull()
|
||||
.references(() => companies.id, { onDelete: 'cascade' }),
|
||||
tagId: text('tag_id').notNull(),
|
||||
},
|
||||
(table) => [primaryKey({ columns: [table.companyId, table.tagId] })],
|
||||
);
|
||||
|
||||
export type Company = typeof companies.$inferSelect;
|
||||
export type NewCompany = typeof companies.$inferInsert;
|
||||
export type CompanyMembership = typeof companyMemberships.$inferSelect;
|
||||
export type NewCompanyMembership = typeof companyMemberships.$inferInsert;
|
||||
export type CompanyAddress = typeof companyAddresses.$inferSelect;
|
||||
export type NewCompanyAddress = typeof companyAddresses.$inferInsert;
|
||||
export type CompanyNote = typeof companyNotes.$inferSelect;
|
||||
export type NewCompanyNote = typeof companyNotes.$inferInsert;
|
||||
@@ -7,6 +7,9 @@ export * from './users';
|
||||
// Clients
|
||||
export * from './clients';
|
||||
|
||||
// Companies
|
||||
export * from './companies';
|
||||
|
||||
// Yachts
|
||||
export * from './yachts';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user