feat(01-02): [BLOCKING] drizzle-kit push — schema live on Postgres
- Connected to postgresql://178.104.27.55:5432/clienthub - 10 tables created: clients, phases, tasks, deliverables, comments, payments, documents, notes, service_catalog, quote_items - UNIQUE constraint on clients.token active at DB level - All FK constraints and CASCADE rules applied - Verified via information_schema.tables query
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
import { relations } from "drizzle-orm/relations";
|
||||||
|
import { clients, notes, payments, phases, quoteItems, serviceCatalog, documents, tasks, deliverables } from "./schema";
|
||||||
|
|
||||||
|
export const notesRelations = relations(notes, ({one}) => ({
|
||||||
|
client: one(clients, {
|
||||||
|
fields: [notes.clientId],
|
||||||
|
references: [clients.id]
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const clientsRelations = relations(clients, ({many}) => ({
|
||||||
|
notes: many(notes),
|
||||||
|
payments: many(payments),
|
||||||
|
phases: many(phases),
|
||||||
|
quoteItems: many(quoteItems),
|
||||||
|
documents: many(documents),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const paymentsRelations = relations(payments, ({one}) => ({
|
||||||
|
client: one(clients, {
|
||||||
|
fields: [payments.clientId],
|
||||||
|
references: [clients.id]
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const phasesRelations = relations(phases, ({one, many}) => ({
|
||||||
|
client: one(clients, {
|
||||||
|
fields: [phases.clientId],
|
||||||
|
references: [clients.id]
|
||||||
|
}),
|
||||||
|
tasks: many(tasks),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const quoteItemsRelations = relations(quoteItems, ({one}) => ({
|
||||||
|
client: one(clients, {
|
||||||
|
fields: [quoteItems.clientId],
|
||||||
|
references: [clients.id]
|
||||||
|
}),
|
||||||
|
serviceCatalog: one(serviceCatalog, {
|
||||||
|
fields: [quoteItems.serviceId],
|
||||||
|
references: [serviceCatalog.id]
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const serviceCatalogRelations = relations(serviceCatalog, ({many}) => ({
|
||||||
|
quoteItems: many(quoteItems),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const documentsRelations = relations(documents, ({one}) => ({
|
||||||
|
client: one(clients, {
|
||||||
|
fields: [documents.clientId],
|
||||||
|
references: [clients.id]
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const tasksRelations = relations(tasks, ({one, many}) => ({
|
||||||
|
phase: one(phases, {
|
||||||
|
fields: [tasks.phaseId],
|
||||||
|
references: [phases.id]
|
||||||
|
}),
|
||||||
|
deliverables: many(deliverables),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const deliverablesRelations = relations(deliverables, ({one}) => ({
|
||||||
|
task: one(tasks, {
|
||||||
|
fields: [deliverables.taskId],
|
||||||
|
references: [tasks.id]
|
||||||
|
}),
|
||||||
|
}));
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
import { pgTable, foreignKey, text, timestamp, unique, numeric, integer, boolean } from "drizzle-orm/pg-core"
|
||||||
|
import { sql } from "drizzle-orm"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const notes = pgTable("notes", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
clientId: text("client_id").notNull(),
|
||||||
|
body: text().notNull(),
|
||||||
|
createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.clientId],
|
||||||
|
foreignColumns: [clients.id],
|
||||||
|
name: "notes_client_id_clients_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const comments = pgTable("comments", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
entityType: text("entity_type").notNull(),
|
||||||
|
entityId: text("entity_id").notNull(),
|
||||||
|
author: text().notNull(),
|
||||||
|
body: text().notNull(),
|
||||||
|
createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const clients = pgTable("clients", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
name: text().notNull(),
|
||||||
|
brandName: text("brand_name").notNull(),
|
||||||
|
brief: text().notNull(),
|
||||||
|
token: text().notNull(),
|
||||||
|
acceptedTotal: numeric("accepted_total", { precision: 10, scale: 2 }).default('0'),
|
||||||
|
createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
|
||||||
|
}, (table) => [
|
||||||
|
unique("clients_token_unique").on(table.token),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const payments = pgTable("payments", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
clientId: text("client_id").notNull(),
|
||||||
|
label: text().notNull(),
|
||||||
|
amount: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
status: text().default('da_saldare').notNull(),
|
||||||
|
paidAt: timestamp("paid_at", { withTimezone: true, mode: 'string' }),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.clientId],
|
||||||
|
foreignColumns: [clients.id],
|
||||||
|
name: "payments_client_id_clients_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const phases = pgTable("phases", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
clientId: text("client_id").notNull(),
|
||||||
|
title: text().notNull(),
|
||||||
|
sortOrder: integer("sort_order").default(0).notNull(),
|
||||||
|
status: text().default('upcoming').notNull(),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.clientId],
|
||||||
|
foreignColumns: [clients.id],
|
||||||
|
name: "phases_client_id_clients_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const quoteItems = pgTable("quote_items", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
clientId: text("client_id").notNull(),
|
||||||
|
serviceId: text("service_id").notNull(),
|
||||||
|
quantity: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
unitPrice: numeric("unit_price", { precision: 10, scale: 2 }).notNull(),
|
||||||
|
subtotal: numeric({ precision: 10, scale: 2 }).notNull(),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.clientId],
|
||||||
|
foreignColumns: [clients.id],
|
||||||
|
name: "quote_items_client_id_clients_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.serviceId],
|
||||||
|
foreignColumns: [serviceCatalog.id],
|
||||||
|
name: "quote_items_service_id_service_catalog_id_fk"
|
||||||
|
}).onDelete("restrict"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const serviceCatalog = pgTable("service_catalog", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
name: text().notNull(),
|
||||||
|
description: text(),
|
||||||
|
unitPrice: numeric("unit_price", { precision: 10, scale: 2 }).notNull(),
|
||||||
|
active: boolean().default(true).notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const documents = pgTable("documents", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
clientId: text("client_id").notNull(),
|
||||||
|
label: text().notNull(),
|
||||||
|
url: text().notNull(),
|
||||||
|
createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.clientId],
|
||||||
|
foreignColumns: [clients.id],
|
||||||
|
name: "documents_client_id_clients_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const tasks = pgTable("tasks", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
phaseId: text("phase_id").notNull(),
|
||||||
|
title: text().notNull(),
|
||||||
|
description: text(),
|
||||||
|
status: text().default('todo').notNull(),
|
||||||
|
sortOrder: integer("sort_order").default(0).notNull(),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.phaseId],
|
||||||
|
foreignColumns: [phases.id],
|
||||||
|
name: "tasks_phase_id_phases_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const deliverables = pgTable("deliverables", {
|
||||||
|
id: text().primaryKey().notNull(),
|
||||||
|
taskId: text("task_id").notNull(),
|
||||||
|
title: text().notNull(),
|
||||||
|
url: text(),
|
||||||
|
status: text().default('pending').notNull(),
|
||||||
|
approvedAt: timestamp("approved_at", { withTimezone: true, mode: 'string' }),
|
||||||
|
}, (table) => [
|
||||||
|
foreignKey({
|
||||||
|
columns: [table.taskId],
|
||||||
|
foreignColumns: [tasks.id],
|
||||||
|
name: "deliverables_task_id_tasks_id_fk"
|
||||||
|
}).onDelete("cascade"),
|
||||||
|
]);
|
||||||
Reference in New Issue
Block a user