feature: a minimal v1 backend implemented for treatments feature.
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "TreatmentStatus" AS ENUM ('DRAFT', 'COMPLETED');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "treatments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"patientId" TEXT NOT NULL,
|
||||
"appointmentId" TEXT,
|
||||
"providerUserId" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"status" "TreatmentStatus" NOT NULL DEFAULT 'DRAFT',
|
||||
"treatmentAt" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "treatments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "treatment_cases" (
|
||||
"id" TEXT NOT NULL,
|
||||
"treatmentId" TEXT NOT NULL,
|
||||
"clientKey" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL,
|
||||
"treatmentType" TEXT NOT NULL,
|
||||
"teeth" JSONB NOT NULL,
|
||||
"comment" TEXT,
|
||||
"sentAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "treatment_cases_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "treatment_case_attachments" (
|
||||
"id" TEXT NOT NULL,
|
||||
"caseId" TEXT,
|
||||
"appointmentId" TEXT,
|
||||
"caseClientKey" TEXT,
|
||||
"fileName" TEXT NOT NULL,
|
||||
"mimeType" TEXT NOT NULL,
|
||||
"sizeBytes" INTEGER NOT NULL,
|
||||
"storagePath" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "treatment_case_attachments_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "treatment_case_sends" (
|
||||
"id" TEXT NOT NULL,
|
||||
"caseId" TEXT NOT NULL,
|
||||
"organizationId" TEXT NOT NULL,
|
||||
"sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "treatment_case_sends_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- Migrate legacy patient_treatment_histories into treatments + single case per row
|
||||
INSERT INTO "treatments" (
|
||||
"id",
|
||||
"organizationId",
|
||||
"patientId",
|
||||
"appointmentId",
|
||||
"providerUserId",
|
||||
"title",
|
||||
"status",
|
||||
"treatmentAt",
|
||||
"createdAt",
|
||||
"updatedAt"
|
||||
)
|
||||
SELECT
|
||||
h."id",
|
||||
p."organizationId",
|
||||
h."patientId",
|
||||
NULL,
|
||||
o."ownerId",
|
||||
h."title",
|
||||
'COMPLETED'::"TreatmentStatus",
|
||||
h."treatmentAt",
|
||||
h."createdAt",
|
||||
h."updatedAt"
|
||||
FROM "patient_treatment_histories" h
|
||||
JOIN "patients" p ON p."id" = h."patientId"
|
||||
JOIN "organizations" o ON o."id" = p."organizationId";
|
||||
|
||||
INSERT INTO "treatment_cases" (
|
||||
"id",
|
||||
"treatmentId",
|
||||
"clientKey",
|
||||
"sortOrder",
|
||||
"treatmentType",
|
||||
"teeth",
|
||||
"comment",
|
||||
"sentAt"
|
||||
)
|
||||
SELECT
|
||||
h."id" || '-case',
|
||||
h."id",
|
||||
NULL,
|
||||
0,
|
||||
'visit',
|
||||
CASE
|
||||
WHEN h."tooth" IS NOT NULL AND btrim(h."tooth") <> '' THEN jsonb_build_array(h."tooth")
|
||||
ELSE '[]'::jsonb
|
||||
END,
|
||||
h."notes",
|
||||
NULL
|
||||
FROM "patient_treatment_histories" h;
|
||||
|
||||
-- Drop legacy table
|
||||
DROP TABLE "patient_treatment_histories";
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "treatments_appointmentId_key" ON "treatments"("appointmentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "treatments_patientId_treatmentAt_idx" ON "treatments"("patientId", "treatmentAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "treatments_organizationId_status_idx" ON "treatments"("organizationId", "status");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "treatment_cases_treatmentId_sortOrder_idx" ON "treatment_cases"("treatmentId", "sortOrder");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "treatment_case_attachments_appointmentId_caseClientKey_idx" ON "treatment_case_attachments"("appointmentId", "caseClientKey");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "treatment_case_attachments_caseId_idx" ON "treatment_case_attachments"("caseId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "treatment_case_sends_caseId_organizationId_key" ON "treatment_case_sends"("caseId", "organizationId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatments" ADD CONSTRAINT "treatments_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatments" ADD CONSTRAINT "treatments_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "patients"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatments" ADD CONSTRAINT "treatments_appointmentId_fkey" FOREIGN KEY ("appointmentId") REFERENCES "appointments"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatment_cases" ADD CONSTRAINT "treatment_cases_treatmentId_fkey" FOREIGN KEY ("treatmentId") REFERENCES "treatments"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatment_case_attachments" ADD CONSTRAINT "treatment_case_attachments_caseId_fkey" FOREIGN KEY ("caseId") REFERENCES "treatment_cases"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatment_case_sends" ADD CONSTRAINT "treatment_case_sends_caseId_fkey" FOREIGN KEY ("caseId") REFERENCES "treatment_cases"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "treatment_case_sends" ADD CONSTRAINT "treatment_case_sends_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -61,6 +61,8 @@ model Organization {
|
||||
sentOrganizationInvitations OrganizationInvitation[] @relation("OrganizationInvitationInviter")
|
||||
patients Patient[]
|
||||
appointments Appointment[]
|
||||
treatments Treatment[]
|
||||
caseSends TreatmentCaseSend[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -81,8 +83,8 @@ model Patient {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
treatments PatientTreatmentHistory[]
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
treatments Treatment[]
|
||||
appointments Appointment[]
|
||||
|
||||
@@index([organizationId, createdAt])
|
||||
@@ -90,24 +92,6 @@ model Patient {
|
||||
@@map("patients")
|
||||
}
|
||||
|
||||
model PatientTreatmentHistory {
|
||||
id String @id @default(uuid())
|
||||
patientId String
|
||||
title String
|
||||
status String
|
||||
treatmentAt DateTime
|
||||
tooth String?
|
||||
notes String?
|
||||
totalCost Float?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([patientId, treatmentAt])
|
||||
@@map("patient_treatment_histories")
|
||||
}
|
||||
|
||||
model Appointment {
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
@@ -119,6 +103,7 @@ model Appointment {
|
||||
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
treatment Treatment?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -128,6 +113,84 @@ model Appointment {
|
||||
@@map("appointments")
|
||||
}
|
||||
|
||||
enum TreatmentStatus {
|
||||
DRAFT
|
||||
COMPLETED
|
||||
}
|
||||
|
||||
model Treatment {
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
patientId String
|
||||
appointmentId String? @unique
|
||||
providerUserId String
|
||||
title String
|
||||
status TreatmentStatus @default(DRAFT)
|
||||
treatmentAt DateTime
|
||||
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
appointment Appointment? @relation(fields: [appointmentId], references: [id], onDelete: SetNull)
|
||||
cases TreatmentCase[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([patientId, treatmentAt])
|
||||
@@index([organizationId, status])
|
||||
@@map("treatments")
|
||||
}
|
||||
|
||||
model TreatmentCase {
|
||||
id String @id @default(uuid())
|
||||
treatmentId String
|
||||
clientKey String?
|
||||
sortOrder Int
|
||||
treatmentType String
|
||||
teeth Json
|
||||
comment String?
|
||||
sentAt DateTime?
|
||||
|
||||
treatment Treatment @relation(fields: [treatmentId], references: [id], onDelete: Cascade)
|
||||
attachments TreatmentCaseAttachment[]
|
||||
sends TreatmentCaseSend[]
|
||||
|
||||
@@index([treatmentId, sortOrder])
|
||||
@@map("treatment_cases")
|
||||
}
|
||||
|
||||
model TreatmentCaseAttachment {
|
||||
id String @id @default(uuid())
|
||||
caseId String?
|
||||
appointmentId String?
|
||||
caseClientKey String?
|
||||
fileName String
|
||||
mimeType String
|
||||
sizeBytes Int
|
||||
storagePath String
|
||||
|
||||
case TreatmentCase? @relation(fields: [caseId], references: [id], onDelete: Cascade)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([appointmentId, caseClientKey])
|
||||
@@index([caseId])
|
||||
@@map("treatment_case_attachments")
|
||||
}
|
||||
|
||||
model TreatmentCaseSend {
|
||||
id String @id @default(uuid())
|
||||
caseId String
|
||||
organizationId String
|
||||
sentAt DateTime @default(now())
|
||||
|
||||
case TreatmentCase @relation(fields: [caseId], references: [id], onDelete: Cascade)
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([caseId, organizationId])
|
||||
@@map("treatment_case_sends")
|
||||
}
|
||||
|
||||
model Plan {
|
||||
id String @id @default(uuid())
|
||||
name String @unique // "Solo", "Small", "Medium", "Large", "Enterprise"
|
||||
|
||||
Reference in New Issue
Block a user