Skip to content

Commit

Permalink
replace use_cases with queries from the query table (#297)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
fzhao99 and pre-commit-ci[bot] authored Jan 21, 2025
1 parent b804744 commit 8687971
Show file tree
Hide file tree
Showing 22 changed files with 376 additions and 434 deletions.
10 changes: 7 additions & 3 deletions query-connector/e2e/alternate_queries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ test.describe("alternate queries with the Query Connector", () => {
await expect(
page.getByRole("heading", { name: PAGE_TITLES["select-query"].title }),
).toBeVisible();
await page.getByTestId("Select").selectOption("chlamydia");
await page
.getByTestId("Select")
.selectOption("Chlamydia case investigation");
await page.getByRole("button", { name: "Submit" }).click();
await expect(page.getByText("Loading")).toHaveCount(0, { timeout: 10000 });

Expand Down Expand Up @@ -65,7 +67,7 @@ test.describe("alternate queries with the Query Connector", () => {
await expect(
page.getByRole("heading", { name: "Select a query" }),
).toBeVisible();
await page.getByTestId("Select").selectOption("cancer");
await page.getByTestId("Select").selectOption("Cancer case investigation");
await page.getByRole("button", { name: "Submit" }).click();
await expect(page.getByText("Loading")).toHaveCount(0, { timeout: 10000 });

Expand All @@ -88,7 +90,9 @@ test.describe("alternate queries with the Query Connector", () => {
await page.getByRole("button", { name: "Search for patient" }).click();
await expect(page.getByText("Loading")).toHaveCount(0, { timeout: 10000 });
await page.getByRole("link", { name: "Select patient" }).click();
await page.getByTestId("Select").selectOption("chlamydia");
await page
.getByTestId("Select")
.selectOption("Chlamydia case investigation");
await page.getByRole("button", { name: "Submit" }).click();
await expect(page.getByText("Loading")).toHaveCount(0, { timeout: 10000 });

Expand Down
4 changes: 3 additions & 1 deletion query-connector/e2e/customize_query.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ test.describe("querying with the Query Connector", () => {
await expect(
page.getByRole("heading", { name: "Select a query" }),
).toBeVisible();
await page.getByTestId("Select").selectOption("chlamydia");
await page
.getByTestId("Select")
.selectOption("Chlamydia case investigation");

await page.getByRole("button", { name: "Customize Query" }).click();
await expect(
Expand Down
4 changes: 3 additions & 1 deletion query-connector/e2e/query_workflow.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ test.describe("querying with the Query Connector", () => {
await expect(
page.getByRole("heading", { name: "Select a query" }),
).toBeVisible();
await page.getByTestId("Select").selectOption("chlamydia");
await page
.getByTestId("Select")
.selectOption("Chlamydia case investigation");

// For some reason only in Chromium (ie not in firefox / webkit) there were
// issues connecting to the database for the cancer use case, which was resulting
Expand Down
66 changes: 38 additions & 28 deletions query-connector/src/app/api/query/route.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { NextResponse, NextRequest } from "next/server";
import {
UseCaseQuery,
UseCaseQueryRequest,
makeFhirQuery,
QueryRequest,
QueryResponse,
createBundle,
APIQueryResponse,
} from "../../query-service";
import { parsePatientDemographics } from "./parsing-service";
import {
USE_CASES,
USE_CASE_DETAILS,
INVALID_FHIR_SERVERS,
INVALID_USE_CASE,
INVALID_QUERY,
RESPONSE_BODY_IS_NOT_PATIENT_RESOURCE,
MISSING_API_QUERY_PARAM,
MISSING_PATIENT_IDENTIFIERS,
USE_CASE_DETAILS,
USE_CASES,
} from "../../constants";

import { handleRequestError } from "./error-handling-service";
import {
getFhirServerNames,
getSavedQueryByName,
} from "@/app/database-service";
import { getFhirServerNames } from "@/app/database-service";
import { unnestValueSetsFromQuery } from "@/app/utils";
import { getSavedQueryById } from "@/app/backend/query-building";

/**
* Health check for TEFCA Viewer
Expand All @@ -33,11 +31,11 @@ export async function GET() {
}

/**
* Handles a POST request to query a given FHIR server for a given use case. The
* use_case and fhir_server are provided as query parameters in the request URL. The
* Handles a POST request to query a given FHIR server for a given query. The
* id and fhir_server are provided as query parameters in the request URL. The
* request body contains the FHIR patient resource to be queried.
* @param request - The incoming Next.js request object.
* @returns Response with UseCaseResponse.
* @returns Response with QueryResponse.
*/
export async function POST(request: NextRequest) {
let requestBody;
Expand Down Expand Up @@ -72,31 +70,34 @@ export async function POST(request: NextRequest) {
return NextResponse.json(OperationOutcome);
}

// Extract use_case and fhir_server from nextUrl
// Extract id and fhir_server from nextUrl
const params = request.nextUrl.searchParams;
const use_case = params.get("use_case");
//deprecated, prefer id
const use_case_param = params.get("use_case");
const id_param = params.get("id");
const fhir_server = params.get("fhir_server");
const fhirServers = await getFhirServerNames();

if (!use_case || !fhir_server) {
const id = id_param ? id_param : mapDeprecatedUseCaseToId(use_case_param);

if (!id || !fhir_server) {
const OperationOutcome = await handleRequestError(MISSING_API_QUERY_PARAM);
return NextResponse.json(OperationOutcome);
} else if (!Object.keys(USE_CASE_DETAILS).includes(use_case)) {
const OperationOutcome = await handleRequestError(INVALID_USE_CASE);
return NextResponse.json(OperationOutcome);
} else if (!Object.values(fhirServers).includes(fhir_server)) {
const OperationOutcome = await handleRequestError(INVALID_FHIR_SERVERS);
return NextResponse.json(OperationOutcome);
}

// Lookup default parameters for particular use-case search
const queryName = USE_CASE_DETAILS[use_case as USE_CASES].queryName;
const queryResults = await getSavedQueryByName(queryName);
const valueSets = unnestValueSetsFromQuery(queryResults);
const queryResults = await getSavedQueryById(id);

// Add params & patient identifiers to UseCaseRequest
const UseCaseRequest: UseCaseQueryRequest = {
use_case: use_case as USE_CASES,
if (queryResults.length === 0) {
const OperationOutcome = await handleRequestError(INVALID_QUERY);
return NextResponse.json(OperationOutcome);
}

// Add params & patient identifiers to QueryName
const QueryRequest: QueryRequest = {
query_name: queryResults[0].query_name,
fhir_server: fhir_server,
...(PatientIdentifiers.first_name && {
first_name: PatientIdentifiers.first_name,
Expand All @@ -109,13 +110,22 @@ export async function POST(request: NextRequest) {
...(PatientIdentifiers.phone && { phone: PatientIdentifiers.phone }),
};

const UseCaseQueryResponse: QueryResponse = await UseCaseQuery(
UseCaseRequest,
const valueSets = unnestValueSetsFromQuery(queryResults);

const QueryResponse: QueryResponse = await makeFhirQuery(
QueryRequest,
valueSets,
);

// Bundle data
const bundle: APIQueryResponse = await createBundle(UseCaseQueryResponse);
const bundle: APIQueryResponse = await createBundle(QueryResponse);

return NextResponse.json(bundle);
}

function mapDeprecatedUseCaseToId(use_case: string | null) {
if (use_case === null) return null;
const potentialUseCaseMatch = USE_CASE_DETAILS[use_case as USE_CASES];
const queryId = potentialUseCaseMatch?.id ?? null;
return queryId;
}
Loading

0 comments on commit 8687971

Please sign in to comment.