06 · HIS 整合對映
醫院 HIS 已有一套非 FHIR 的事件介面。本章定義 EMR 整合層如何把 FHIR 資源翻成這些事件,以及回應如何落回 FHIR。
臨床端永遠不碰本章的任何欄位。 這些欄位在 FHIR 資源上只以 Identifier 或 extension[hisTransmissionEvent] 形式出現。
6.1 事件總覽
| HIS 事件 | 方向 | 觸發 | FHIR 對應 |
|---|---|---|---|
PrescriptionCreated |
EMR → HIS | POST /MedicationRequest/{id}/$submit |
MedicationRequest |
PrescriptionCancelled |
EMR → HIS | 醫囑取消 | MedicationRequest.status = cancelled |
MedicationChangeStatus |
HIS → EMR | HIS 端狀態變更 | 只寫 extension[hisTransmissionEvent] |
ServiceRequestCreated |
EMR → HIS | $submit |
ServiceRequest |
ServiceRequestUpdated |
EMR → HIS | 服務項目異動 | ServiceRequest |
ServiceRequestCancelled |
EMR → HIS | 服務取消 | ServiceRequest.status = revoked |
| 檢驗結果回報 | HIS → EMR | 報告產出 | DiagnosticReport + Observation + Specimen |
CoverageUpdated |
HIS → EMR | 保險異動 | Coverage |
6.2 PrescriptionCreated
送出對映
| FHIR | HIS 欄位 | 取得 | 約束 |
|---|---|---|---|
Encounter.identifier |
archiveId |
H | HIS 當前存檔代碼。不可拿病歷號或舊科別 archiveId 代替 |
MedicationRequest.authoredOn |
prescriptionTime |
M | 格式 yyyyMMddHHmm。院方時區須明確(Q-01) |
MedicationRequest.note |
advice |
M | 醫師叮囑,可空 |
supportingInformation → Composition P 段 |
progressNote |
P | 取已確認版本的治療進度。空白阻擋送出 |
extension[emergencyCart] |
stockCode |
M | 開立至急救車時條件必填;常規預備處方留空 |
medicationCodeableConcept.coding[his-medication] |
medications[]. 藥品碼 |
M | 必須來自已同步目錄 |
dosageInstruction.timing(四時段) |
medications[].morning/noon/afternoon/evening |
M | 單位由藥品/調劑目錄核對,各時段不可混用不同單位 |
| (計算) | medications[].quantity |
C | 任一時段有值時 quantity = morning+noon+afternoon+evening |
dispenseRequest.expectedSupplyDuration |
medications[].expectedSupplyDuration |
M | 不得把天數自動乘入四時段 quantity 公式 |
dispenseRequest.performer |
medications[].dispenseStockCode |
M | 無已同步代碼 → 阻擋送出 |
extension[consultationRequired] |
medications[].medicationConsultationRequest |
C | 星號藥 true;非星號明確 false。不省略、不以 null 代 false |
dosageInstruction.timing.repeat |
medications[].repeatPeriod |
M | D1 無完整代碼字典,UI 選單未定(Q-05) |
阻擋條件(送出前檢查)
| 編號 | 條件 | 錯誤碼 |
|---|---|---|
| BR-INT-001 | progressNote 為空 |
PROGRESS-NOTE-REQUIRED |
| BR-INT-002 | 任一藥品缺 dispenseStockCode 對照 |
DISPENSE-STOCK-UNMAPPED |
| BR-INT-003 | medicationConsultationRequest 為 null |
TRISTATE-NOT-RESOLVED |
| BR-INT-005 | 四時段單位不一致 | DOSE-UNIT-INCONSISTENT |
| BR-INT-006 | archiveId 非本次就醫的當前值 |
ARCHIVE-ID-STALE |
阻擋一律在 $submit 回 422,醫囑維持已簽未送,不進入 sent。
回應落回
data.hisPrescriptionNumber → MedicationRequest.identifier[system=…/his-prescription-number]
data.medications[].medicationRequestId → MedicationRequest.identifier[system=…/his-medication-request-id]
error / message / status → extension[hisTransmissionEvent]
medicationRequestId 必須儲存,否則後續狀態回推與對帳無法配對。
回應的 medications[] 要與送出行逐行對帳:行數不符或有行對不上 → 標記 hisTransmissionStatus=unknown,產生人工處理 Task,不自動重送。
取消
PrescriptionCancelled:
encounterNumber ← Encounter.identifier
hisPrescriptionNumber ← MedicationRequest.identifier[his-prescription-number]
requester ← 執行取消的醫師帳號(從權杖,非客戶端指定)
hisPrescriptionNumber是整張 HIS 處方的號碼,不是medicationRequestId。
送錯會取消到別張處方。整合層必須驗證這個 identifier 的 system 正確(BR-INT-007),不接受任意字串。
6.3 ServiceRequestCreated / Updated / Cancelled
送出對映
| FHIR | HIS 欄位 | 取得 | TDL | 約束 |
|---|---|---|---|---|
requester.extension[department] |
requestRoomCode |
H | — | 當前開立病房代碼 |
note.text |
note |
M | — | 臨床備註 |
bodySite |
services[].bodySite |
M | TDL.1166 | 不混用檢體類型 |
specimen → Specimen.type |
services[].specimen |
M | TDL.1165 | 查不到正式字典時不用自由文字冒充代碼 |
extension[useContrast] |
services[].useContrastEnhanced |
M | — | 未選不等於 false |
extension[isConsumable] |
services[].isConsumable |
M | — | 必須明確 true/false |
extension[sameSurgicalTeam] |
services[].isSameSurgicalTeam |
M | — | true/false/null 三態不可合併 |
locationReference |
services[].performingPlaceCode |
M | — | 有病房優先病房,否則科室。查無對照時阻擋 |
Coverage → HIS doituong_id |
services[].patientType |
H | — | 不得送範例字串 BHYT;CoverageUpdated 沒有此欄 |
| (HIS 字典) | services[].priceType |
H | — | HIS loaigia_id。查不到價格類型字典 → 缺值阻擋 |
priority |
severity(僅建立) |
M | TDL.1157 | 建立用 1 正常/2 急/3 特急;修改時不送(Q-05) |
阻擋條件
| 編號 | 條件 | 錯誤碼 |
|---|---|---|
| BR-INT-008 | performingPlaceCode 查無對照 |
PERFORMING-PLACE-UNMAPPED |
| BR-INT-009 | priceType 缺值 |
PRICE-TYPE-MISSING |
| BR-INT-010 | specimen 無正式字典代碼 |
SPECIMEN-CODE-UNMAPPED |
| BR-INT-011 | isConsumable / useContrastEnhanced 未明確給值 |
TRISTATE-NOT-RESOLVED |
| BR-INT-012 | patientType 為字面值 BHYT 或非 doituong_id |
PATIENT-TYPE-INVALID |
修改的兩種語義
ServiceRequestUpdated 的 services[].serviceRequestNumber 決定行為:
| 帶不帶 | HIS 行為 | FHIR 表達 |
|---|---|---|
| 帶舊詳細行碼 | HIS 取消舊服務並新增新服務 | 舊 ServiceRequest.status=revoked,建新的 ServiceRequest replaces 舊的 |
| 不帶 | 純新增 | 新建 ServiceRequest |
orderNumber 必須填原需求單號,不得填詳細行碼(BR-INT-013)。這是兩個不同層級的識別碼:
orderNumber= 整張需求單serviceRequestNumber= 單內的一行
取消
ipAddress 與 computerName 為取得=C:由伺服器從連線取得,不接受客戶端提供,也不暴露權杖(BR-INT-014)。
6.4 MedicationChangeStatus(HIS → EMR)
HIS status |
意義 |
|---|---|
| 1 | 新開立 |
| 2 | 審核 |
| 3 | 匯總領取 |
| 4 | 發放 |
| 5 | 急救車補充 |
這五個值沒有一個代表 eMAR 已給藥。
處理規則(BR-INT-004):
- 只寫入
MedicationRequest.extension[hisTransmissionEvent],附changeStatusTime。 - 絕不建立或修改
MedicationAdministration。 - 絕不改變
MedicationRequest.status(臨床狀態軸)。 - 較舊的
changeStatusTime不覆蓋較新的狀態(規格標【推論】,需 FPT 確認事件是否保證有序)。
6.5 檢驗結果回報(HIS → EMR)
HIS 送回報告時,整合層以 transaction Bundle 一次落地,確保報告與其逐項數值同時可見:
Bundle(transaction)
├─ Specimen (upsert by TDL.1246 檢體編號)
├─ Observation ×N (每個檢驗指標一筆)
└─ DiagnosticReport(result → 上述 Observation)
落地規則:
| 來源 | 規則 |
|---|---|
| 旗標 | 有旗標才填 Observation.interpretation。無旗標不填,不推定正常 |
| 缺值 | 填 dataAbsentReason,不填 value[x],不送 0 |
| 指標代碼 | Q-02 未定前,Observation.code 只帶院內/來源碼,不硬指派 LOINC |
| 重發 | 新版本 DiagnosticReport.status = corrected,舊版保留 |
| 無關聯醫囑 | basedOn 留空並在 UI 顯示「未提供來源醫囑關聯」。不按名稱猜測配對 |
最後一條來自原型原文:「來源未提供醫囑關聯,不按名稱猜測配對」。名稱相近就自動綁定會產生錯誤的醫囑-結果對應。
6.6 冪等與重試
冪等鍵
outbound_request.idempotency_key(取得=C)由伺服器產生:
idempotency_key = sha256(encounterNumber ‖ resourceType ‖ resourceId ‖ versionId ‖ eventType)
- 同一資源同一版本重送 → 整合層回傳首次的結果,不重打 HIS。
- 資源版本改變 → 新的鍵,視為新事件。
重試
| HIS 回應 | 動作 |
|---|---|
2xx + error=false |
落回識別碼,hisTransmissionStatus=accepted |
2xx + error=true |
rejected,保留 message,不重試 |
| 連線失敗 | 指數退避重試 ≤3 次,同一冪等鍵 |
| 逾時無回應 | hisTransmissionStatus=unknown,停止重試,產生人工查明 Task |
unknown 之後禁止自動重送(BR-ORD-007)。重送可能造成重複處方;必須由人確認 HIS 端的實際結果。
部分成功(Q-06)
ServiceRequestCreated 的回應是 data.services[] 陣列,但規格註明「未明確部分成功契約」。在 FPT 確認前,整合層採保守處理:
- 逐行對帳;行數或行碼對不上即視為整體結果不確定。
- 已取得
serviceRequestNumber的行 →accepted。 - 未取得的行 →
unknown,不重送,產生人工處理Task。 - 不因為部分行成功就把整張標成成功。
6.7 整合層邊界
整合層是獨立元件,不是 FHIR server 的一部分:
- 對 FHIR server 用
system/scope 的服務帳號。 - 所有寫入走標準 FHIR 互動(
update+If-Match),不繞過業務規則。 - 例外:HIS 唯讀資源(
Patient、Encounter、DiagnosticReport…)只有整合服務帳號能寫;臨床使用者帳號仍被READ-ONLY-SOURCE擋下。 - 整合層的私有狀態(
outbound_request、重試次數、原始 payload)存在自己的資料庫,不進 FHIR 資源。