变更统计是 4 个已纳入 diff 的文件,共 137 行新增、40 行删除。核心内容是把 Prisma schema 从原本的 User/Post 扩展为医院、科室、医疗组、患者、工程师分配等模型,同时同步调整了用户创建 DTO 和 service 的入参映射,并新增了一份对应迁移、删除了一份旧迁移。

This commit is contained in:
EL 2026-03-12 17:33:11 +08:00
parent f22469d400
commit 3cd7a044ca
5 changed files with 287 additions and 39 deletions

View File

@ -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;

View File

@ -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;

View File

@ -13,18 +13,108 @@ datasource db {
provider = "postgresql" provider = "postgresql"
} }
enum UserRole {
SYSTEM_ADMIN
HOSPITAL_ADMIN
DIRECTOR
TEAM_LEAD
DOCTOR
ENGINEER
}
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 { model User {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
email String @unique email String @unique
name String? name String?
posts Post[] 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 Post { model Patient {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
title String name String
content String? hospitalId Int
published Boolean? @default(false) departmentId Int?
author User? @relation(fields: [authorId], references: [id]) medicalGroupId Int?
authorId 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])
} }

View File

@ -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 { export class CreateUserDto {
@IsEmail() @IsEmail()
@ -7,4 +8,27 @@ export class CreateUserDto {
@IsString() @IsString()
@IsOptional() @IsOptional()
name?: string; 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;
} }

View File

@ -20,7 +20,15 @@ export class UsersService {
} }
return this.prisma.user.create({ 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,
},
}); });
} }