Skip to content

Commit 155f8e2

Browse files
authored
Merge pull request #76 from fathima200/issue-26
Feat: Implemented Pathology and Diagnostic Services
2 parents bbe939c + 55d7eb6 commit 155f8e2

9 files changed

Lines changed: 1660 additions & 0 deletions
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, CreateDateColumn, UpdateDateColumn } from 'typeorm';
2+
import { Patient } from '../../patients/entities/patient.entity';
3+
import { Doctor } from '../../doctors/entities/doctor.entity';
4+
import { PathologyReport } from './pathology-report.entity';
5+
import { PathologyImage } from './pathology-image.entity';
6+
import { QualityAssurance } from './quality-assurance.entity';
7+
8+
export enum CaseStatus {
9+
RECEIVED = 'received',
10+
IN_PROGRESS = 'in_progress',
11+
REVIEWED = 'reviewed',
12+
COMPLETED = 'completed',
13+
ARCHIVED = 'archived'
14+
}
15+
16+
export enum CaseType {
17+
HISTOLOGY = 'histology',
18+
CYTOLOGY = 'cytology',
19+
MOLECULAR = 'molecular',
20+
GENETIC = 'genetic',
21+
IMMUNOHISTOCHEMISTRY = 'immunohistochemistry',
22+
FLOW_CYTOMETRY = 'flow_cytometry'
23+
}
24+
25+
export enum Priority {
26+
LOW = 'low',
27+
NORMAL = 'normal',
28+
HIGH = 'high',
29+
URGENT = 'urgent',
30+
STAT = 'stat'
31+
}
32+
33+
@Entity('pathology_cases')
34+
export class PathologyCase {
35+
@PrimaryGeneratedColumn('uuid')
36+
id: string;
37+
38+
@Column({ unique: true })
39+
caseNumber: string;
40+
41+
@Column({
42+
type: 'enum',
43+
enum: CaseType
44+
})
45+
caseType: CaseType;
46+
47+
@Column({
48+
type: 'enum',
49+
enum: CaseStatus,
50+
default: CaseStatus.RECEIVED
51+
})
52+
status: CaseStatus;
53+
54+
@Column({
55+
type: 'enum',
56+
enum: Priority,
57+
default: Priority.NORMAL
58+
})
59+
priority: Priority;
60+
61+
@Column('text')
62+
clinicalHistory: string;
63+
64+
@Column('text')
65+
specimenDescription: string;
66+
67+
@Column()
68+
collectionDate: Date;
69+
70+
@Column()
71+
receivedDate: Date;
72+
73+
@Column({ nullable: true })
74+
expectedCompletionDate: Date;
75+
76+
@Column({ nullable: true })
77+
completedDate: Date;
78+
79+
@Column('simple-json', { nullable: true })
80+
specimenDetails: {
81+
site: string;
82+
procedure: string;
83+
fixative: string;
84+
containerType: string;
85+
quantity: number;
86+
grossDescription: string;
87+
};
88+
89+
@Column('simple-json', { nullable: true })
90+
clinicalData: {
91+
symptoms: string[];
92+
previousDiagnosis: string;
93+
medications: string[];
94+
relevantHistory: string;
95+
};
96+
97+
@ManyToOne(() => Patient, patient => patient.pathologyCases)
98+
patient: Patient;
99+
100+
@ManyToOne(() => Doctor, doctor => doctor.requestedPathologyCases)
101+
requestingDoctor: Doctor;
102+
103+
@ManyToOne(() => Doctor, doctor => doctor.reviewedPathologyCases)
104+
pathologist: Doctor;
105+
106+
@OneToMany(() => PathologyReport, (report: PathologyReport) => report.pathologyCase)
107+
reports: PathologyReport[];
108+
109+
@OneToMany(() => PathologyImage, (image: PathologyImage) => image.pathologyCase)
110+
images: PathologyImage[];
111+
112+
@OneToMany(() => QualityAssurance, (qa: QualityAssurance) => qa.pathologyCase)
113+
qualityAssurances: QualityAssurance[];
114+
115+
@CreateDateColumn()
116+
createdAt: Date;
117+
118+
@UpdateDateColumn()
119+
updatedAt: Date;
120+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, CreateDateColumn, UpdateDateColumn } from 'typeorm';
3+
import { PathologyCase } from './pathology-case.entity';
4+
import { Doctor } from '../../doctors/entities/doctor.entity';
5+
6+
export enum ImageType {
7+
MICROSCOPIC = 'microscopic',
8+
MACROSCOPIC = 'macroscopic',
9+
GROSS = 'gross',
10+
FLUORESCENCE = 'fluorescence',
11+
ELECTRON_MICROSCOPY = 'electron_microscopy',
12+
WHOLE_SLIDE = 'whole_slide',
13+
IMMUNOFLUORESCENCE = 'immunofluorescence'
14+
}
15+
16+
export enum ImageFormat {
17+
JPEG = 'jpeg',
18+
PNG = 'png',
19+
TIFF = 'tiff',
20+
SVS = 'svs',
21+
NDPI = 'ndpi',
22+
CZI = 'czi',
23+
DICOM = 'dicom'
24+
}
25+
26+
export enum StainType {
27+
H_AND_E = 'h_and_e',
28+
PAS = 'pas',
29+
MASSON_TRICHROME = 'masson_trichrome',
30+
RETICULIN = 'reticulin',
31+
CONGO_RED = 'congo_red',
32+
GRAM = 'gram',
33+
AFB = 'afb',
34+
IMMUNOHISTOCHEMICAL = 'immunohistochemical',
35+
SPECIAL_STAIN = 'special_stain'
36+
}
37+
38+
@Entity('pathology_images')
39+
export class PathologyImage {
40+
@PrimaryGeneratedColumn('uuid')
41+
id: string;
42+
43+
@Column()
44+
filename: string;
45+
46+
@Column()
47+
originalFilename: string;
48+
49+
@Column()
50+
filePath: string;
51+
52+
@Column()
53+
fileSize: number;
54+
55+
@Column({
56+
type: 'enum',
57+
enum: ImageFormat
58+
})
59+
format: ImageFormat;
60+
61+
@Column({
62+
type: 'enum',
63+
enum: ImageType
64+
})
65+
imageType: ImageType;
66+
67+
@Column({
68+
type: 'enum',
69+
enum: StainType,
70+
nullable: true
71+
})
72+
stainType: StainType;
73+
74+
@Column('decimal', { precision: 10, scale: 2, nullable: true })
75+
magnification: number;
76+
77+
@Column({ nullable: true })
78+
slideNumber: string;
79+
80+
@Column({ nullable: true })
81+
blockNumber: string;
82+
83+
@Column('simple-json', { nullable: true })
84+
metadata: {
85+
width: number;
86+
height: number;
87+
resolution: string;
88+
colorDepth: number;
89+
compressionType: string;
90+
acquisitionDate: Date;
91+
scannerModel: string;
92+
objective: string;
93+
};
94+
95+
@Column('simple-json', { nullable: true })
96+
annotations: Array<{
97+
id: string;
98+
type: string;
99+
coordinates: number[];
100+
description: string;
101+
createdBy: string;
102+
createdAt: Date;
103+
}>;
104+
105+
@Column('text', { nullable: true })
106+
description: string;
107+
108+
@Column({ default: false })
109+
isKeyImage: boolean;
110+
111+
@Column({ default: false })
112+
isArchived: boolean;
113+
114+
@Column({ nullable: true })
115+
thumbnailPath: string;
116+
117+
@Column('simple-json', { nullable: true })
118+
qualityMetrics: {
119+
focusScore: number;
120+
brightnessLevel: number;
121+
contrastLevel: number;
122+
colorBalance: string;
123+
artifactPresence: boolean;
124+
};
125+
126+
@ManyToOne(() => PathologyCase, pathologyCase => pathologyCase.images)
127+
pathologyCase: PathologyCase;
128+
129+
@ManyToOne(() => Doctor, doctor => doctor.capturedImages)
130+
capturedBy: Doctor;
131+
132+
@CreateDateColumn()
133+
createdAt: Date;
134+
135+
@UpdateDateColumn()
136+
updatedAt: Date;
137+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, CreateDateColumn, UpdateDateColumn } from 'typeorm';
2+
import { PathologyCase } from './pathology-case.entity';
3+
import { Doctor } from '../../doctors/entities/doctor.entity';
4+
5+
export enum ReportStatus {
6+
DRAFT = 'draft',
7+
PRELIMINARY = 'preliminary',
8+
FINAL = 'final',
9+
AMENDED = 'amended',
10+
CORRECTED = 'corrected'
11+
}
12+
13+
export enum DiagnosisType {
14+
BENIGN = 'benign',
15+
MALIGNANT = 'malignant',
16+
SUSPICIOUS = 'suspicious',
17+
INFLAMMATORY = 'inflammatory',
18+
REACTIVE = 'reactive',
19+
NORMAL = 'normal',
20+
INADEQUATE = 'inadequate'
21+
}
22+
23+
@Entity('pathology_reports')
24+
export class PathologyReport {
25+
@PrimaryGeneratedColumn('uuid')
26+
id: string;
27+
28+
@Column({ unique: true })
29+
reportNumber: string;
30+
31+
@Column({
32+
type: 'enum',
33+
enum: ReportStatus,
34+
default: ReportStatus.DRAFT
35+
})
36+
status: ReportStatus;
37+
38+
@Column('text')
39+
macroscopicDescription: string;
40+
41+
@Column('text')
42+
microscopicDescription: string;
43+
44+
@Column('text')
45+
diagnosis: string;
46+
47+
@Column({
48+
type: 'enum',
49+
enum: DiagnosisType
50+
})
51+
diagnosisType: DiagnosisType;
52+
53+
@Column('text', { nullable: true })
54+
comments: string;
55+
56+
@Column('text', { nullable: true })
57+
recommendations: string;
58+
59+
@Column('simple-json', { nullable: true })
60+
immunohistochemistry: {
61+
markers: Array<{
62+
name: string;
63+
result: string;
64+
intensity: string;
65+
distribution: string;
66+
}>;
67+
interpretation: string;
68+
};
69+
70+
@Column('simple-json', { nullable: true })
71+
molecularFindings: {
72+
mutations: Array<{
73+
gene: string;
74+
variant: string;
75+
significance: string;
76+
}>;
77+
biomarkers: Array<{
78+
name: string;
79+
status: string;
80+
value: string;
81+
}>;
82+
};
83+
84+
@Column('simple-json', { nullable: true })
85+
stagingInformation: {
86+
tnmStaging: {
87+
t: string;
88+
n: string;
89+
m: string;
90+
stage: string;
91+
};
92+
gradingSystem: string;
93+
grade: string;
94+
};
95+
96+
@Column('simple-json', { nullable: true })
97+
specialStains: Array<{
98+
stainName: string;
99+
result: string;
100+
interpretation: string;
101+
}>;
102+
103+
@Column()
104+
reportDate: Date;
105+
106+
@Column({ nullable: true })
107+
verifiedDate: Date;
108+
109+
@Column({ default: false })
110+
isVerified: boolean;
111+
112+
@Column('text', { nullable: true })
113+
templateUsed: string;
114+
115+
@Column('simple-json', { nullable: true })
116+
additionalTesting: {
117+
flowCytometry: string;
118+
cytogenetics: string;
119+
molecularTesting: string;
120+
otherTests: string[];
121+
};
122+
123+
@ManyToOne(() => PathologyCase, pathologyCase => pathologyCase.reports)
124+
pathologyCase: PathologyCase;
125+
126+
@ManyToOne(() => Doctor, doctor => doctor.authoredReports)
127+
author: Doctor;
128+
129+
@ManyToOne(() => Doctor, doctor => doctor.verifiedReports)
130+
verifiedBy: Doctor;
131+
132+
@CreateDateColumn()
133+
createdAt: Date;
134+
135+
@UpdateDateColumn()
136+
updatedAt: Date;
137+
}

0 commit comments

Comments
 (0)