diff --git a/prisma/migrations/20260312073029_init/migration.sql b/prisma/migrations/20260312073029_init/migration.sql deleted file mode 100644 index 72c87ae..0000000 --- a/prisma/migrations/20260312073029_init/migration.sql +++ /dev/null @@ -1,25 +0,0 @@ --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "email" TEXT NOT NULL, - "name" TEXT, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Post" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "content" TEXT, - "published" BOOLEAN DEFAULT false, - "authorId" INTEGER, - - CONSTRAINT "Post_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); - --- AddForeignKey -ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20260312092840/migration.sql b/prisma/migrations/20260312092840/migration.sql new file mode 100644 index 0000000..e6846bd --- /dev/null +++ b/prisma/migrations/20260312092840/migration.sql @@ -0,0 +1,151 @@ +-- CreateEnum +CREATE TYPE "UserRole" AS ENUM ('SYSTEM_ADMIN', 'HOSPITAL_ADMIN', 'DIRECTOR', 'TEAM_LEAD', 'DOCTOR', 'ENGINEER'); + +-- CreateTable +CREATE TABLE "Hospital" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "code" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Hospital_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Department" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "hospitalId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Department_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MedicalGroup" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "departmentId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "MedicalGroup_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "User" ( + "id" SERIAL NOT NULL, + "email" TEXT NOT NULL, + "name" TEXT, + "role" "UserRole" NOT NULL DEFAULT 'DOCTOR', + "hospitalId" INTEGER, + "departmentId" INTEGER, + "medicalGroupId" INTEGER, + "managerId" INTEGER, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Patient" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "hospitalId" INTEGER NOT NULL, + "departmentId" INTEGER, + "medicalGroupId" INTEGER, + "doctorId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Patient_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "EngineerHospitalAssignment" ( + "id" SERIAL NOT NULL, + "hospitalId" INTEGER NOT NULL, + "engineerId" INTEGER NOT NULL, + "assignedById" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "EngineerHospitalAssignment_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Hospital_code_key" ON "Hospital"("code"); + +-- CreateIndex +CREATE UNIQUE INDEX "Department_hospitalId_name_key" ON "Department"("hospitalId", "name"); + +-- CreateIndex +CREATE UNIQUE INDEX "MedicalGroup_departmentId_name_key" ON "MedicalGroup"("departmentId", "name"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE INDEX "User_role_idx" ON "User"("role"); + +-- CreateIndex +CREATE INDEX "User_hospitalId_idx" ON "User"("hospitalId"); + +-- CreateIndex +CREATE INDEX "User_managerId_idx" ON "User"("managerId"); + +-- CreateIndex +CREATE INDEX "Patient_doctorId_idx" ON "Patient"("doctorId"); + +-- CreateIndex +CREATE INDEX "Patient_hospitalId_idx" ON "Patient"("hospitalId"); + +-- CreateIndex +CREATE INDEX "EngineerHospitalAssignment_engineerId_idx" ON "EngineerHospitalAssignment"("engineerId"); + +-- CreateIndex +CREATE INDEX "EngineerHospitalAssignment_assignedById_idx" ON "EngineerHospitalAssignment"("assignedById"); + +-- CreateIndex +CREATE UNIQUE INDEX "EngineerHospitalAssignment_hospitalId_engineerId_key" ON "EngineerHospitalAssignment"("hospitalId", "engineerId"); + +-- AddForeignKey +ALTER TABLE "Department" ADD CONSTRAINT "Department_hospitalId_fkey" FOREIGN KEY ("hospitalId") REFERENCES "Hospital"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MedicalGroup" ADD CONSTRAINT "MedicalGroup_departmentId_fkey" FOREIGN KEY ("departmentId") REFERENCES "Department"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_hospitalId_fkey" FOREIGN KEY ("hospitalId") REFERENCES "Hospital"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_departmentId_fkey" FOREIGN KEY ("departmentId") REFERENCES "Department"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_medicalGroupId_fkey" FOREIGN KEY ("medicalGroupId") REFERENCES "MedicalGroup"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "User" ADD CONSTRAINT "User_managerId_fkey" FOREIGN KEY ("managerId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Patient" ADD CONSTRAINT "Patient_hospitalId_fkey" FOREIGN KEY ("hospitalId") REFERENCES "Hospital"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Patient" ADD CONSTRAINT "Patient_departmentId_fkey" FOREIGN KEY ("departmentId") REFERENCES "Department"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Patient" ADD CONSTRAINT "Patient_medicalGroupId_fkey" FOREIGN KEY ("medicalGroupId") REFERENCES "MedicalGroup"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Patient" ADD CONSTRAINT "Patient_doctorId_fkey" FOREIGN KEY ("doctorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EngineerHospitalAssignment" ADD CONSTRAINT "EngineerHospitalAssignment_hospitalId_fkey" FOREIGN KEY ("hospitalId") REFERENCES "Hospital"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EngineerHospitalAssignment" ADD CONSTRAINT "EngineerHospitalAssignment_engineerId_fkey" FOREIGN KEY ("engineerId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EngineerHospitalAssignment" ADD CONSTRAINT "EngineerHospitalAssignment_assignedById_fkey" FOREIGN KEY ("assignedById") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 178b772..a16dada 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -13,18 +13,108 @@ datasource db { provider = "postgresql" } -model User { - id Int @id @default(autoincrement()) - email String @unique - name String? - posts Post[] +enum UserRole { + SYSTEM_ADMIN + HOSPITAL_ADMIN + DIRECTOR + TEAM_LEAD + DOCTOR + ENGINEER } -model Post { - id Int @id @default(autoincrement()) - title String - content String? - published Boolean? @default(false) - author User? @relation(fields: [authorId], references: [id]) - authorId Int? +model Hospital { + id Int @id @default(autoincrement()) + name String + code String @unique + departments Department[] + users User[] + patients Patient[] + engineerAssignments EngineerHospitalAssignment[] + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt +} + +model Department { + id Int @id @default(autoincrement()) + name String + hospitalId Int + hospital Hospital @relation(fields: [hospitalId], references: [id], onDelete: Cascade) + medicalGroups MedicalGroup[] + users User[] + patients Patient[] + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + @@unique([hospitalId, name]) +} + +model MedicalGroup { + id Int @id @default(autoincrement()) + name String + departmentId Int + department Department @relation(fields: [departmentId], references: [id], onDelete: Cascade) + users User[] + patients Patient[] + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + @@unique([departmentId, name]) +} + +model User { + id Int @id @default(autoincrement()) + email String @unique + name String? + role UserRole @default(DOCTOR) + hospitalId Int? + departmentId Int? + medicalGroupId Int? + managerId Int? + hospital Hospital? @relation(fields: [hospitalId], references: [id], onDelete: SetNull) + department Department? @relation(fields: [departmentId], references: [id], onDelete: SetNull) + medicalGroup MedicalGroup? @relation(fields: [medicalGroupId], references: [id], onDelete: SetNull) + manager User? @relation("UserHierarchy", fields: [managerId], references: [id], onDelete: SetNull) + subordinates User[] @relation("UserHierarchy") + patients Patient[] @relation("DoctorPatients") + engineerAssignments EngineerHospitalAssignment[] @relation("EngineerAssignments") + assignedEngineerHospitals EngineerHospitalAssignment[] @relation("SystemAdminAssignments") + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + @@index([role]) + @@index([hospitalId]) + @@index([managerId]) +} + +model Patient { + id Int @id @default(autoincrement()) + name String + hospitalId Int + departmentId Int? + medicalGroupId Int? + doctorId Int + hospital Hospital @relation(fields: [hospitalId], references: [id], onDelete: Restrict) + department Department? @relation(fields: [departmentId], references: [id], onDelete: SetNull) + medicalGroup MedicalGroup? @relation(fields: [medicalGroupId], references: [id], onDelete: SetNull) + doctor User @relation("DoctorPatients", fields: [doctorId], references: [id], onDelete: Restrict) + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + @@index([doctorId]) + @@index([hospitalId]) +} + +model EngineerHospitalAssignment { + id Int @id @default(autoincrement()) + hospitalId Int + engineerId Int + assignedById Int + hospital Hospital @relation(fields: [hospitalId], references: [id], onDelete: Cascade) + engineer User @relation("EngineerAssignments", fields: [engineerId], references: [id], onDelete: Restrict) + assignedBy User @relation("SystemAdminAssignments", fields: [assignedById], references: [id], onDelete: Restrict) + createdAt DateTime @default(now()) + + @@unique([hospitalId, engineerId]) + @@index([engineerId]) + @@index([assignedById]) } diff --git a/src/users/dto/create-user.dto.ts b/src/users/dto/create-user.dto.ts index 0e19f8e..6ae1277 100644 --- a/src/users/dto/create-user.dto.ts +++ b/src/users/dto/create-user.dto.ts @@ -1,4 +1,5 @@ -import { IsEmail, IsOptional, IsString } from 'class-validator'; +import { UserRole } from '../../generated/prisma/enums.js'; +import { IsEmail, IsEnum, IsInt, IsOptional, IsString, Min } from 'class-validator'; export class CreateUserDto { @IsEmail() @@ -7,4 +8,27 @@ export class CreateUserDto { @IsString() @IsOptional() name?: string; + + @IsEnum(UserRole) + role: UserRole; + + @IsInt() + @Min(1) + @IsOptional() + hospitalId?: number; + + @IsInt() + @Min(1) + @IsOptional() + departmentId?: number; + + @IsInt() + @Min(1) + @IsOptional() + medicalGroupId?: number; + + @IsInt() + @Min(1) + @IsOptional() + managerId?: number; } diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 4425c04..8b0e751 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -20,7 +20,15 @@ export class UsersService { } return this.prisma.user.create({ - data: createUserDto, + data: { + email: createUserDto.email, + name: createUserDto.name, + role: createUserDto.role, + hospitalId: createUserDto.hospitalId, + departmentId: createUserDto.departmentId, + medicalGroupId: createUserDto.medicalGroupId, + managerId: createUserDto.managerId, + }, }); }