shankar 8630a3e2c5 Fixed React backend startup issue.
Updated SQL script to correct procedure and column sizes.
Moved SQL scripts to the project root folder (outside React frontend).
Resolved backend container dependency issue to ensure MySQL is up before starting React backend.
Moved common values to .env file in the project root.
Updated React backend and MySQL ports to use default values.
Added code to get last study received, containers status and updated into DB.
2024-11-22 13:44:03 +05:30

272 lines
8.7 KiB
TypeScript

// src/repositories/DicomStudyRepository.ts
import { DicomStudy, CreateDicomStudyDTO, UpdateDicomStudyDTO, DBDicomStudy, DicomStudySearchParams } from '../types/dicom';
import pool from '../config/db';
import logger from '../utils/logger';
import { Pool } from 'mysql2/promise';
import { RowDataPacket, ResultSetHeader } from 'mysql2';
export class DicomStudyRepository {
constructor(private pool: Pool) {} // Modified constructor
private async getRouterStringId(numericId: number): Promise<string> {
try {
const [result] = await pool.query(
'SELECT router_id FROM routers WHERE id = ?',
[numericId]
);
const rows = result as any[];
if (rows.length === 0) {
throw new Error(`Router not found with id: ${numericId}`);
}
return rows[0].router_id;
} catch (error) {
logger.error('Error getting router string ID:', error);
throw error;
}
}
private async getRouterNumericId(routerId: string): Promise<number> {
try {
const [result] = await pool.query(
'SELECT id FROM routers WHERE router_id = ?',
[routerId]
);
const rows = result as any[];
if (rows.length === 0) {
throw new Error(`Router not found with router_id: ${routerId}`);
}
return rows[0].id;
} catch (error) {
logger.error('Error getting router numeric ID:', error);
throw error;
}
}
private async mapDBStudyToDicomStudy(dbStudy: DBDicomStudy): Promise<DicomStudy> {
return {
id: dbStudy.id,
router_id: dbStudy.router_id.toString(),
study_instance_uid: dbStudy.study_instance_uid,
patient_id: dbStudy.patient_id,
patient_name: dbStudy.patient_name,
accession_number: dbStudy.accession_number,
study_date: dbStudy.study_date,
modality: dbStudy.modality,
study_description: dbStudy.study_description,
series_instance_uid: dbStudy.series_instance_uid,
procedure_code: dbStudy.procedure_code,
referring_physician_name: dbStudy.referring_physician_name,
study_status_code: dbStudy.study_status_code,
association_id: dbStudy.association_id,
created_at: dbStudy.created_at,
updated_at: dbStudy.updated_at
};
}
async create(studyData: CreateDicomStudyDTO): Promise<DicomStudy> {
try {
const [result] = await pool.query(
`INSERT INTO dicom_study_overview (
router_id, study_instance_uid, patient_id, patient_name,
accession_number, study_date, modality, study_description,
series_instance_uid, procedure_code, referring_physician_name,
study_status_code, association_id, created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())`,
[
studyData.router_id,
studyData.study_instance_uid,
studyData.patient_id,
studyData.patient_name,
studyData.accession_number,
studyData.study_date,
studyData.modality,
studyData.study_description,
studyData.series_instance_uid,
studyData.procedure_code,
studyData.referring_physician_name,
studyData.study_status_code,
studyData.association_id
]
);
// Get the created study with the correct router_id format
const insertId = (result as any).insertId;
return await this.findById(insertId) as DicomStudy;
} catch (error) {
logger.error('Error creating DICOM study:', error);
throw new Error('Failed to create DICOM study');
}
}
async findAll(): Promise<DicomStudy[]> {
try {
const [rows] = await pool.query(`
SELECT d.*, r.router_id as router_string_id
FROM dicom_study_overview d
JOIN routers r ON d.router_id = r.id
ORDER BY d.created_at DESC
`);
return Promise.all((rows as DBDicomStudy[]).map(row => this.mapDBStudyToDicomStudy(row)));
} catch (error) {
logger.error('Error fetching all DICOM studies:', error);
throw new Error('Failed to fetch DICOM studies');
}
}
async findById(id: number): Promise<DicomStudy | null> {
try {
const [rows] = await pool.query(`
SELECT d.*, r.router_id as router_string_id
FROM dicom_study_overview d
JOIN routers r ON d.router_id = r.id
WHERE d.id = ?
`, [id]);
const results = rows as DBDicomStudy[];
if (results.length === 0) {
return null;
}
return await this.mapDBStudyToDicomStudy(results[0]);
} catch (error) {
logger.error('Error fetching DICOM study by ID:', error);
throw new Error('Failed to fetch DICOM study');
}
}
async findByRouterId(routerId: string): Promise<DicomStudy[]> {
try {
const numericRouterId = await this.getRouterNumericId(routerId);
const [rows] = await pool.query(`
SELECT d.*, r.router_id as router_string_id
FROM dicom_study_overview d
JOIN routers r ON d.router_id = r.id
WHERE d.router_id = ?
ORDER BY d.created_at DESC
`, [numericRouterId]);
return Promise.all((rows as DBDicomStudy[]).map(row => this.mapDBStudyToDicomStudy(row)));
} catch (error) {
logger.error('Error fetching DICOM studies by router ID:', error);
throw new Error('Failed to fetch DICOM studies');
}
}
async update(id: number, studyData: UpdateDicomStudyDTO): Promise<DicomStudy | null> {
try {
// First check if study exists
const existingStudy = await this.findById(id);
if (!existingStudy) {
return null;
}
// Build update query dynamically based on provided fields
const updateFields: string[] = [];
const updateValues: any[] = [];
Object.entries(studyData).forEach(([key, value]) => {
if (value !== undefined) {
updateFields.push(`${key} = ?`);
updateValues.push(value);
}
});
if (updateFields.length > 0) {
// Add updated_at timestamp
updateFields.push('updated_at = CURRENT_TIMESTAMP');
// Add id for WHERE clause
updateValues.push(id);
await pool.query(`
UPDATE dicom_study_overview
SET ${updateFields.join(', ')}
WHERE id = ?
`, updateValues);
}
// Return updated study
return await this.findById(id);
} catch (error) {
logger.error('Error updating DICOM study:', error);
throw new Error('Failed to update DICOM study');
}
}
async delete(id: number): Promise<boolean> {
try {
const [result] = await pool.query(
'DELETE FROM dicom_study_overview WHERE id = ?',
[id]
);
return (result as any).affectedRows > 0;
} catch (error) {
logger.error('Error deleting DICOM study:', error);
throw new Error('Failed to delete DICOM study');
}
}
async search(params: DicomStudySearchParams): Promise<DicomStudy[]> {
try {
let query = `
SELECT d.*, r.router_id as router_string_id
FROM dicom_study_overview d
JOIN routers r ON d.router_id = r.id
WHERE 1=1
`;
const values: any[] = [];
if (params.startDate) {
query += ' AND d.study_date >= ?';
values.push(params.startDate);
}
if (params.endDate) {
query += ' AND d.study_date <= ?';
values.push(params.endDate);
}
if (params.modality) {
query += ' AND d.modality = ?';
values.push(params.modality);
}
if (params.patientName) {
query += ' AND d.patient_name LIKE ?';
values.push(`%${params.patientName}%`);
}
// Add sorting
query += ' ORDER BY d.created_at DESC';
const [rows] = await pool.query(query, values);
return Promise.all((rows as DBDicomStudy[]).map(row => this.mapDBStudyToDicomStudy(row)));
} catch (error) {
logger.error('Error searching DICOM studies:', error);
throw new Error('Failed to search DICOM studies');
}
}
async findByStudyInstanceUid(studyInstanceUid: string): Promise<DicomStudy | null> {
try {
// Use RowDataPacket[] to align with mysql2/promise type expectations
const [rows] = await pool.query<DBDicomStudy[] & RowDataPacket[]>(`
SELECT * FROM dicom_study_overview WHERE study_instance_uid = ?`,
[studyInstanceUid]
);
// Check if rows is empty
if (rows.length === 0) {
return null;
}
// Map the first result to your DicomStudy object
return await this.mapDBStudyToDicomStudy(rows[0]);
} catch (error) {
logger.error('Error fetching DICOM study by Study Instance UID:', error);
throw new Error('Failed to fetch DICOM study');
}
}
}