diff --git a/src/lib/server/db/schema.ts b/src/lib/server/db/schema.ts index 0a8eca6..6717597 100644 --- a/src/lib/server/db/schema.ts +++ b/src/lib/server/db/schema.ts @@ -1044,6 +1044,99 @@ export const companyServiceAccounts = pgTable( ] ); +// ── Procedures & Checklists ──────────────────────────── + +export const procedureInstanceStatusEnum = pgEnum('procedure_instance_status', [ + 'in_progress', + 'completed', + 'cancelled' +]); + +export const procedureTemplates = pgTable( + 'procedure_templates', + { + id: uuid('id').primaryKey().defaultRandom(), + companyId: uuid('company_id') + .notNull() + .references(() => companies.id, { onDelete: 'cascade' }), + title: text('title').notNull(), + description: text('description'), + category: text('category'), + isPublished: boolean('is_published').notNull().default(false), + createdBy: text('created_by').references(() => users.id, { onDelete: 'set null' }), + deletedAt: timestamp('deleted_at', { withTimezone: true }), + createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), + updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow() + }, + (table) => [index('procedure_templates_company_idx').on(table.companyId)] +); + +export const procedureSteps = pgTable( + 'procedure_steps', + { + id: uuid('id').primaryKey().defaultRandom(), + templateId: uuid('template_id') + .notNull() + .references(() => procedureTemplates.id, { onDelete: 'cascade' }), + stepNumber: integer('step_number').notNull(), + title: text('title').notNull(), + description: text('description'), + assigneeRole: text('assignee_role'), + estimatedMinutes: integer('estimated_minutes'), + createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow() + }, + (table) => [ + uniqueIndex('procedure_steps_template_step_idx').on(table.templateId, table.stepNumber) + ] +); + +export const procedureInstances = pgTable( + 'procedure_instances', + { + id: uuid('id').primaryKey().defaultRandom(), + templateId: uuid('template_id') + .notNull() + .references(() => procedureTemplates.id, { onDelete: 'restrict' }), + companyId: uuid('company_id') + .notNull() + .references(() => companies.id, { onDelete: 'cascade' }), + title: text('title').notNull(), + status: procedureInstanceStatusEnum('status').notNull().default('in_progress'), + startedBy: text('started_by').references(() => users.id, { onDelete: 'set null' }), + completedAt: timestamp('completed_at', { withTimezone: true }), + cancelledAt: timestamp('cancelled_at', { withTimezone: true }), + notes: text('notes'), + createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), + updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow() + }, + (table) => [ + index('procedure_instances_company_status_idx').on(table.companyId, table.status) + ] +); + +export const procedureInstanceSteps = pgTable( + 'procedure_instance_steps', + { + id: uuid('id').primaryKey().defaultRandom(), + instanceId: uuid('instance_id') + .notNull() + .references(() => procedureInstances.id, { onDelete: 'cascade' }), + stepId: uuid('step_id') + .notNull() + .references(() => procedureSteps.id, { onDelete: 'restrict' }), + stepNumber: integer('step_number').notNull(), + title: text('title').notNull(), + description: text('description'), + isCompleted: boolean('is_completed').notNull().default(false), + completedBy: text('completed_by').references(() => users.id, { onDelete: 'set null' }), + completedAt: timestamp('completed_at', { withTimezone: true }), + notes: text('notes') + }, + (table) => [ + index('procedure_instance_steps_instance_idx').on(table.instanceId, table.stepNumber) + ] +); + export const companyAddresses = pgTable( 'company_addresses', { @@ -1147,7 +1240,14 @@ export const companyLogEventEnum = pgEnum('company_log_event', [ 'recurring_bill_posted', 'service_account_created', 'service_account_updated', - 'service_account_deleted' + 'service_account_deleted', + 'procedure_template_created', + 'procedure_template_updated', + 'procedure_template_deleted', + 'procedure_instance_started', + 'procedure_step_completed', + 'procedure_instance_completed', + 'procedure_instance_cancelled' ]); export const companyLog = pgTable(