feat: add client_addresses table for multi-address storage
Adds client_addresses table with cascade deletes, port scoping, primary address flag, and indexes. Updates clientsRelations and portsRelations, adds clientAddressesRelations. Generates migration 0000_narrow_longshot.sql. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,9 @@ import { ports } from './ports';
|
||||
export const clients = pgTable(
|
||||
'clients',
|
||||
{
|
||||
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
portId: text('port_id')
|
||||
.notNull()
|
||||
.references(() => ports.id),
|
||||
@@ -52,7 +54,9 @@ export const clients = pgTable(
|
||||
export const clientContacts = pgTable(
|
||||
'client_contacts',
|
||||
{
|
||||
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
clientId: text('client_id')
|
||||
.notNull()
|
||||
.references(() => clients.id, { onDelete: 'cascade' }),
|
||||
@@ -66,15 +70,21 @@ export const clientContacts = pgTable(
|
||||
},
|
||||
(table) => [
|
||||
index('idx_cc_client').on(table.clientId),
|
||||
index('idx_cc_email').on(table.channel, table.value).where(sql`${table.channel} = 'email'`),
|
||||
index('idx_cc_phone').on(table.channel, table.value).where(sql`${table.channel} = 'phone'`),
|
||||
index('idx_cc_email')
|
||||
.on(table.channel, table.value)
|
||||
.where(sql`${table.channel} = 'email'`),
|
||||
index('idx_cc_phone')
|
||||
.on(table.channel, table.value)
|
||||
.where(sql`${table.channel} = 'phone'`),
|
||||
],
|
||||
);
|
||||
|
||||
export const clientRelationships = pgTable(
|
||||
'client_relationships',
|
||||
{
|
||||
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
portId: text('port_id')
|
||||
.notNull()
|
||||
.references(() => ports.id),
|
||||
@@ -94,7 +104,9 @@ export const clientRelationships = pgTable(
|
||||
export const clientNotes = pgTable(
|
||||
'client_notes',
|
||||
{
|
||||
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
clientId: text('client_id')
|
||||
.notNull()
|
||||
.references(() => clients.id, { onDelete: 'cascade' }),
|
||||
@@ -122,7 +134,9 @@ export const clientTags = pgTable(
|
||||
export const clientMergeLog = pgTable(
|
||||
'client_merge_log',
|
||||
{
|
||||
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
portId: text('port_id')
|
||||
.notNull()
|
||||
.references(() => ports.id),
|
||||
@@ -137,6 +151,31 @@ export const clientMergeLog = pgTable(
|
||||
(table) => [index('idx_cml_port').on(table.portId)],
|
||||
);
|
||||
|
||||
export const clientAddresses = pgTable(
|
||||
'client_addresses',
|
||||
{
|
||||
id: text('id')
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
clientId: text('client_id')
|
||||
.notNull()
|
||||
.references(() => clients.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_ca_client').on(table.clientId), index('idx_ca_port').on(table.portId)],
|
||||
);
|
||||
|
||||
export type Client = typeof clients.$inferSelect;
|
||||
export type NewClient = typeof clients.$inferInsert;
|
||||
export type ClientContact = typeof clientContacts.$inferSelect;
|
||||
@@ -147,3 +186,5 @@ export type ClientNote = typeof clientNotes.$inferSelect;
|
||||
export type NewClientNote = typeof clientNotes.$inferInsert;
|
||||
export type ClientMergeLog = typeof clientMergeLog.$inferSelect;
|
||||
export type NewClientMergeLog = typeof clientMergeLog.$inferInsert;
|
||||
export type ClientAddress = typeof clientAddresses.$inferSelect;
|
||||
export type NewClientAddress = typeof clientAddresses.$inferInsert;
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
clientNotes,
|
||||
clientTags,
|
||||
clientMergeLog,
|
||||
clientAddresses,
|
||||
} from './clients';
|
||||
|
||||
// Interests
|
||||
@@ -100,6 +101,7 @@ export const portsRelations = relations(ports, ({ many }) => ({
|
||||
berthMaintenanceLogs: many(berthMaintenanceLog),
|
||||
clientMergeLogs: many(clientMergeLog),
|
||||
clientRelationships: many(clientRelationships),
|
||||
clientAddresses: many(clientAddresses),
|
||||
}));
|
||||
|
||||
// ─── Users ────────────────────────────────────────────────────────────────────
|
||||
@@ -156,6 +158,7 @@ export const clientsRelations = relations(clients, ({ one, many }) => ({
|
||||
waitingListEntries: many(berthWaitingList),
|
||||
scratchpadNotes: many(scratchpadNotes),
|
||||
formSubmissions: many(formSubmissions),
|
||||
addresses: many(clientAddresses),
|
||||
}));
|
||||
|
||||
export const clientContactsRelations = relations(clientContacts, ({ one }) => ({
|
||||
@@ -165,6 +168,17 @@ export const clientContactsRelations = relations(clientContacts, ({ one }) => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
export const clientAddressesRelations = relations(clientAddresses, ({ one }) => ({
|
||||
client: one(clients, {
|
||||
fields: [clientAddresses.clientId],
|
||||
references: [clients.id],
|
||||
}),
|
||||
port: one(ports, {
|
||||
fields: [clientAddresses.portId],
|
||||
references: [ports.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const clientRelationshipsRelations = relations(clientRelationships, ({ one }) => ({
|
||||
port: one(ports, {
|
||||
fields: [clientRelationships.portId],
|
||||
|
||||
Reference in New Issue
Block a user