update
This commit is contained in:
@@ -237,7 +237,11 @@ class ListController extends Controller
|
||||
$tcmtb,
|
||||
$urine
|
||||
);
|
||||
|
||||
$batasWaktu = Carbon::now()->subHours(24);
|
||||
Periksa::whereNull('status')->where('mulai', '<', $batasWaktu)->update([
|
||||
'status' => 'Dibatalkan (Arsip)',
|
||||
'updated_at' => now()
|
||||
]);
|
||||
$arraylist = Periksa::select(
|
||||
'id', 'mulai', 'akhir', 'orderid', 'noloket', 'nofoto', 'noregister', 'asalpasien', 'nmrs', 'pasien_id', 'nmpasien',
|
||||
'jkpasien', 'tgllahirpasien', 'tlppasien', 'alamatpasien', 'reques', 'usia', 'berat', 'ktp', 'bpjs', 'ruangan_id',
|
||||
|
||||
@@ -285,7 +285,7 @@ class AstmMessageService
|
||||
Periksa::where('nofoto', $accession_number)->update([
|
||||
'status' => 'Data Vitek di Terima',
|
||||
]);
|
||||
Log::info("Data berhasil disimpan:", $resultSample->toArray());
|
||||
//Log::info("Data berhasil disimpan:", $resultSample->toArray());
|
||||
$resultSample->save();
|
||||
}
|
||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||
@@ -467,7 +467,7 @@ class AstmMessageService
|
||||
'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.']);
|
||||
} else {
|
||||
$headerData = explode("|", $astmData);
|
||||
@@ -628,7 +628,7 @@ class AstmMessageService
|
||||
$resultSample->additional_result = json_encode($resultData);
|
||||
if ($noregister){
|
||||
$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.']);
|
||||
}
|
||||
} 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;
|
||||
@@ -838,7 +838,6 @@ class AstmMessageService
|
||||
public function processAstmMessagesLokal($dataListener) {
|
||||
foreach ($dataListener as $data) {
|
||||
try {
|
||||
// Ambil pesan ASTM dari kolom 'message' atau yang relevan
|
||||
$response = $data->rawdt;
|
||||
if ($data->alat == 'MGIT' OR $data->alat == 'COM5' OR $data->alat == 'BACTEC'){
|
||||
$assembled = $this->reassembleAstmFrames($data->rawdt);
|
||||
|
||||
@@ -70,9 +70,9 @@
|
||||
<td valign="top">Tanggal Kirim Sample</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top">{{ $periksa->daftar }}</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top" colspan="2"> </td>
|
||||
<td valign="top">Spesimen</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -69,9 +69,9 @@
|
||||
<td valign="top">Tanggal Kirim Sample</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top">{{ $periksa->daftar }}</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top" colspan="2"> </td>
|
||||
<td valign="top">Spesimen</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -87,9 +87,9 @@
|
||||
<td valign="top">Tanggal Kirim Sample</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top">{{ $periksa->daftar }}</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top" colspan="2"> </td>
|
||||
<td valign="top">Spesimen</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -69,9 +69,9 @@
|
||||
<td valign="top">Tanggal Kirim Sample</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top">{{ $periksa->daftar }}</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top" colspan="2"> </td>
|
||||
<td valign="top">Spesimen</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
<td valign="top">Tanggal Kirim Sample</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top">{{ $periksa->daftar }}</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top" colspan="2"> </td>
|
||||
<td valign="top">Spesimen</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -70,9 +70,9 @@
|
||||
<td valign="top">Tanggal Kirim Sample</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top">{{ $periksa->daftar }}</td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top" colspan="2"> </td>
|
||||
<td valign="top">Spesimen</td>
|
||||
<td valign="top">:</td>
|
||||
<td valign="top" colspan="2">{!! $periksa->nm_spesimen !!}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -1555,8 +1555,8 @@
|
||||
<div class="form-group col-lg-4">
|
||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
||||
<option value=""></option>
|
||||
<option value="D">MTB Detected (D)</option>
|
||||
<option value="ND">MTB Not Detected (ND)</option>
|
||||
<option value="Detected">MTB Detected (D)</option>
|
||||
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1707,8 +1707,8 @@
|
||||
<div class="form-group col-lg-4">
|
||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
||||
<option value=""></option>
|
||||
<option value="D">MTB Detected (D)</option>
|
||||
<option value="ND">MTB Not Detected (ND)</option>
|
||||
<option value="Detected">MTB Detected (D)</option>
|
||||
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1610,8 +1610,8 @@
|
||||
<div class="form-group col-lg-4">
|
||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
||||
<option value=""></option>
|
||||
<option value="D">MTB Detected (D)</option>
|
||||
<option value="ND">MTB Not Detected (ND)</option>
|
||||
<option value="Detected">MTB Detected (D)</option>
|
||||
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1762,8 +1762,8 @@
|
||||
<div class="form-group col-lg-4">
|
||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
||||
<option value=""></option>
|
||||
<option value="D">MTB Detected (D)</option>
|
||||
<option value="ND">MTB Not Detected (ND)</option>
|
||||
<option value="Detected">MTB Detected (D)</option>
|
||||
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1610,8 +1610,8 @@
|
||||
<div class="form-group col-lg-4">
|
||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_pagimtb" name="hasilpemeriksaanttcmmtbxdrxpert_pagimtb">
|
||||
<option value=""></option>
|
||||
<option value="D">MTB Detected (D)</option>
|
||||
<option value="ND">MTB Not Detected (ND)</option>
|
||||
<option value="Detected">MTB Detected (D)</option>
|
||||
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1762,8 +1762,8 @@
|
||||
<div class="form-group col-lg-4">
|
||||
<select class="form-control ekspertiseseletc" id="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb" name="hasilpemeriksaanttcmmtbxdrxpert_sewaktumtb">
|
||||
<option value=""></option>
|
||||
<option value="D">MTB Detected (D)</option>
|
||||
<option value="ND">MTB Not Detected (ND)</option>
|
||||
<option value="Detected">MTB Detected (D)</option>
|
||||
<option value="Not Detected">MTB Not Detected (ND)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+92
-83
@@ -75,7 +75,7 @@ active_genexpert_connections = {}
|
||||
connection_lock = threading.Lock()
|
||||
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'
|
||||
},
|
||||
{
|
||||
@@ -133,7 +133,7 @@ class LisPhoenix(Base):
|
||||
__tablename__ = 'lis_phoenix'
|
||||
id = Column(Integer, primary_key=True)
|
||||
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
|
||||
tgl_data = Column(SqDate)
|
||||
rawdt = Column(Text)
|
||||
@@ -145,7 +145,7 @@ class LisPhoenix(Base):
|
||||
class LisPhoenixDtl(Base):
|
||||
__tablename__ = 'lis_phoenix_dtl'
|
||||
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))
|
||||
nm_antibiotik = Column(String(100))
|
||||
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"):
|
||||
session = SessionLocal()
|
||||
try:
|
||||
# --- LANGKAH 1: PEMBERSIHAN DATA ---
|
||||
# Vitek sering mengirim karakter framing \x1e (RS), \x1d (GS), \x03 (ETX)
|
||||
# Hapus framing characters dan newline
|
||||
clean_data = raw_data.replace('\x02', '').replace('\x03', '').replace('\x1e', '').replace('\r', '').replace('\n', '')
|
||||
# --- 1. CLEANING DATA ---
|
||||
# Hapus karakter kontrol STX(02), ETX(03), RS(1e/30), GS(1d/29), CR, LF
|
||||
# Perhatikan: Log Anda menunjukkan RS () muncul di tengah kata, jadi harus dihapus total.
|
||||
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)
|
||||
if '\x1d' in clean_data:
|
||||
clean_data = clean_data.split('\x1d')[0]
|
||||
|
||||
# --- LANGKAH 2: PARSING FIELD BERDASARKAN TAG ---
|
||||
# Format Vitek: tag|value|tag|value...
|
||||
# Pisahkan field berdasarkan pipa '|'
|
||||
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
|
||||
sample_id = None # ci (Accession Number)
|
||||
patient_id = "" # pi
|
||||
# --- 2. VARIABLE INIT ---
|
||||
sample_id = None # ci (No Lab / No Container)
|
||||
patient_id = "" # pi (No RM)
|
||||
patient_name = "" # pn
|
||||
organism_name = "" # o2
|
||||
antibiotics = [] # List untuk menyimpan hasil AB
|
||||
card_barcode = "" # is
|
||||
antibiotics = [] # List penampung hasil AB
|
||||
result_date = datetime.datetime.now()
|
||||
|
||||
# Penanda apakah kita sedang membaca blok antibiotik
|
||||
current_ab_name = ""
|
||||
current_ab_mic = ""
|
||||
current_ab_int = ""
|
||||
# Variabel sementara untuk looping antibiotik
|
||||
curr_ab_name = ""
|
||||
curr_ab_mic = ""
|
||||
curr_ab_int = ""
|
||||
|
||||
# Loop setiap field untuk mencari Tag
|
||||
# --- 3. PARSING LOOP ---
|
||||
for field in fields:
|
||||
if not field: continue
|
||||
|
||||
# --- HEADER INFO ---
|
||||
if field.startswith("pi") and len(field) > 2: # Patient ID
|
||||
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
|
||||
if field.startswith("ci") and len(field) > 2:
|
||||
sample_id = field[2:].strip()
|
||||
|
||||
# --- ORGANISME (Bakteri) ---
|
||||
elif field.startswith("pi") and len(field) > 2:
|
||||
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:
|
||||
organism_name = field[2:].strip()
|
||||
|
||||
# --- ANTIBIOTIK (Looping Block) ---
|
||||
# Penanda blok antibiotik baru dimulai dengan tag 'ra'
|
||||
# --- ANTIBIOTIK BLOCK (Mulai Pesan Kedua) ---
|
||||
# Tag 'ra' adalah pemisah antar obat
|
||||
elif field == "ra":
|
||||
# Simpan antibiotik sebelumnya jika ada
|
||||
if current_ab_name:
|
||||
ab_str = f"{current_ab_name} {current_ab_mic} ({current_ab_int})"
|
||||
# Jika ada data obat sebelumnya di memori, simpan dulu
|
||||
if curr_ab_name:
|
||||
ab_str = f"{curr_ab_name} {curr_ab_mic} ({curr_ab_int})"
|
||||
antibiotics.append(ab_str)
|
||||
# Reset temp vars
|
||||
current_ab_name = ""
|
||||
current_ab_mic = ""
|
||||
current_ab_int = ""
|
||||
# Reset untuk obat berikutnya
|
||||
curr_ab_name = ""; curr_ab_mic = ""; curr_ab_int = ""
|
||||
|
||||
# Detail Antibiotik
|
||||
elif field.startswith("a2") and len(field) > 2: # Nama Antibiotik
|
||||
current_ab_name = field[2:].strip()
|
||||
elif field.startswith("a3") and len(field) > 2: # Nilai MIC
|
||||
current_ab_mic = field[2:].strip()
|
||||
elif field.startswith("a4") and len(field) > 2: # Interpretasi (S/I/R)
|
||||
current_ab_int = field[2:].strip()
|
||||
# Detail Obat
|
||||
elif field.startswith("a2") and len(field) > 2: # Nama Obat (mis: Cefoxitin)
|
||||
curr_ab_name = field[2:].strip()
|
||||
elif field.startswith("a3") and len(field) > 2: # MIC (mis: >=4)
|
||||
curr_ab_mic = field[2:].strip()
|
||||
elif field.startswith("a4") and len(field) > 2: # Interpretasi (R/S/I)
|
||||
curr_ab_int = field[2:].strip()
|
||||
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
|
||||
if current_ab_name:
|
||||
ab_str = f"{current_ab_name} {current_ab_mic} ({current_ab_int})"
|
||||
antibiotics.append(ab_str)
|
||||
# Jangan lupa simpan obat terakhir yang tersisa di buffer
|
||||
if curr_ab_name:
|
||||
ab_str = f"{curr_ab_name} {curr_ab_mic} ({curr_ab_int})"
|
||||
antibiotics.append(ab_str)
|
||||
|
||||
# --- LANGKAH 3: FORMAT FINAL & SAVE ---
|
||||
# Kita hanya memproses jika tipe pesan adalah 'mtrsl' (Result) dan ada Sample ID
|
||||
if msg_type == 'mtrsl' and sample_id:
|
||||
# --- 4. FORMAT FINAL STRING ---
|
||||
# Format: "Staphylococcus hominis | Cefoxitin >=4 (R), Gentamicin 4 (S)..."
|
||||
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()
|
||||
else:
|
||||
if msg_type != 'mtrsl':
|
||||
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]}...")
|
||||
logging.warning(f"[{port_name}] Pesan diabaikan (Tanpa Sample ID): {clean_data[:30]}...")
|
||||
|
||||
except Exception as 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()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def create_vitek_order_message(order):
|
||||
"""
|
||||
Membuat Frame Order Vitek sesuai Manual Ref 514937.
|
||||
|
||||
Reference in New Issue
Block a user