Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conditions Endpoint #2934

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions containers/ecr-viewer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ services:
- AZURE_CONTAINER_NAME=${AZURE_CONTAINER_NAME:-ecr-viewer-files}
- NEXT_PUBLIC_NON_INTEGRATED_VIEWER=${NEXT_PUBLIC_NON_INTEGRATED_VIEWER:-false}
- NEXT_PUBLIC_BASEPATH=${NEXT_PUBLIC_BASEPATH:-/ecr-viewer}
- METADATA_DATABASE_SCHEMA=${METADATA_DATABASE_SCHEMA:-core}
- SQL_SERVER_USER=${SQL_SERVER_USER}
- SQL_SERVER_PASSWORD=${SQL_SERVER_PASSWORD}
- SQL_SERVER_HOST=${SQL_SERVER_HOST}
JNygaard-Skylight marked this conversation as resolved.
Show resolved Hide resolved
profiles:
- ecr-viewer

Expand Down
10 changes: 9 additions & 1 deletion containers/ecr-viewer/seed-scripts/sql/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

/opt/mssql/bin/sqlservr &

# Wait for SQL Server to start up
until /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $MSSQL_SA_PASSWORD -Q "SELECT 1" -C &>/dev/null; do
echo "Waiting for SQL Server to start..."
sleep 1
done
echo "SQL Server ready."

# Run your SQL script
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P $MSSQL_SA_PASSWORD -d master -i /var/opt/mssql/scripts/extended.sql -C

wait
wait
86 changes: 86 additions & 0 deletions containers/ecr-viewer/seed-scripts/sql/extended.sql
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of copying this file here, can we update the docker-compose to copy the real one? I believe you'll need to update test_type_system and test_result_qualitative in that one too.

- ./sql/extended.sql:/var/opt/mssql/scripts/extended.sql

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
CREATE TABLE ECR_DATA
(
eICR_ID VARCHAR(200) PRIMARY KEY,
set_id VARCHAR(255),
fhir_reference_link VARCHAR(255),
last_name VARCHAR(255),
first_name VARCHAR(255),
birth_date DATE,
gender VARCHAR(50),
birth_sex VARCHAR(50),
gender_identity VARCHAR(50),
race VARCHAR(255),
ethnicity VARCHAR(255),
street_address_1 VARCHAR(255),
street_address_2 VARCHAR(255),
state VARCHAR(50),
zip_code VARCHAR(20),
latitude FLOAT,
longitude FLOAT,
homelessness_status VARCHAR(255),
disabilities VARCHAR(255),
tribal_affiliation VARCHAR(255),
tribal_enrollment_status VARCHAR(255),
current_job_title VARCHAR(255),
current_job_industry VARCHAR(255),
usual_occupation VARCHAR(255),
usual_industry VARCHAR(255),
preferred_language VARCHAR(255),
pregnancy_status VARCHAR(255),
rr_id VARCHAR(255),
processing_status VARCHAR(255),
eicr_version_number VARCHAR(50),
authoring_date DATE,
authoring_time TIME,
authoring_provider VARCHAR(255),
provider_id VARCHAR(255),
facility_id VARCHAR(255),
facility_name VARCHAR(255),
encounter_type VARCHAR(255),
encounter_start_date DATE,
encounter_start_time TIME,
encounter_end_date DATE,
encounter_end_time TIME,
reason_for_visit VARCHAR(MAX),
active_problems VARCHAR(MAX)
);

CREATE TABLE ecr_rr_conditions
(
UUID VARCHAR(200) PRIMARY KEY,
eICR_ID VARCHAR(200) NOT NULL REFERENCES ECR_DATA (eICR_ID),
condition VARCHAR(MAX)
);

CREATE TABLE ecr_rr_rule_summaries
(
UUID VARCHAR(200) PRIMARY KEY,
ECR_RR_CONDITIONS_ID VARCHAR(200) REFERENCES ecr_rr_conditions (UUID),
rule_summary VARCHAR(MAX)
);


