update
This commit is contained in:
No files matched your search
@@ -237,7 +237,11 @@ class ListController extends Controller
|
|||||||
$tcmtb,
|
$tcmtb,
|
||||||
$urine
|
$urine
|
||||||
);
|
);
|
||||||
|
$batasWaktu = Carbon::now()->subHours(24);
|
||||||
|
Periksa::whereNull('status')->where('mulai', '<', $batasWaktu)->update([
|
||||||
|
'status' => 'Dibatalkan (Arsip)',
|
||||||
|
'updated_at' => now()
|
||||||
|
]);
|
||||||
$arraylist = Periksa::select(
|
$arraylist = Periksa::select(
|
||||||
'id', 'mulai', 'akhir', 'orderid', 'noloket', 'nofoto', 'noregister', 'asalpasien', 'nmrs', 'pasien_id', 'nmpasien',
|
'id', 'mulai', 'akhir', 'orderid', 'noloket', 'nofoto', 'noregister', 'asalpasien', 'nmrs', 'pasien_id', 'nmpasien',
|
||||||
'jkpasien', 'tgllahirpasien', 'tlppasien', 'alamatpasien', 'reques', 'usia', 'berat', 'ktp', 'bpjs', 'ruangan_id',
|
'jkpasien', 'tgllahirpasien', 'tlppasien', 'alamatpasien', 'reques', 'usia', 'berat', 'ktp', 'bpjs', 'ruangan_id',
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ class AstmMessageService
|
|||||||
Periksa::where('nofoto', $accession_number)->update([
|
Periksa::where('nofoto', $accession_number)->update([
|
||||||
'status' => 'Data Vitek di Terima',
|
'status' => 'Data Vitek di Terima',
|
||||||
]);
|
]);
|
||||||
Log::info("Data berhasil disimpan:", $resultSample->toArray());
|
//Log::info("Data berhasil disimpan:", $resultSample->toArray());
|
||||||
$resultSample->save();
|
$resultSample->save();
|
||||||
}
|
}
|
||||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||||
@@ -467,7 +467,7 @@ class AstmMessageService
|
|||||||
'status' => 'Data Vitek di Terima',
|
'status' => 'Data Vitek di Terima',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
Log::info("Data MTRL Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
//Log::info("Data MTRL Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
||||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||||
} else {
|
} else {
|
||||||
$headerData = explode("|", $astmData);
|
$headerData = explode("|", $astmData);
|
||||||
@@ -628,7 +628,7 @@ class AstmMessageService
|
|||||||
$resultSample->additional_result = json_encode($resultData);
|
$resultSample->additional_result = json_encode($resultData);
|
||||||
if ($noregister){
|
if ($noregister){
|
||||||
$resultSample->save();
|
$resultSample->save();
|
||||||
Log::info("Data ASTM Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
//Log::info("Data ASTM Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
||||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -823,7 +823,7 @@ class AstmMessageService
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Log::info("Data BD ASTM Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
//Log::info("Data BD ASTM Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -838,7 +838,6 @@ class AstmMessageService
|
|||||||
public function processAstmMessagesLokal($dataListener) {
|
public function processAstmMessagesLokal($dataListener) {
|
||||||
foreach ($dataListener as $data) {
|
foreach ($dataListener as $data) {
|
||||||
try {
|
try {
|
||||||
// Ambil pesan ASTM dari kolom 'message' atau yang relevan
|
|
||||||
$response = $data->rawdt;
|
$response = $data->rawdt;
|
||||||
if ($data->alat == 'MGIT' OR $data->alat == 'COM5' OR $data->alat == 'BACTEC'){
|
if ($data->alat == 'MGIT' OR $data->alat == 'COM5' OR $data->alat == 'BACTEC'){
|
||||||
$assembled = $this->reassembleAstmFrames($data->rawdt);
|
$assembled = $this->reassembleAstmFrames($data->rawdt);
|
||||||
|
|||||||
@@ -70,9 +70,9 @@
|
|||||||
<td valign="top">Tanggal Kirim Sample</td>
|
<td valign="top">Tanggal Kirim Sample</td>
|
||||||
<td valign="top">:</td>
|
<td valign="top">:</td>
|
||||||
<td valign="top">{{ $periksa->daftar }}</td>
|
<td valign="top">{{ $periksa->daftar }}</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">Spesimen</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">:</td>
|
||||||
<td valign="top" colspan="2"> </td>
|
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -69,9 +69,9 @@
|
|||||||
<td valign="top">Tanggal Kirim Sample</td>
|
<td valign="top">Tanggal Kirim Sample</td>
|
||||||
<td valign="top">:</td>
|
<td valign="top">:</td>
|
||||||
<td valign="top">{{ $periksa->daftar }}</td>
|
<td valign="top">{{ $periksa->daftar }}</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">Spesimen</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">:</td>
|
||||||
<td valign="top" colspan="2"> </td>
|
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -87,9 +87,9 @@
|
|||||||
<td valign="top">Tanggal Kirim Sample</td>
|
<td valign="top">Tanggal Kirim Sample</td>
|
||||||
<td valign="top">:</td>
|
<td valign="top">:</td>
|
||||||
<td valign="top">{{ $periksa->daftar }}</td>
|
<td valign="top">{{ $periksa->daftar }}</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">Spesimen</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">:</td>
|
||||||
<td valign="top" colspan="2"> </td>
|
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -69,9 +69,9 @@
|
|||||||
<td valign="top">Tanggal Kirim Sample</td>
|
<td valign="top">Tanggal Kirim Sample</td>
|
||||||
<td valign="top">:</td>
|
<td valign="top">:</td>
|
||||||
<td valign="top">{{ $periksa->daftar }}</td>
|
<td valign="top">{{ $periksa->daftar }}</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">Spesimen</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">:</td>
|
||||||
<td valign="top" colspan="2"> </td>
|
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -85,9 +85,9 @@
|
|||||||
<td valign="top">Tanggal Kirim Sample</td>
|
<td valign="top">Tanggal Kirim Sample</td>
|
||||||
<td valign="top">:</td>
|
<td valign="top">:</td>
|
||||||
<td valign="top">{{ $periksa->daftar }}</td>
|
<td valign="top">{{ $periksa->daftar }}</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">Spesimen</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">:</td>
|
||||||
<td valign="top" colspan="2"> </td>
|
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -70,9 +70,9 @@
|
|||||||
<td valign="top">Tanggal Kirim Sample</td>
|
<td valign="top">Tanggal Kirim Sample</td>
|
||||||
<td valign="top">:</td>
|
<td valign="top">:</td>
|
||||||
<td valign="top">{{ $periksa->daftar }}</td>
|
<td valign="top">{{ $periksa->daftar }}</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">Spesimen</td>
|
||||||
<td valign="top"> </td>
|
<td valign="top">:</td>
|
||||||
<td valign="top" colspan="2"> </td>
|
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -1555,8 +1555,8 @@
|
|||||||
<div class="form-group col-lg-4">
|
<div class="form-group col-lg-4">
|
||||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="D">MTB Detected (D)</option>
|
<option value="Detected">MTB Detected (D)</option>
|
||||||
<option value="ND">MTB Not Detected (ND)</option>
|
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1707,8 +1707,8 @@
|
|||||||
<div class="form-group col-lg-4">
|
<div class="form-group col-lg-4">
|
||||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="D">MTB Detected (D)</option>
|
<option value="Detected">MTB Detected (D)</option>
|
||||||
<option value="ND">MTB Not Detected (ND)</option>
|
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1610,8 +1610,8 @@
|
|||||||
<div class="form-group col-lg-4">
|
<div class="form-group col-lg-4">
|
||||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="D">MTB Detected (D)</option>
|
<option value="Detected">MTB Detected (D)</option>
|
||||||
<option value="ND">MTB Not Detected (ND)</option>
|
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1762,8 +1762,8 @@
|
|||||||
<div class="form-group col-lg-4">
|
<div class="form-group col-lg-4">
|
||||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="D">MTB Detected (D)</option>
|
<option value="Detected">MTB Detected (D)</option>
|
||||||
<option value="ND">MTB Not Detected (ND)</option>
|
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1610,8 +1610,8 @@
|
|||||||
<div class="form-group col-lg-4">
|
<div class="form-group col-lg-4">
|
||||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="D">MTB Detected (D)</option>
|
<option value="Detected">MTB Detected (D)</option>
|
||||||
<option value="ND">MTB Not Detected (ND)</option>
|
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1762,8 +1762,8 @@
|
|||||||
<div class="form-group col-lg-4">
|
<div class="form-group col-lg-4">
|
||||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="D">MTB Detected (D)</option>
|
<option value="Detected">MTB Detected (D)</option>
|
||||||
<option value="ND">MTB Not Detected (ND)</option>
|
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+92
-83
@@ -75,7 +75,7 @@ active_genexpert_connections = {}
|
|||||||
connection_lock = threading.Lock()
|
connection_lock = threading.Lock()
|
||||||
DEVICE_CONFIGS = [
|
DEVICE_CONFIGS = [
|
||||||
{
|
{
|
||||||
'port': 'COM6', 'baud_rate': 19200, 'device_type': 'vitek', 'alat_name': 'Vitek 1',
|
'port': 'COM6', 'baud_rate': 9600, 'device_type': 'vitek', 'alat_name': 'Vitek 1',
|
||||||
'protocol': 'serial', 'flag_column': 'flg_vitek1'
|
'protocol': 'serial', 'flag_column': 'flg_vitek1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -133,7 +133,7 @@ class LisPhoenix(Base):
|
|||||||
__tablename__ = 'lis_phoenix'
|
__tablename__ = 'lis_phoenix'
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
no_id = Column(String(50)) # Patient ID
|
no_id = Column(String(50)) # Patient ID
|
||||||
seq_no = Column(String(50), unique=True) # Isolate ID / Sample ID
|
seq_no = Column(String(50)) # Isolate ID / Sample ID
|
||||||
rnmpas = Column(String(100)) # Patient Name
|
rnmpas = Column(String(100)) # Patient Name
|
||||||
tgl_data = Column(SqDate)
|
tgl_data = Column(SqDate)
|
||||||
rawdt = Column(Text)
|
rawdt = Column(Text)
|
||||||
@@ -145,7 +145,7 @@ class LisPhoenix(Base):
|
|||||||
class LisPhoenixDtl(Base):
|
class LisPhoenixDtl(Base):
|
||||||
__tablename__ = 'lis_phoenix_dtl'
|
__tablename__ = 'lis_phoenix_dtl'
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
seq_no = Column(String(50), index=True) # Isolate ID / Sample ID
|
seq_no = Column(String(50)) # Isolate ID / Sample ID
|
||||||
kd_antibiotik = Column(String(50))
|
kd_antibiotik = Column(String(50))
|
||||||
nm_antibiotik = Column(String(100))
|
nm_antibiotik = Column(String(100))
|
||||||
keterangan = Column(String(50)) # MIC Value (e.g., <=0.5)
|
keterangan = Column(String(50)) # MIC Value (e.g., <=0.5)
|
||||||
@@ -557,111 +557,121 @@ def calculate_vitek_checksum(data_str):
|
|||||||
def parse_and_save_vitek_result(raw_data, port_name="VITEK"):
|
def parse_and_save_vitek_result(raw_data, port_name="VITEK"):
|
||||||
session = SessionLocal()
|
session = SessionLocal()
|
||||||
try:
|
try:
|
||||||
# --- LANGKAH 1: PEMBERSIHAN DATA ---
|
# --- 1. CLEANING DATA ---
|
||||||
# Vitek sering mengirim karakter framing \x1e (RS), \x1d (GS), \x03 (ETX)
|
# Hapus karakter kontrol STX(02), ETX(03), RS(1e/30), GS(1d/29), CR, LF
|
||||||
# Hapus framing characters dan newline
|
# Perhatikan: Log Anda menunjukkan RS () muncul di tengah kata, jadi harus dihapus total.
|
||||||
clean_data = raw_data.replace('\x02', '').replace('\x03', '').replace('\x1e', '').replace('\r', '').replace('\n', '')
|
clean_data = raw_data.replace('\x02', '').replace('\x03', '').replace('\x1e', '').replace('\x1d', '').replace('\r', '').replace('\n', '')
|
||||||
|
|
||||||
# Pisahkan jika ada checksum di akhir (biasanya setelah \x1d)
|
# Pisahkan field berdasarkan pipa '|'
|
||||||
if '\x1d' in clean_data:
|
|
||||||
clean_data = clean_data.split('\x1d')[0]
|
|
||||||
|
|
||||||
# --- LANGKAH 2: PARSING FIELD BERDASARKAN TAG ---
|
|
||||||
# Format Vitek: tag|value|tag|value...
|
|
||||||
fields = clean_data.split('|')
|
fields = clean_data.split('|')
|
||||||
|
|
||||||
msg_type = fields[0] # mtmpr (Order) atau mtrsl (Result)
|
# Cek apakah ini pesan result (mtrsl)
|
||||||
|
if not fields or fields[0] != 'mtrsl':
|
||||||
|
return # Abaikan jika bukan result
|
||||||
|
|
||||||
# Inisialisasi variabel
|
# --- 2. VARIABLE INIT ---
|
||||||
sample_id = None # ci (Accession Number)
|
sample_id = None # ci (No Lab / No Container)
|
||||||
patient_id = "" # pi
|
patient_id = "" # pi (No RM)
|
||||||
patient_name = "" # pn
|
patient_name = "" # pn
|
||||||
organism_name = "" # o2
|
organism_name = "" # o2
|
||||||
antibiotics = [] # List untuk menyimpan hasil AB
|
card_barcode = "" # is
|
||||||
|
antibiotics = [] # List penampung hasil AB
|
||||||
result_date = datetime.datetime.now()
|
result_date = datetime.datetime.now()
|
||||||
|
|
||||||
# Penanda apakah kita sedang membaca blok antibiotik
|
# Variabel sementara untuk looping antibiotik
|
||||||
current_ab_name = ""
|
curr_ab_name = ""
|
||||||
current_ab_mic = ""
|
curr_ab_mic = ""
|
||||||
current_ab_int = ""
|
curr_ab_int = ""
|
||||||
|
|
||||||
# Loop setiap field untuk mencari Tag
|
# --- 3. PARSING LOOP ---
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if not field: continue
|
if not field: continue
|
||||||
|
|
||||||
# --- HEADER INFO ---
|
# --- HEADER INFO ---
|
||||||
if field.startswith("pi") and len(field) > 2: # Patient ID
|
if field.startswith("ci") and len(field) > 2:
|
||||||
patient_id = field[2:].strip()
|
|
||||||
elif field.startswith("pn") and len(field) > 2: # Patient Name
|
|
||||||
patient_name = field[2:].strip()
|
|
||||||
elif field.startswith("ci") and len(field) > 2: # Case ID / No Reg (KUNCI UTAMA)
|
|
||||||
# Format Vitek kadang 25-035007, kita ambil angkanya saja atau sesuai format LIS
|
|
||||||
sample_id = field[2:].strip()
|
sample_id = field[2:].strip()
|
||||||
|
elif field.startswith("pi") and len(field) > 2:
|
||||||
# --- ORGANISME (Bakteri) ---
|
patient_id = field[2:].strip()
|
||||||
|
elif field.startswith("pn") and len(field) > 2:
|
||||||
|
patient_name = field[2:].strip()
|
||||||
|
elif field.startswith("is") and len(field) > 2:
|
||||||
|
card_barcode = field[2:].strip()
|
||||||
|
# --- ORGANISME ---
|
||||||
elif field.startswith("o2") and len(field) > 2:
|
elif field.startswith("o2") and len(field) > 2:
|
||||||
organism_name = field[2:].strip()
|
organism_name = field[2:].strip()
|
||||||
|
|
||||||
# --- ANTIBIOTIK (Looping Block) ---
|
# --- ANTIBIOTIK BLOCK (Mulai Pesan Kedua) ---
|
||||||
# Penanda blok antibiotik baru dimulai dengan tag 'ra'
|
# Tag 'ra' adalah pemisah antar obat
|
||||||
elif field == "ra":
|
elif field == "ra":
|
||||||
# Simpan antibiotik sebelumnya jika ada
|
# Jika ada data obat sebelumnya di memori, simpan dulu
|
||||||
if current_ab_name:
|
if curr_ab_name:
|
||||||
ab_str = f"{current_ab_name} {current_ab_mic} ({current_ab_int})"
|
ab_str = f"{curr_ab_name} {curr_ab_mic} ({curr_ab_int})"
|
||||||
antibiotics.append(ab_str)
|
antibiotics.append(ab_str)
|
||||||
# Reset temp vars
|
# Reset untuk obat berikutnya
|
||||||
current_ab_name = ""
|
curr_ab_name = ""; curr_ab_mic = ""; curr_ab_int = ""
|
||||||
current_ab_mic = ""
|
|
||||||
current_ab_int = ""
|
|
||||||
|
|
||||||
# Detail Antibiotik
|
# Detail Obat
|
||||||
elif field.startswith("a2") and len(field) > 2: # Nama Antibiotik
|
elif field.startswith("a2") and len(field) > 2: # Nama Obat (mis: Cefoxitin)
|
||||||
current_ab_name = field[2:].strip()
|
curr_ab_name = field[2:].strip()
|
||||||
elif field.startswith("a3") and len(field) > 2: # Nilai MIC
|
elif field.startswith("a3") and len(field) > 2: # MIC (mis: >=4)
|
||||||
current_ab_mic = field[2:].strip()
|
curr_ab_mic = field[2:].strip()
|
||||||
elif field.startswith("a4") and len(field) > 2: # Interpretasi (S/I/R)
|
elif field.startswith("a4") and len(field) > 2: # Interpretasi (R/S/I)
|
||||||
current_ab_int = field[2:].strip()
|
curr_ab_int = field[2:].strip()
|
||||||
elif field.startswith("an") and len(field) > 2: # Interpretasi Alternatif
|
elif field.startswith("an") and len(field) > 2: # Interpretasi Alternatif
|
||||||
if not current_ab_int: current_ab_int = field[2:].strip()
|
if not curr_ab_int: curr_ab_int = field[2:].strip()
|
||||||
|
|
||||||
# Jangan lupa simpan antibiotik terakhir setelah loop selesai
|
# Jangan lupa simpan obat terakhir yang tersisa di buffer
|
||||||
if current_ab_name:
|
if curr_ab_name:
|
||||||
ab_str = f"{current_ab_name} {current_ab_mic} ({current_ab_int})"
|
ab_str = f"{curr_ab_name} {curr_ab_mic} ({curr_ab_int})"
|
||||||
antibiotics.append(ab_str)
|
antibiotics.append(ab_str)
|
||||||
|
|
||||||
# --- LANGKAH 3: FORMAT FINAL & SAVE ---
|
# --- 4. FORMAT FINAL STRING ---
|
||||||
# Kita hanya memproses jika tipe pesan adalah 'mtrsl' (Result) dan ada Sample ID
|
# Format: "Staphylococcus hominis | Cefoxitin >=4 (R), Gentamicin 4 (S)..."
|
||||||
if msg_type == 'mtrsl' and sample_id:
|
final_res_string = organism_name
|
||||||
|
#if antibiotics:
|
||||||
|
# final_res_string += " | " + ", ".join(antibiotics)
|
||||||
|
|
||||||
|
# Fallback jika negatif (biasanya tidak ada o2, tapi ada teks neg)
|
||||||
|
#if not final_res_string and "neg" in raw_data.lower():
|
||||||
|
# final_res_string = "NEGATIVE / NO GROWTH"
|
||||||
|
|
||||||
|
# --- 5. LOGIKA DATABASE (UPSERT: UPDATE or INSERT) ---
|
||||||
|
if sample_id:
|
||||||
|
# Cari data berdasarkan No Lab (Sample ID)
|
||||||
|
final_seq_no = card_barcode if card_barcode else patient_id
|
||||||
|
existing_data = session.query(LisPhoenix).filter(
|
||||||
|
LisPhoenix.seq_no == final_seq_no
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if existing_data:
|
||||||
|
# === SKENARIO PESAN KEDUA (UPDATE) ===
|
||||||
|
logging.info(f"[{port_name}] UPDATE Data (Tahap 2) -> ID: {sample_id}, Pasien: {patient_name}")
|
||||||
|
print(f"[{port_name}] UPDATE Data -> ID: {sample_id} (Hasil Lengkap)")
|
||||||
|
existing_data.rnmpas = patient_name
|
||||||
|
existing_data.organisme = final_res_string
|
||||||
|
existing_data.rawdt = raw_data
|
||||||
|
existing_data.tgl_data = result_date
|
||||||
|
existing_data.processed = None
|
||||||
|
|
||||||
|
else:
|
||||||
|
# === SKENARIO PESAN PERTAMA (INSERT) ===
|
||||||
|
logging.info(f"[{port_name}] INSERT Data Baru (Tahap 1) -> ID: {sample_id}, Pasien: {patient_name}")
|
||||||
|
print(f"[{port_name}] INSERT Data -> ID: {sample_id} (Identifikasi Awal)")
|
||||||
|
|
||||||
|
new_entry = LisPhoenix(
|
||||||
|
no_id=sample_id,
|
||||||
|
seq_no=final_seq_no,
|
||||||
|
rnmpas=patient_name,
|
||||||
|
tgl_data=result_date,
|
||||||
|
rawdt=raw_data,
|
||||||
|
organisme=final_res_string,
|
||||||
|
alat=port_name
|
||||||
|
)
|
||||||
|
session.add(new_entry)
|
||||||
|
|
||||||
# Gabungkan hasil: Organisme | AB1, AB2, AB3...
|
|
||||||
final_res_string = organism_name
|
|
||||||
if antibiotics:
|
|
||||||
final_res_string += " | " + ", ".join(antibiotics)
|
|
||||||
|
|
||||||
# Jika tidak ada organisme tapi tipe result, mungkin Negative?
|
|
||||||
if not final_res_string and "neg" in raw_data.lower():
|
|
||||||
final_res_string = "NEGATIVE / NO GROWTH"
|
|
||||||
|
|
||||||
logging.info(f"[{port_name}] Save DB -> ID: {sample_id}, Pasien: {patient_name}, Bakteri: {organism_name}")
|
|
||||||
print(f"[{port_name}] Save DB -> ID: {sample_id}, Pasien: {patient_name}, Bakteri: {organism_name}")
|
|
||||||
new_entry = LisPhoenix(
|
|
||||||
no_id=sample_id, # Menggunakan tag 'ci'
|
|
||||||
seq_no=patient_id, # Menggunakan tag 'pi'
|
|
||||||
rnmpas=patient_name, # Menggunakan tag 'pn'
|
|
||||||
tgl_data=result_date,
|
|
||||||
rawdt=raw_data,
|
|
||||||
organisme=final_res_string, # Hasil gabungan
|
|
||||||
alat=port_name
|
|
||||||
)
|
|
||||||
session.add(new_entry)
|
|
||||||
session.commit()
|
session.commit()
|
||||||
else:
|
else:
|
||||||
if msg_type != 'mtrsl':
|
logging.warning(f"[{port_name}] Pesan diabaikan (Tanpa Sample ID): {clean_data[:30]}...")
|
||||||
logging.info(f"[{port_name}] Mengabaikan pesan tipe {msg_type}")
|
|
||||||
print(f"[{port_name}] Mengabaikan pesan tipe {msg_type}")
|
|
||||||
else:
|
|
||||||
logging.warning(f"[{port_name}] Data tidak lengkap (No Sample ID). Raw: {raw_data[:50]}...")
|
|
||||||
print(f"[{port_name}] Data tidak lengkap (No Sample ID). Raw: {raw_data[:50]}...")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error Parsing Vitek: {e}")
|
logging.error(f"Error Parsing Vitek: {e}")
|
||||||
@@ -669,7 +679,6 @@ def parse_and_save_vitek_result(raw_data, port_name="VITEK"):
|
|||||||
session.rollback()
|
session.rollback()
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
def create_vitek_order_message(order):
|
def create_vitek_order_message(order):
|
||||||
"""
|
"""
|
||||||
Membuat Frame Order Vitek sesuai Manual Ref 514937.
|
Membuat Frame Order Vitek sesuai Manual Ref 514937.
|
||||||
|
|||||||
Reference in New Issue
Block a user