This commit is contained in:
Dwi Swandhana
2026-03-03 11:41:15 +07:00
parent d59f1a9807
commit e0ac8dd30d
+52 -13
View File
@@ -1312,6 +1312,39 @@ def split_patient_name(full_name):
last_name = (last_name or "NAME").upper()[:20]
return first_name, last_name
def sanitize_astm_field(value, *, uppercase=False, max_len=None, allow_component_sep=False):
"""
Sanitasi field agar aman untuk ASTM:
- Buang karakter NULL/control (termasuk CR/LF)
- Hilangkan delimiter ASTM pada field biasa
- Trim dan optional uppercase/truncate
"""
if value is None:
text = ""
else:
text = str(value)
# Hilangkan NULL byte yang sering muncul dari CHAR/VARCHAR bermasalah.
text = text.replace("\x00", "")
# Buang karakter kontrol non-printable.
text = re.sub(r"[\x00-\x1f\x7f]", " ", text)
if allow_component_sep:
text = text.replace("|", " ")
else:
text = text.replace("|", " ").replace("^", " ")
text = re.sub(r"\s+", " ", text).strip()
# ASTM payload dikirim dengan latin-1; karakter di luar rentang ini diganti aman.
text = text.encode("latin-1", errors="replace").decode("latin-1")
if uppercase:
text = text.upper()
if max_len is not None:
text = text[:max_len]
return text
def create_vitek_order_message(order):
"""
Membuat Frame Order Vitek sesuai Manual Ref 514937.
@@ -1325,7 +1358,8 @@ def create_vitek_order_message(order):
p_name = f"{last_name}^{first_name}"
specimen = str(order.kd_spesimen).upper() if order.kd_spesimen else "BLOOD"
room = str(getattr(order, 'ruangan', "") or "RSSA MALANG").strip().upper()
room = room.replace("|", " ").replace("^", " ")[:30]
# VITEK: Patient Location Code menggunakan tag "pl" (maks 40 char pada spec yang dipakai)
room = room.replace("|", " ").replace("^", " ")[:40]
now = datetime.datetime.now()
date_str = now.strftime("%m/%d/%Y")
@@ -1336,7 +1370,7 @@ def create_vitek_order_message(order):
content_body = (
f"mtmpr|pi{pid}|pn{p_name}"
f"|si|ss{specimen}"
f"|lo{room}"
f"|pl{room}"
f"|s1{date_str}|s2{time_str}"
f"|ci{sid}|t11|zz"
)
@@ -1688,27 +1722,32 @@ def create_astm_order_message(order):
Menghindari pergeseran kolom (shifting error).
"""
# --- 1. PERSIAPAN DATA ---
pid = str(order.norm).strip() if order.norm else ""
sid = str(order.rnoreg).strip() if order.rnoreg else ""
pid = sanitize_astm_field(order.norm, max_len=32)
sid = sanitize_astm_field(order.rnoreg, max_len=32)
# Nama pasien dipisah agar mengikuti format ASTM: Last^First
first_name, last_name = split_patient_name(order.nama)
first_name, last_name = split_patient_name(sanitize_astm_field(order.nama, max_len=80))
first_name = sanitize_astm_field(first_name, uppercase=True, max_len=20)
last_name = sanitize_astm_field(last_name, uppercase=True, max_len=20)
p_name = f"{last_name}^{first_name}"
sex = "M" if str(order.rjenis).upper().startswith("L") else "F"
sex_raw = sanitize_astm_field(order.rjenis, uppercase=True, max_len=10)
sex = "M" if sex_raw.startswith("L") else "F"
# Lokasi / Ruangan (Field 26)
location = getattr(order, 'ruangan', "RSSA Malang")
if not location: location = "RSSA Malang"
# Lokasi / Ruangan (Field 26) sebaiknya berupa kode singkat agar tidak ditrunkasi LIS.
raw_location = sanitize_astm_field(getattr(order, 'ruangan', "UT"), uppercase=True, max_len=40)
location = re.sub(r"[^A-Z0-9]", "", raw_location)[:10]
if not location:
location = "UT"
# Diagnosis (Clinical Info - Field 14 di ASTM standar atau 13 di beberapa varian)
# Kita pasang di Index 13 (Field 14) agar aman
diagnosis = getattr(order, 'diagnosa', "Unspecified")
diagnosis = sanitize_astm_field(getattr(order, 'diagnosa', "Unspecified"), max_len=60)
if not diagnosis: diagnosis = "Unspecified"
# Specimen Info (Field 16)
# Format: SpecimenType^BodySite^Container^Condition
specimen_type = str(order.kd_spesimen).upper() if order.kd_spesimen else "BLOOD"
specimen_type = sanitize_astm_field(order.kd_spesimen, uppercase=True, max_len=20) if order.kd_spesimen else "BLOOD"
body_site = "VENA" # Site
condition = "Baik" # Condition
condition = "BAIK" # Condition
specimen_field = f"{specimen_type}^{body_site}^^{condition}"
# --- 2. KONSTRUKSI RECORD DENGAN INDEX PASTI ---
@@ -1739,7 +1778,7 @@ def create_astm_order_message(order):
o_rec[1] = "1" # Field 2
o_rec[2] = sid # Field 3: Sample ID
o_rec[3] = "" # Field 4: Instrument Specimen ID
o_rec[4] = "^^^BD_BACTEC" # Field 5: Universal Test ID
o_rec[4] = "^^^" # Field 5: Universal Test ID
o_rec[5] = "R" # Field 6: Priority
# ... Field 7-11 ...
o_rec[11] = "A" # Field 12: Action Code (A=Add, N=New) (Index 11)