tia/src/db/schema/medical.ts
Mannu a3d3a140ed refactor(db/schema): align TypeScript schema with production
Path A baseline reconciliation. drizzle-kit pull against tia_prod showed
prod had drifted well past schema.ts because legacy hand-rolled migrations
0003-0015 wrote to the DB but were never reflected back into TypeScript.

Shared-table drift fixed:
- users:          + password_hash, + password_updated_at
- families:       + tier, + max_children, + max_members
- children:       col is 'stage' (kept JS key currentStage -> stage);
                  'image_url' not 'profile_photo_url'; birth_date is DATE;
                  sex nullable; dropped phantom stage_overrides
- family_members: dropped phantom display_name
- family_invites: dropped phantom display_name, accepted_at
- audit_log:      + resource_id, + resource_type; metadata -> jsonb; +5 indexes
- memories:       + vision_tags (text[]), + vision_embedding (vector 1536)
- logs.ts:        'diapers' phantom table renamed to diapersLogs ('diapers_logs')

19 missing tables added across new files:
- admin.ts:     admins, admin_sessions, password_resets
- support.ts:   support_tickets, support_responses
- ai.ts:        chat_sessions, chat_messages, ai_usage
- medical.ts:   medicines, medication_doses, allergies, illness_logs, doctor_visits
- affiliate.ts: member_profiles, recommended_products, product_clicks
- logs.ts:      + milestone_achievements
- audit.ts:     + log_corrections

BUG FIX: schema/index.ts never re-exported ./logs — Drizzle was blind to
feeds/sleeps/vaccinations/growth/medications. Now exported.

Verified: tsc --noEmit has zero non-test errors. Dropped phantom columns
confirmed to have zero references in src/.
2026-05-23 12:17:20 +05:30

89 lines
3.5 KiB
TypeScript

import {
pgTable,
text,
timestamp,
uuid,
varchar,
date,
index,
} from "drizzle-orm/pg-core";
// ---------------------------------------------------------------------------
// Medical schema — aligned to PRODUCTION as of 2026-05-19 baseline.
// Tables: medicines, medication_doses, allergies, illness_logs, doctor_visits
// (legacy migrations 0003_medical_data, 0012_medical_doses).
//
// Note: `medicines` here is the per-child medicine list with reminder times.
// `medications` (in logs.ts) is a separate prescription-record table that
// predates it. Both exist in prod; keep them distinct.
// ---------------------------------------------------------------------------
export const medicines = pgTable("medicines", {
id: uuid("id").primaryKey().defaultRandom(),
childId: uuid("child_id").notNull(),
name: varchar("name", { length: 255 }).notNull(),
dose: varchar("dose", { length: 255 }),
notes: text("notes"),
reminderTime: varchar("reminder_time", { length: 10 }),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});
// Append-only dose administration log. Corrections go via log_corrections.
export const medicationDoses = pgTable(
"medication_doses",
{
id: uuid("id").primaryKey().defaultRandom(),
medicineId: uuid("medicine_id").notNull(),
familyId: uuid("family_id").notNull(),
administeredAt: timestamp("administered_at", { withTimezone: true })
.defaultNow()
.notNull(),
administeredBy: uuid("administered_by"),
amountGiven: text("amount_given"),
notes: text("notes"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
},
(table) => [
index("medication_doses_family_idx").on(table.familyId),
index("medication_doses_medicine_idx").on(table.medicineId),
]
);
export const allergies = pgTable("allergies", {
id: uuid("id").primaryKey().defaultRandom(),
childId: uuid("child_id").notNull(),
name: varchar("name", { length: 255 }).notNull(),
severity: varchar("severity", { length: 50 }).default("mild"),
notes: text("notes"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});
export const illnessLogs = pgTable("illness_logs", {
id: uuid("id").primaryKey().defaultRandom(),
childId: uuid("child_id").notNull(),
name: varchar("name", { length: 255 }).notNull(),
startDate: date("start_date").notNull(),
endDate: date("end_date"),
notes: text("notes"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});
export const doctorVisits = pgTable("doctor_visits", {
id: uuid("id").primaryKey().defaultRandom(),
childId: uuid("child_id").notNull(),
doctorName: varchar("doctor_name", { length: 255 }).notNull(),
reason: varchar("reason", { length: 255 }),
visitDate: date("visit_date").notNull(),
notes: text("notes"),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow(),
});
export type Medicine = typeof medicines.$inferSelect;
export type MedicationDose = typeof medicationDoses.$inferSelect;
export type Allergy = typeof allergies.$inferSelect;
export type IllnessLog = typeof illnessLogs.$inferSelect;
export type DoctorVisit = typeof doctorVisits.$inferSelect;