193 lines
5.3 KiB
Go
Executable File
193 lines
5.3 KiB
Go
Executable File
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
)
|
|
|
|
const sophiaPatientID = 1
|
|
|
|
type Response struct {
|
|
OrderName string `json:"orderName"`
|
|
Key string `json:"key"`
|
|
Results []Result `json:"results"`
|
|
}
|
|
|
|
type Result struct {
|
|
OrderMetadata OrderMeta `json:"orderMetadata"`
|
|
ResultComponents []Component `json:"resultComponents"`
|
|
IsAbnormal bool `json:"isAbnormal"`
|
|
}
|
|
|
|
type OrderMeta struct {
|
|
OrderProviderName string `json:"orderProviderName"`
|
|
AuthorizingProviderName string `json:"authorizingProviderName"`
|
|
PrioritizedInstantISO string `json:"prioritizedInstantISO"`
|
|
CollectionTimestampsDisplay string `json:"collectionTimestampsDisplay"`
|
|
ResultStatus string `json:"resultStatus"`
|
|
ResultType string `json:"resultType"`
|
|
ResultingLab Lab `json:"resultingLab"`
|
|
AssociatedDiagnoses []string `json:"associatedDiagnoses"`
|
|
SpecimensDisplay string `json:"specimensDisplay"`
|
|
}
|
|
|
|
type Lab struct {
|
|
Name string `json:"name"`
|
|
Address []string `json:"address"`
|
|
CliaNumber string `json:"cliaNumber"`
|
|
}
|
|
|
|
type Component struct {
|
|
ComponentInfo CompInfo `json:"componentInfo"`
|
|
ComponentResultInfo CompResultInfo `json:"componentResultInfo"`
|
|
ComponentComments CompComments `json:"componentComments"`
|
|
}
|
|
|
|
type CompInfo struct {
|
|
Name string `json:"name"`
|
|
CommonName string `json:"commonName"`
|
|
Units string `json:"units"`
|
|
}
|
|
|
|
type CompResultInfo struct {
|
|
Value string `json:"value"`
|
|
NumericValue *float64 `json:"numericValue,omitempty"`
|
|
ReferenceRange RefRange `json:"referenceRange"`
|
|
AbnormalFlag string `json:"abnormalFlagCategoryValue"`
|
|
}
|
|
|
|
type RefRange struct {
|
|
Low *float64 `json:"low,omitempty"`
|
|
High *float64 `json:"high,omitempty"`
|
|
FormattedReferenceRange string `json:"formattedReferenceRange"`
|
|
}
|
|
|
|
type CompComments struct {
|
|
HasContent bool `json:"hasContent"`
|
|
ContentAsString string `json:"contentAsString"`
|
|
}
|
|
|
|
func main() {
|
|
dbPath := "labs.db"
|
|
if len(os.Args) > 1 {
|
|
dbPath = os.Args[1]
|
|
}
|
|
|
|
db, err := sql.Open("sqlite3", dbPath)
|
|
if err != nil {
|
|
fmt.Printf("Failed to open %s: %v\n", dbPath, err)
|
|
os.Exit(1)
|
|
}
|
|
defer db.Close()
|
|
|
|
files, _ := filepath.Glob("output/*.json")
|
|
fmt.Printf("Processing %d files\n", len(files))
|
|
|
|
labCount, skipCount, testCount := 0, 0, 0
|
|
|
|
for _, f := range files {
|
|
data, _ := os.ReadFile(f)
|
|
var resp Response
|
|
if err := json.Unmarshal(data, &resp); err != nil {
|
|
continue
|
|
}
|
|
if len(resp.Results) == 0 {
|
|
continue
|
|
}
|
|
|
|
r := resp.Results[0]
|
|
if r.OrderMetadata.ResultType != "LAB" {
|
|
skipCount++
|
|
continue
|
|
}
|
|
|
|
provider := r.OrderMetadata.OrderProviderName
|
|
if provider == "" {
|
|
provider = r.OrderMetadata.AuthorizingProviderName
|
|
}
|
|
|
|
labAddr := ""
|
|
if len(r.OrderMetadata.ResultingLab.Address) > 0 {
|
|
for i, a := range r.OrderMetadata.ResultingLab.Address {
|
|
if i > 0 {
|
|
labAddr += ", "
|
|
}
|
|
labAddr += a
|
|
}
|
|
}
|
|
|
|
diagnoses := ""
|
|
for i, d := range r.OrderMetadata.AssociatedDiagnoses {
|
|
if i > 0 {
|
|
diagnoses += "; "
|
|
}
|
|
diagnoses += d
|
|
}
|
|
|
|
isAbnormal := 0
|
|
if r.IsAbnormal {
|
|
isAbnormal = 1
|
|
}
|
|
|
|
res, err := db.Exec(`INSERT OR IGNORE INTO lab_orders
|
|
(patient_id, order_name, order_key, collection_date, provider, lab_name, lab_address, lab_clia, specimen, status, is_abnormal, diagnoses)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
sophiaPatientID, resp.OrderName, resp.Key, r.OrderMetadata.PrioritizedInstantISO, provider,
|
|
r.OrderMetadata.ResultingLab.Name, labAddr, r.OrderMetadata.ResultingLab.CliaNumber,
|
|
r.OrderMetadata.SpecimensDisplay, r.OrderMetadata.ResultStatus, isAbnormal, diagnoses)
|
|
|
|
if err != nil {
|
|
fmt.Printf("err %s: %v\n", f, err)
|
|
continue
|
|
}
|
|
|
|
rowsAffected, _ := res.RowsAffected()
|
|
var orderID int64
|
|
if rowsAffected == 0 {
|
|
// Already exists, get existing ID
|
|
row := db.QueryRow(`SELECT id FROM lab_orders WHERE order_key = ?`, resp.Key)
|
|
if err := row.Scan(&orderID); err != nil {
|
|
fmt.Printf("err getting existing order %s: %v\n", f, err)
|
|
continue
|
|
}
|
|
} else {
|
|
orderID, _ = res.LastInsertId()
|
|
labCount++
|
|
}
|
|
|
|
for _, c := range r.ResultComponents {
|
|
var numVal, refLow, refHigh *float64
|
|
if c.ComponentResultInfo.NumericValue != nil {
|
|
numVal = c.ComponentResultInfo.NumericValue
|
|
}
|
|
if c.ComponentResultInfo.ReferenceRange.Low != nil {
|
|
refLow = c.ComponentResultInfo.ReferenceRange.Low
|
|
}
|
|
if c.ComponentResultInfo.ReferenceRange.High != nil {
|
|
refHigh = c.ComponentResultInfo.ReferenceRange.High
|
|
}
|
|
|
|
comments := ""
|
|
if c.ComponentComments.HasContent {
|
|
comments = c.ComponentComments.ContentAsString
|
|
}
|
|
|
|
db.Exec(`INSERT INTO lab_tests
|
|
(order_id, name, common_name, value, numeric_value, units, ref_low, ref_high, ref_range_display, abnormal_flag, comments)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
orderID, c.ComponentInfo.Name, c.ComponentInfo.CommonName,
|
|
c.ComponentResultInfo.Value, numVal, c.ComponentInfo.Units,
|
|
refLow, refHigh, c.ComponentResultInfo.ReferenceRange.FormattedReferenceRange,
|
|
c.ComponentResultInfo.AbnormalFlag, comments)
|
|
testCount++
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Done: %d lab orders, %d tests (%d non-lab skipped)\n", labCount, testCount, skipCount)
|
|
}
|