CREATE TABLE ecr_labs
(
UUID VARCHAR(200) PRIMARY KEY,
eICR_ID VARCHAR(200) REFERENCES ECR_DATA (eICR_ID),
test_type VARCHAR(255),
test_type_code VARCHAR(50),
test_type_system VARCHAR(MAX),
test_result_qualitative VARCHAR(MAX),
test_result_quantitative FLOAT,
test_result_units VARCHAR(50),
test_result_code VARCHAR(50),
test_result_code_display VARCHAR(255),
test_result_code_system VARCHAR(50),
test_result_interpretation VARCHAR(255),
test_result_interpretation_code VARCHAR(50),
test_result_interpretation_system VARCHAR(255),
test_result_reference_range_low_value FLOAT,
test_result_reference_range_low_units VARCHAR(50),
test_result_reference_range_high_value FLOAT,
test_result_reference_range_high_units VARCHAR(50),
specimen_type VARCHAR(255),
specimen_collection_date DATE,
performing_lab VARCHAR(255)
);
19 changes: 19 additions & 0 deletions containers/ecr-viewer/src/app/api/conditions/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NextResponse } from "next/server";
import { get_conditions_postgres, get_conditions_sqlserver } from "./service";

/**
* Retrieves FHIR data from PostgreSQL database based on eCR ID.
* @returns A promise resolving to a NextResponse object.
*/
export async function GET() {
const metadataSaveLocation = process.env.METADATA_DATABASE_TYPE;

switch (metadataSaveLocation) {
case "postgres":
return await get_conditions_postgres();
case "sqlserver":
return await get_conditions_sqlserver();
default:
return NextResponse.json({ message: "Invalid source" }, { status: 500 });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we have another variable called "source", could we update this error to specifically say Invalid metadata database type?

}
}
65 changes: 65 additions & 0 deletions containers/ecr-viewer/src/app/api/conditions/service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import pgPromise from "pg-promise";
import { database } from "../services/db";
import { NextResponse } from "next/server";
import sql from "mssql";
/**
* Retrieves all unique conditions from the ecr_rr_conditions table in the PostgreSQL database.
* @returns A promise resolving to a NextResponse object.
* @throws An error if the connection to the PostgreSQL database fails.
*/
export const get_conditions_postgres = async () => {
console.log("Get conditions from postgres");

const { ParameterizedQuery: PQ } = pgPromise;

try {
const response = await database.tx(async (t) => {
const getConditions = new PQ({
text: 'SELECT DISTINCT "condition" FROM ecr_rr_conditions',
JNygaard-Skylight marked this conversation as resolved.
Show resolved Hide resolved
});

const conditions = await t.any(getConditions);
return NextResponse.json(
conditions.map((c) => c.condition),
{ status: 200 },
);
});

return response;
} catch (error: any) {
console.error("Error fetching data:", error);
return NextResponse.json({ message: error.message }, { status: 500 });
}
};

