update
This commit is contained in:
+52
-13
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user