import { Injectable } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { Prisma, rekam_medis } from '@dist/generated/prisma'; import { CreateRekamMedisDto } from './dto/create-rekammedis.dto'; import { CreateLogDto } from '../log/dto/create-log.dto'; @Injectable() export class RekammedisService { // Define known values as constants to avoid hardcoding everywhere private readonly KNOWN_BLOOD_TYPES = ['A', 'B', 'AB', 'O']; private readonly KNOWN_TINDAK_LANJUT = [ 'Dipulangkan untuk Kontrol', 'Dirawat', 'Dirujuk ke RS', 'Konsul Ke Poli Lain', 'Konsultasi Dokter Spesialis', 'Kontrol', 'Kontrol Ulang', 'Masuk Rawat Inap', 'Meninggal Dunia Sebelum Dirawat', 'Meninggal Dunia Setelah Dirawat', 'Pulang', 'Rencana Operasi', 'Rujuk Balik', 'Selesai Pelayanan IGD', 'Selesai Pelayanan Rawat Jalan', ]; constructor(private prisma: PrismaService) {} async getAllRekamMedis(params: { take?: number; skip?: number; page?: number; orderBy?: any; no_rm?: string; order?: 'asc' | 'desc'; id_visit?: string; nama_pasien?: string; tanggal_start?: string; tanggal_end?: string; umur_min?: string; umur_max?: string; jenis_kelamin?: string; gol_darah?: string; kode_diagnosa?: string; tindak_lanjut?: string; }) { const { skip, page, orderBy, order, no_rm, id_visit, nama_pasien, tanggal_start, tanggal_end, umur_min, umur_max, jenis_kelamin, kode_diagnosa, } = params; const golDarahArray = params.gol_darah?.split(',') || []; const tindakLanjutArray = params.tindak_lanjut?.split(',') || []; console.log('Params Received:', params); const take = params.take ? parseInt(params.take.toString()) : 10; const skipValue = skip ? parseInt(skip.toString()) : page ? (parseInt(page.toString()) - 1) * take : 0; const buildMultiSelectFilter = ( fieldName: string, selectedValues: string[], knownValues: string[], unknownLabel: string, includesDash: boolean = false, ) => { if (selectedValues.length === 0) { return undefined; } const hasKnownValues = selectedValues.some((val) => knownValues.includes(val), ); const hasUnknown = selectedValues.includes(unknownLabel); const totalOptions = knownValues.length + 1; if (selectedValues.length === totalOptions) { return undefined; } if (hasUnknown && !hasKnownValues) { const conditions: any[] = [{ [fieldName]: { equals: null } }]; if (includesDash) { conditions.push({ [fieldName]: { equals: '-' } }); conditions.push({ [fieldName]: { notIn: knownValues } }); } return conditions.length > 1 ? { OR: conditions } : conditions[0]; } if (hasKnownValues && hasUnknown) { const knownSelected = selectedValues.filter( (val) => val !== unknownLabel, ); const conditions: any[] = [ { [fieldName]: { in: knownSelected } }, { [fieldName]: { equals: null } }, ]; if (includesDash) { conditions.push({ [fieldName]: { equals: '-' } }); conditions.push({ [fieldName]: { notIn: knownValues } }); } return { OR: conditions }; } return { [fieldName]: { in: selectedValues } }; }; const golDarahFilter = buildMultiSelectFilter( 'gol_darah', golDarahArray, this.KNOWN_BLOOD_TYPES, 'Tidak Tahu', true, ); const tindakLanjutFilter = buildMultiSelectFilter( 'tindak_lanjut', tindakLanjutArray, this.KNOWN_TINDAK_LANJUT, 'Belum Ada Keterangan', false, ); const whereClause = { no_rm: no_rm ? { startsWith: no_rm } : undefined, id_visit: id_visit ? { contains: id_visit } : undefined, nama_pasien: nama_pasien ? { contains: nama_pasien } : undefined, waktu_visit: tanggal_start && tanggal_end ? { gte: new Date(tanggal_start), lte: new Date(tanggal_end), } : undefined, umur: umur_min && umur_max ? { gte: parseInt(umur_min, 10), lte: parseInt(umur_max, 10), } : undefined, jenis_kelamin: jenis_kelamin ? { equals: jenis_kelamin } : undefined, kode_diagnosa: kode_diagnosa ? { contains: kode_diagnosa } : undefined, ...golDarahFilter, ...tindakLanjutFilter, }; const results = await this.prisma.rekam_medis.findMany({ skip: skipValue, take: take, where: whereClause, orderBy: orderBy ? { [orderBy]: order || 'asc' } : { waktu_visit: order ? order : 'asc' }, }); const count = await this.prisma.rekam_medis.count({ where: whereClause, }); const umurMin = await this.prisma.rekam_medis.findMany({ distinct: ['umur'], orderBy: { umur: 'asc', }, select: { umur: true, }, }); const umurMax = await this.prisma.rekam_medis.findMany({ distinct: ['umur'], orderBy: { umur: 'desc', }, select: { umur: true, }, }); const rangeUmur = { min: umurMin.length > 0 ? umurMin[0].umur : null, max: umurMax.length > 0 ? umurMax[0].umur : null, }; return { ...results, totalCount: count, rangeUmur: rangeUmur, }; } async createRekamMedis(data: CreateRekamMedisDto) { const latestId = await this.prisma.rekam_medis.findFirst({ orderBy: { waktu_visit: 'desc' }, }); let newId = ''; let xCounter = 0; let rekamMedis: Prisma.rekam_medisCreateInput; for (let i = (latestId?.id_visit?.length ?? 0) - 1; i >= 0; i--) { if (latestId?.id_visit[i] === 'X') { xCounter++; } else { newId = latestId?.id_visit?.substring(0, i + 1) || ''; break; } } if (xCounter < 1) { newId = (parseInt(latestId?.id_visit || '0', 10) + 1).toString(); } else { newId = (parseInt(newId || '0', 10) + 1).toString(); } rekamMedis = { ...data, id_visit: newId, waktu_visit: new Date(), }; const logData: CreateLogDto = { event: 'rekam_medis_created', payload: { dokter_id: 123, visit_id: newId, anamnese: data.anamnese, jenis_kasus: data.jenis_kasus, tindak_lanjut: data.tindak_lanjut, }, }; try { const newRekamMedis = await this.prisma.$transaction(async (tx) => { const createdRekamMedis = await tx.rekam_medis.create({ data: rekamMedis, }); await tx.blockchain_log_queue.create({ data: { event: logData.event, user_id: 9, payload: logData.payload, }, }); // Input Into Fabric Here return createdRekamMedis; }); return newRekamMedis; } catch (error) { console.error('Error creating Rekam Medis:', error); throw error; } } }