/**
* Retrieves all unique conditions from the ecr_rr_conditions table in the SQL Server database.
* @returns A promise resolving to a NextResponse object.
* @throws An error if the connection to the SQL Server database fails.
*/
export const get_conditions_sqlserver = async () => {
let pool = await sql.connect({
user: process.env.SQL_SERVER_USER,
password: process.env.SQL_SERVER_PASSWORD,
server: process.env.SQL_SERVER_HOST || "localhost",
options: {
trustServerCertificate: true,
},
});
Comment on lines +39 to +46
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we initialize this connection in this file and in save-fhir-data-service.ts can we just pull this out into a single file like we do for postgres?


try {
const transaction = new sql.Transaction(pool);
await transaction.begin();
const request = new sql.Request(transaction);

const result = await request.query(
"SELECT DISTINCT erc.[condition] FROM ecr_rr_conditions erc ",
);
const conditions: string[] = result.recordset.map((row) => row.condition);

return NextResponse.json(conditions, { status: 200 });
} catch (error: any) {
console.error("Error fetching data:", error);
return NextResponse.json({ message: error.message }, { status: 500 });
}
};
6 changes: 1 addition & 5 deletions containers/ecr-viewer/src/app/api/save-fhir-data/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import { S3_SOURCE, AZURE_SOURCE, POSTGRES_SOURCE } from "@/app/api/utils";
export async function POST(request: NextRequest) {
let requestBody;
let fhirBundle;
let saveSource;
let ecrId;

try {
requestBody = await request.json();
fhirBundle = requestBody.fhirBundle;
saveSource = requestBody.saveSource;
ecrId = requestBody.fhirBundle.entry[0].resource.id;
} catch (error: any) {
console.error("Error reading request body:", error);
Expand All @@ -36,9 +34,7 @@ export async function POST(request: NextRequest) {
);
}

if (!saveSource) {
saveSource = process.env.SOURCE;
}
let saveSource = requestBody.saveSource || process.env.SOURCE;
JNygaard-Skylight marked this conversation as resolved.
Show resolved Hide resolved

if (
[S3_SOURCE, AZURE_SOURCE, POSTGRES_SOURCE].includes(saveSource) == false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,22 @@ export const saveMetadataToSqlServer = async (
metadata: BundleExtendedMetadata,
ecrId: string,
) => {
let pool = await sql.connect({
user: process.env.SQL_SERVER_USER,
password: process.env.SQL_SERVER_PASSWORD,
server: process.env.SQL_SERVER_HOST || "localhost",
options: {
trustServerCertificate: true,
},
});
let pool;
try {
pool = await sql.connect({
user: process.env.SQL_SERVER_USER,
password: process.env.SQL_SERVER_PASSWORD,
server: process.env.SQL_SERVER_HOST || "localhost",
options: {
trustServerCertificate: true,
},
});
} catch (error: any) {
return NextResponse.json(
{ message: "Failed to connect to SQL Server. " + error.message },
{ status: 500 },
);
}

const transaction = new sql.Transaction(pool);
await transaction.begin();
Expand Down Expand Up @@ -290,10 +298,14 @@ export const saveMetadataToSqlServer = async (
.input("eICR_ID", sql.VarChar(200), metadata.eicr_id)
.input("test_type", sql.VarChar(200), lab.test_type)
.input("test_type_code", sql.VarChar(50), lab.test_type_code)
.input("test_type_system", sql.VarChar(50), lab.test_type_system)
.input(
"test_type_system",
sql.VarChar(sql.MAX),
JNygaard-Skylight marked this conversation as resolved.
Show resolved Hide resolved
lab.test_type_system,
)
.input(
"test_result_qualitative",
sql.VarChar(255),
sql.VarChar(sql.MAX),
lab.test_result_qualitative,
)
.input(
Expand Down Expand Up @@ -383,6 +395,7 @@ export const saveMetadataToSqlServer = async (
{ status: 200 },
);
} catch (error: any) {
console.log(metadata);
JNygaard-Skylight marked this conversation as resolved.
Show resolved Hide resolved
console.error("Error inserting metadata to database:", error);

// Rollback the transaction if any error occurs
Expand Down Expand Up @@ -494,18 +507,21 @@ export const saveWithMetadata = async (
saveSource: string,
metadata: BundleMetadata | BundleExtendedMetadata,
) => {
console.log("Saving FHIR data with metadata");
let fhirDataResult;
let metadataResult;
const metadataSaveLocation = process.env.METADATA_DATABASE_TYPE;
try {
fhirDataResult = await saveFhirData(fhirBundle, ecrId, saveSource);

if (metadataSaveLocation == "postgres") {
console.log("Saving metadata to Postgres");
metadataResult = await saveMetadataToPostgres(
metadata as BundleMetadata,
ecrId,
);
} else if (metadataSaveLocation == "sqlserver") {
console.log("Saving metadata to SQL Server");
JNygaard-Skylight marked this conversation as resolved.
Show resolved Hide resolved
metadataResult = await saveMetadataToSqlServer(
metadata as BundleExtendedMetadata,
ecrId,
Expand Down
Loading
Loading