Expand GenXpert assay mapping and use assay-based responses
This commit is contained in:
+90
-46
@@ -100,13 +100,48 @@ GENEXPERT_TEST_MAPPING = {
|
||||
"TCM TB": "MTB-RIF", # Xpert MTB-RIF Assay G4 Version 6
|
||||
"TCM TB ULTRA": "MTB-RIF_ULTRA2", # Xpert MTB-RIF Ultra Version 4
|
||||
"TCM TB XDR": "MTB-XDR", # Xpert MTB-XDR Version 1
|
||||
"COVID-19": "COV-2 2", # Xpert Xpress SARS-CoV-2 Version 2
|
||||
"HCV VL": "HCV", # Xpert HCV Viral Load Version 1
|
||||
"COVID-19": "COV-2 2", # Xpert Xpress SARS-CoV-2 Version 2
|
||||
"17.3.1 TCM COVID-19": "COV-2 2", # Xpert Xpress SARS-CoV-2 Version 2
|
||||
"17.3.2 PCR COVID-19": "COV-2 2", # Xpert Xpress SARS-CoV-2 Version 2
|
||||
"E.2.5 HCV TCM": "HCV",
|
||||
"18.1.1 TCM HCV": "HCV",
|
||||
"18.1.2 TCM HIV VIRAL LOAD": "HIV-1_VL",
|
||||
"18.1.4 TCM HPV": "HCV",
|
||||
"7.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-RIF",
|
||||
"5.3.8 KULTUR TBC MGIT (AUTOMATIC)": "MTB-RIF",
|
||||
"5.3.7 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"3.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL) ": "MTB-XDR",
|
||||
"2.3.7 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"1.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"1.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"15.2.1 KULTUR TB MEDIA LJ": "MTB-XDR",
|
||||
"8.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"9.3.5 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"9.3.6 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"12.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"H.2.5 PEMERIKSAAN KULTUR MYCROBACTERIUM TBC": "MTB-XDR",
|
||||
"12.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"11.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"10.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"10.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"3.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"15.2.2 KULTUR TB MEDIA MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"11.3.7 KULTUR TBC MGIT (AUTOMATIC)": "MTB-XDR",
|
||||
"8.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"7.3.6 KULTUR TBC MEDIA LJ (KONVENSIONAL)": "MTB-XDR",
|
||||
"2.3.10 TCM CLAMIDIA TRACHOMATIS / NEISSERIA GONORRHOE": "MTB-RIF",
|
||||
"12.3.8 TCM TB (GENE EXPERT)": "MTB-RIF",
|
||||
"15.2.3 TCM TB (GENE EXPERT)": "MTB-RIF",
|
||||
"2.3.9 TCM GENE EXPERT": "MTB-RIF",
|
||||
"3.3.8 TCM GENE EXPERT": "MTB-RIF",
|
||||
"3.3.9 TCM MYCOBACTERIUM TUBERCULOSIS": "MTB-RIF",
|
||||
"5.3.9 TCM TBC (GENE EXPERT)": "MTB-RIF",
|
||||
"7.3.8 TCM TBC (GENE EXPERT)": "MTB-RIF",
|
||||
"8.3.8 TCM TBC (GENE EXPERT)": "MTB-RIF",
|
||||
"10.3.8 TCM TBC (GENE EXPERT)": "MTB-RIF",
|
||||
"11.3.9 TCM TB (GENE EXPERT)": "MTB-RIF",
|
||||
|
||||
# Mapping untuk IP 10.10.120.74 (Khusus)
|
||||
# Catatan: Di dokumen Anda tertulis Assay 'HBV' tapi kodenya 'HCV'.
|
||||
# Pastikan ini benar, atau sesuaikan jika itu typo di dokumen.
|
||||
"HBV VL": "HCV",
|
||||
}
|
||||
GENEXPERT_IP_CAPABILITIES = {
|
||||
"10.10.120.75": ["MTB-RIF", "MTB-RIF_ULTRA2", "MTB-XDR", "HIV-1_VL", "COV-2 2"],
|
||||
@@ -278,35 +313,32 @@ def parse_genexpert_qpd(qpd_segment):
|
||||
"param_2": param_2,
|
||||
}
|
||||
|
||||
def resolve_genexpert_test_code(order, ip_addr=None):
|
||||
def resolve_genexpert_assay(order, ip_addr=None):
|
||||
assay_name = str(getattr(order, "tes", "") or "").strip()
|
||||
test_code = GENEXPERT_TEST_MAPPING.get(assay_name)
|
||||
supported_codes = None
|
||||
if ip_addr is not None:
|
||||
supported_codes = GENEXPERT_IP_CAPABILITIES.get(str(ip_addr or "").strip(), [])
|
||||
specimen_code = str(getattr(order, "kd_spesimen", "") or "").strip()
|
||||
assay_code = GENEXPERT_TEST_MAPPING.get(assay_name)
|
||||
assay_source = "mapping:tes"
|
||||
|
||||
if not test_code:
|
||||
if not assay_code and specimen_code:
|
||||
assay_code = specimen_code
|
||||
assay_source = "fallback:kd_spesimen"
|
||||
|
||||
supported_codes = GENEXPERT_IP_CAPABILITIES.get(str(ip_addr or "").strip(), []) if ip_addr else []
|
||||
capability_match = True if not supported_codes else assay_code in supported_codes
|
||||
|
||||
if not assay_code:
|
||||
print(
|
||||
f"[GENEXPERT] Skip rnoreg={getattr(order, 'rnoreg', '')} di {ip_addr}: "
|
||||
f"mapping test code tidak ditemukan untuk tes='{assay_name}'"
|
||||
f"[GENEXPERT-DEBUG] rnoreg={getattr(order, 'rnoreg', '')}, ip={ip_addr}, "
|
||||
f"tes='{assay_name}', kd_spesimen='{specimen_code}', assay_code=EMPTY"
|
||||
)
|
||||
return None
|
||||
return None, "none", capability_match
|
||||
|
||||
if supported_codes is not None and supported_codes and test_code not in supported_codes:
|
||||
print(
|
||||
f"[GENEXPERT] Skip rnoreg={getattr(order, 'rnoreg', '')} di {ip_addr}: "
|
||||
f"test_code={test_code} tidak didukung alat"
|
||||
)
|
||||
return None
|
||||
|
||||
if supported_codes is not None and not supported_codes:
|
||||
print(
|
||||
f"[GENEXPERT] Skip rnoreg={getattr(order, 'rnoreg', '')} di {ip_addr}: "
|
||||
"capability IP belum dikonfigurasi"
|
||||
)
|
||||
return None
|
||||
|
||||
return test_code
|
||||
print(
|
||||
f"[GENEXPERT-DEBUG] rnoreg={getattr(order, 'rnoreg', '')}, ip={ip_addr}, "
|
||||
f"tes='{assay_name}', kd_spesimen='{specimen_code}', assay_code='{assay_code}', "
|
||||
f"assay_source={assay_source}, capability_match={capability_match}"
|
||||
)
|
||||
return assay_code, assay_source, capability_match
|
||||
|
||||
def get_genexpert_query_orders(ip_addr, hl7_msg):
|
||||
flag = get_flag_by_device(ip_addr)
|
||||
@@ -328,21 +360,24 @@ def get_genexpert_query_orders(ip_addr, hl7_msg):
|
||||
(flag_attr == False) | (flag_attr == None)
|
||||
).order_by(PaslabOrder.urut.asc()).all()
|
||||
|
||||
supported_codes = GENEXPERT_IP_CAPABILITIES.get(str(ip_addr or "").strip(), [])
|
||||
if not supported_codes:
|
||||
print(f"[GENEXPERT] Tidak ada capability test_code untuk IP {ip_addr}.")
|
||||
return []
|
||||
|
||||
requested_sample_id = (param_2 or param_1).strip() if (param_2 or param_1) else ""
|
||||
if requested_sample_id and requested_sample_id.upper() != "ALL":
|
||||
for order in base_orders:
|
||||
if str(order.rnoreg or "").strip() != requested_sample_id:
|
||||
continue
|
||||
assay_code, _, _ = resolve_genexpert_assay(order, ip_addr)
|
||||
if not assay_code:
|
||||
return []
|
||||
return [order]
|
||||
print(f"[GENEXPERT] Tidak ada order untuk sample_id={requested_sample_id} di {ip_addr}")
|
||||
return []
|
||||
|
||||
return base_orders[:1]
|
||||
for order in base_orders:
|
||||
assay_code, _, _ = resolve_genexpert_assay(order, ip_addr)
|
||||
if assay_code:
|
||||
return [order]
|
||||
print(f"[GENEXPERT] Tidak ada order dengan assay valid untuk IP {ip_addr}")
|
||||
return []
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
@@ -373,7 +408,6 @@ def create_genexpert_rsp_z02_response(orders, incoming_hl7, ip_addr=None):
|
||||
query_tag = qpd.get("query_tag") or (extract_msg_control_id(incoming_hl7) or "UNKNOWN")
|
||||
query_name = qpd.get("query_name") or "Z03^HOST QUERY"
|
||||
resp_control_id = f"RSP{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}"
|
||||
supported_codes = GENEXPERT_IP_CAPABILITIES.get(str(ip_addr or "").strip(), [])
|
||||
|
||||
msh = build_genexpert_response_msh("RSP^Z02", incoming_hl7, resp_control_id)
|
||||
msa = f"MSA|AA|{query_tag}"
|
||||
@@ -386,17 +420,22 @@ def create_genexpert_rsp_z02_response(orders, incoming_hl7, ip_addr=None):
|
||||
patient_id = str(order.norm or order.rnoreg or "").strip()
|
||||
sample_id = str(order.rnoreg or "").strip()
|
||||
order_ts = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
|
||||
assay_code, assay_source, capability_match = resolve_genexpert_assay(order, ip_addr)
|
||||
if not assay_code:
|
||||
print(f"[GENEXPERT] Payload order dilewati rnoreg={sample_id} karena assay kosong.")
|
||||
continue
|
||||
|
||||
print(
|
||||
f"[GENEXPERT-DEBUG] Build RSP rnoreg={sample_id}, ip={ip_addr}, "
|
||||
f"patient_id={patient_id}, assay_code={assay_code}, assay_source={assay_source}, "
|
||||
f"capability_match={capability_match}, query_name='{query_name}', query_tag='{query_tag}'"
|
||||
)
|
||||
|
||||
segments.append(f"PID|{patient_idx}||{patient_id}")
|
||||
|
||||
test_codes = supported_codes if supported_codes else []
|
||||
if not test_codes:
|
||||
print(f"[GENEXPERT] Tidak ada test_code capability untuk payload ke {ip_addr}")
|
||||
|
||||
for order_idx, test_code in enumerate(test_codes, start=1):
|
||||
segments.append(f"ORC|NW|{order_idx}|||||||{order_ts}")
|
||||
segments.append(f"OBR|{order_idx}|||{test_code}|||||||A")
|
||||
segments.append("TQ1|||||||||R")
|
||||
segments.append(f"SPM|{order_idx}|{sample_id}^||ORH|||||||P")
|
||||
segments.append(f"ORC|NW|1|||||||{order_ts}")
|
||||
segments.append(f"OBR|1|||{assay_code}|||||||A")
|
||||
segments.append("TQ1|||||||||R")
|
||||
segments.append(f"SPM|1|{sample_id}^||ORH|||||||P")
|
||||
|
||||
return "\r".join(segments) + "\r"
|
||||
|
||||
@@ -411,6 +450,11 @@ def send_all_orders(conn, ip_addr, hl7_msg, msg_id):
|
||||
conn.sendall(f"\x0b{rsp}\x1c\r".encode('utf-8'))
|
||||
return
|
||||
|
||||
qpd_segment = extract_segment(hl7_msg, "QPD")
|
||||
print(
|
||||
f"[GENEXPERT-DEBUG] QBP diproses untuk ip={ip_addr}, msg_id={msg_id}, "
|
||||
f"qpd='{qpd_segment}', selected_rnoreg={[str(order.rnoreg or '').strip() for order in orders]}"
|
||||
)
|
||||
print(f"[GENEXPERT] Mengirim {len(orders)} order ke {ip_addr}")
|
||||
rsp = create_genexpert_rsp_z02_response(orders, hl7_msg, ip_addr=ip_addr)
|
||||
mllp = f"\x0b{rsp}\x1c\r"
|
||||
|
||||
Reference in New Issue
Block a user