Skip to content

Commit

Permalink
Add Alerts Performance overview table
Browse files Browse the repository at this point in the history
  • Loading branch information
anagperal committed Jan 7, 2025
1 parent 398ca6a commit 2e97e67
Show file tree
Hide file tree
Showing 22 changed files with 891 additions and 280 deletions.
7 changes: 5 additions & 2 deletions src/CompositionRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { MapConfigTestRepository } from "./data/repositories/test/MapConfigTestR
import { GetMapConfigUseCase } from "./domain/usecases/GetMapConfigUseCase";
import { GetProvincesOrgUnits } from "./domain/usecases/GetProvincesOrgUnits";
import { PerformanceOverviewRepository } from "./domain/repositories/PerformanceOverviewRepository";
import { GetAllPerformanceOverviewMetricsUseCase } from "./domain/usecases/GetAllPerformanceOverviewMetricsUseCase";
import { GetAllNationalPerformanceOverviewMetricsUseCase } from "./domain/usecases/GetAllNationalPerformanceOverviewMetricsUseCase";
import { PerformanceOverviewD2Repository } from "./data/repositories/PerformanceOverviewD2Repository";
import { PerformanceOverviewTestRepository } from "./data/repositories/test/PerformanceOverviewTestRepository";
import { AlertSyncDataStoreRepository } from "./data/repositories/AlertSyncDataStoreRepository";
Expand Down Expand Up @@ -73,6 +73,7 @@ import { CasesFileTestRepository } from "./data/repositories/test/CasesFileTestR
import { UserGroupD2Repository } from "./data/repositories/UserGroupD2Repository";
import { UserGroupRepository } from "./domain/repositories/UserGroupRepository";
import { UserGroupTestRepository } from "./data/repositories/test/UserGroupTestRepository";
import { GetAllAlertsPerformanceOverviewMetricsUseCase } from "./domain/usecases/GetAllAlertsPerformanceOverviewMetricsUseCase";

export type CompositionRoot = ReturnType<typeof getCompositionRoot>;

Expand Down Expand Up @@ -128,7 +129,9 @@ function getCompositionRoot(repositories: Repositories) {
new DeleteIncidentManagementTeamMemberRolesUseCase(repositories),
},
performanceOverview: {
getPerformanceOverviewMetrics: new GetAllPerformanceOverviewMetricsUseCase(
getNationalPerformanceOverviewMetrics:
new GetAllNationalPerformanceOverviewMetricsUseCase(repositories),
getAlertsPerformanceOverviewMetrics: new GetAllAlertsPerformanceOverviewMetricsUseCase(
repositories
),
getTotalCardCounts: new GetTotalCardCountsUseCase(repositories),
Expand Down
7 changes: 1 addition & 6 deletions src/data/repositories/OrgUnitD2Repository.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { D2Api, MetadataPick } from "../../types/d2-api";
import { OrgUnit, OrgUnitLevelType } from "../../domain/entities/OrgUnit";
import { OrgUnit, orgUnitLevelTypeByLevelNumber } from "../../domain/entities/OrgUnit";
import { Id } from "../../domain/entities/Ref";
import { OrgUnitRepository } from "../../domain/repositories/OrgUnitRepository";
import { apiToFuture, FutureData } from "../api-futures";

const orgUnitLevelTypeByLevelNumber: Record<number, OrgUnitLevelType> = {
1: "National",
2: "Province",
3: "District",
};
export class OrgUnitD2Repository implements OrgUnitRepository {
constructor(private api: D2Api) {}

Expand Down
119 changes: 117 additions & 2 deletions src/data/repositories/PerformanceOverviewD2Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { Maybe } from "../../utils/ts-utils";
import { AnalyticsResponse, D2Api } from "../../types/d2-api";
import { PerformanceOverviewRepository } from "../../domain/repositories/PerformanceOverviewRepository";
import { apiToFuture, FutureData } from "../api-futures";
import { RTSL_ZEBRA_PROGRAM_ID } from "./consts/DiseaseOutbreakConstants";
import {
RTSL_ZEBRA_ALERTS_PROGRAM_ID,
RTSL_ZEBRA_ALERTS_VERIFICATION_STATUS_ID,
RTSL_ZEBRA_PROGRAM_ID,
} from "./consts/DiseaseOutbreakConstants";
import _ from "../../domain/entities/generic/Collection";
import { Future } from "../../domain/entities/generic/Future";
import {
Expand Down Expand Up @@ -33,6 +37,13 @@ import {
ProgramIndicatorsDatastore,
ProgramIndicatorsDatastoreKey,
} from "./common/getProgramIndicatorsFromDatastore";
import { AlertsPerformanceOverviewMetrics } from "../../domain/entities/alert/AlertsPerformanceOverviewMetrics";
import {
AlertsPerformanceOverviewDimensions,
AlertsPerformanceOverviewDimensionsKey,
AlertsPerformanceOverviewDimensionsValue,
} from "./consts/AlertsPerformanceOverviewConstants";
import { orgUnitLevelTypeByLevelNumber } from "../../domain/entities/OrgUnit";

const formatDate = (date: Date): string => {
const year = date.getFullYear();
Expand All @@ -55,6 +66,8 @@ const EVENT_TRACKER_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY =
const ALERTS_PERFORMANCE_717_PROGRAM_INDICATORS_DATASTORE_KEY =
"alerts-717-performance-program-indicators";
const PERFORMANCE_OVERVIEW_DIMENSIONS_DATASTORE_KEY = "performance-overview-dimensions";
const ALERTS_PERFORMANCE_OVERVIEW_DIMENSIONS_DATASTORE_KEY =
"alerts-performance-overview-dimensions";

type EventTrackerOverviewInDataStore = {
key: string;
Expand Down Expand Up @@ -429,7 +442,7 @@ export class PerformanceOverviewD2Repository implements PerformanceOverviewRepos
);
}

getPerformanceOverviewMetrics(
getNationalPerformanceOverviewMetrics(
diseaseOutbreakEvents: DiseaseOutbreakEventBaseAttrs[]
): FutureData<PerformanceOverviewMetrics[]> {
return this.datastore
Expand Down Expand Up @@ -571,6 +584,102 @@ export class PerformanceOverviewD2Repository implements PerformanceOverviewRepos
});
}

getAlertsPerformanceOverviewMetrics(): FutureData<AlertsPerformanceOverviewMetrics[]> {
return this.datastore
.getObject<AlertsPerformanceOverviewDimensions>(
ALERTS_PERFORMANCE_OVERVIEW_DIMENSIONS_DATASTORE_KEY
)
.flatMap(nullablePerformanceOverviewDimensions => {
return assertOrError(
nullablePerformanceOverviewDimensions,
ALERTS_PERFORMANCE_OVERVIEW_DIMENSIONS_DATASTORE_KEY
).flatMap(performanceOverviewDimensions => {
return apiToFuture(
this.api.get<AnalyticsResponse>(
`/analytics/enrollments/query/${RTSL_ZEBRA_ALERTS_PROGRAM_ID}`,
{
dimension: [
performanceOverviewDimensions.eventEBSId,
performanceOverviewDimensions.eventIBSId,
performanceOverviewDimensions.nationalDiseaseOutbreakEventId,
performanceOverviewDimensions.hazardType,
performanceOverviewDimensions.suspectedDisease,
performanceOverviewDimensions.cases,
performanceOverviewDimensions.deaths,
performanceOverviewDimensions.notify1d,
performanceOverviewDimensions.detect7d,
performanceOverviewDimensions.incidentManager,
performanceOverviewDimensions.respond7d,
performanceOverviewDimensions.incidentStatus,
],
startDate: DEFAULT_START_DATE,
endDate: DEFAULT_END_DATE,
paging: false,
programStatus: "ACTIVE",
filter: `${RTSL_ZEBRA_ALERTS_VERIFICATION_STATUS_ID}:eq:RTSL_ZEB_AL_OS_VERIFICATION_VERIFIED`,
}
)
).flatMap(response => {
const mappedIndicators: AlertsPerformanceOverviewMetrics[] =
response.rows.map((row: string[]) => {
return Object.keys(performanceOverviewDimensions).reduce(
(acc, dimensionKey) => {
const dimension: AlertsPerformanceOverviewDimensionsValue =
performanceOverviewDimensions[
dimensionKey as AlertsPerformanceOverviewDimensionsKey
];

const index = response.headers.findIndex(
header => header.name === dimension
);
if (dimension === "enrollmentdate") {
const duration = `${moment()
.diff(moment(row[index]), "days")
.toString()}d`;

const inputDate = row[index];
const formattedDate = inputDate?.split(" ")[0]; // YYYY-MM-DD
return {
...acc,
duration: duration,
[dimensionKey]: formattedDate,
};
} else if (dimension === "ounamehierarchy") {
const hierarchyArray = row[index]?.split("/");
return {
...acc,
province:
(hierarchyArray && hierarchyArray.length > 1
? hierarchyArray[1]
: row[index]) || "",
orgUnitType:
hierarchyArray && hierarchyArray.length > 0
? orgUnitLevelTypeByLevelNumber[
hierarchyArray.length
] || "National"
: "National",
};
} else {
const nameValue = Object.values(
response.metaData.items
).find(item => item.code === row[index])?.name;

return {
...acc,
[dimensionKey]: nameValue || row[index],
};
}
},
{} as AlertsPerformanceOverviewMetrics
);
});

return Future.success(mappedIndicators);
});
});
});
}

private getAnalyticsByIndicators(ids: Id[]): FutureData<IdValue[]> {
return apiToFuture(
this.api.analytics.get({
Expand Down Expand Up @@ -803,6 +912,12 @@ export class PerformanceOverviewD2Repository implements PerformanceOverviewRepos
acc.respond7d = row[index];
break;

case "date": {
const inputDate = row[index];
const formattedDate = inputDate?.split(" ")[0]; // YYYY-MM-DD
acc.date = formattedDate;
break;
}
default:
acc[key] = row[index];
break;
Expand Down
25 changes: 25 additions & 0 deletions src/data/repositories/consts/AlertsPerformanceOverviewConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Id } from "../../../domain/entities/Ref";

export type AlertsPerformanceOverviewDimensions = {
teiId: "tei";
eventEBSId: Id;
eventIBSId: Id;
nationalDiseaseOutbreakEventId: Id;
hazardType: Id;
suspectedDisease: Id;
orgUnit: "ouname";
orgUnitHierarchy: "ounamehierarchy";
cases: Id;
deaths: Id;
date: "enrollmentdate";
notify1d: Id;
detect7d: Id;
incidentManager: Id;
respond7d: Id;
incidentStatus: Id;
};

export type AlertsPerformanceOverviewDimensionsKey = keyof AlertsPerformanceOverviewDimensions;

export type AlertsPerformanceOverviewDimensionsValue =
AlertsPerformanceOverviewDimensions[AlertsPerformanceOverviewDimensionsKey];
1 change: 1 addition & 0 deletions src/data/repositories/consts/DiseaseOutbreakConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const RTSL_ZEBRA_ALERTS_NATIONAL_DISEASE_OUTBREAK_EVENT_ID_TEA_ID = "Pq1d
export const RTSL_ZEBRA_ALERTS_DISEASE_TEA_ID = "agsVaIpit4S";
export const RTSL_ZEBRA_ALERTS_EVENT_TYPE_TEA_ID = "ydsfY6zyvt7";
export const RTSL_ZEBRA_ALERTS_NATIONAL_INCIDENT_STATUS_TEA_ID = "DzGqKzjhIsz";
export const RTSL_ZEBRA_ALERTS_VERIFICATION_STATUS_ID = "HvgldgBK8Th";

export const hazardTypeCodeMap: Record<HazardType, string> = {
"Biological:Human": "RTSL_ZEB_OS_HAZARD_TYPE_BIOLOGICAL_HUMAN",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type PerformanceOverviewDimensions = {
suspectedDisease: Id;
hazardType: Id;
nationalIncidentStatus: "incidentStatus";
date: "enrollmentdate";
};

type EventTrackerCountIndicatorBase = {
Expand Down
105 changes: 60 additions & 45 deletions src/data/repositories/test/PerformanceOverviewTestRepository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AlertsPerformanceOverviewMetrics } from "../../../domain/entities/alert/AlertsPerformanceOverviewMetrics";
import { PerformanceMetrics717 } from "../../../domain/entities/disease-outbreak-event/PerformanceOverviewMetrics";
import { Future } from "../../../domain/entities/generic/Future";
import { OverviewCard } from "../../../domain/entities/PerformanceOverview";
Expand All @@ -23,7 +24,7 @@ export class PerformanceOverviewTestRepository implements PerformanceOverviewRep
return Future.success(0);
}

getPerformanceOverviewMetrics(): FutureData<any[]> {
getNationalPerformanceOverviewMetrics(): FutureData<any[]> {
return Future.success([
{
id: "JPenxAnjdhY",
Expand Down Expand Up @@ -76,56 +77,70 @@ export class PerformanceOverviewTestRepository implements PerformanceOverviewRep
detect7d: "",
notify1d: "",
},
]);
}

getAlertsPerformanceOverviewMetrics(): FutureData<AlertsPerformanceOverviewMetrics[]> {
return Future.success([
{
id: "EtoUrZCn8mP",
manager: "user, dev (dev.user)",
creationDate: "2024-08-22 15:12:06.016",
province: "zm Zambia Ministry of Health",
cases: "1",
teiId: "n3zdthapNzC",
deaths: "3",
province: " ce Central Province ",
orgUnit: "Central Province",
orgUnitType: "Province",
detect7d: "",
duration: "158d",
notify1d: "3",
respond7d: "-2",
eventEBSId: "",
eventIBSId: "OUTBREAK_000005",
hazardType: "",
incidentStatus: "Watch",
incidentManager: "etst",
suspectedDisease: "COVID19",
event: "Cholera Aug 2024",
era1: "15",
era2: "14",
era3: "",
era4: "14",
era5: "",
era6: "",
era7: "14",
detect7d: "2",
notify1d: "1",
nationalDiseaseOutbreakEventId: "tnhWg7zKmNF",
date: "2024-08-27",
},
{
id: "HNiwOkH3vdJ",
manager: "user, dev (dev.user)",
creationDate: "2024-08-22 13:29:27.734",
province: "zm Zambia Ministry of Health",
suspectedDisease: "Anthrax",
event: "Anthrax July 2024",
era1: "29",
era2: "28",
era3: "",
era4: "",
era5: "",
era6: "",
era7: "17",
detect7d: "10",
notify1d: "21",
cases: "22",
teiId: "ZJylQsTku6z",
deaths: "1",
province: " ce Central Province ",
orgUnit: "Central Province",
orgUnitType: "Province",
detect7d: "",
duration: "139d",
notify1d: "1",
respond7d: "-1",
eventEBSId: "",
eventIBSId: "OUTBREAK_000011",
hazardType: "",
incidentStatus: "Watch",
incidentManager: "Zebra Test 1",
suspectedDisease: "COVID19",
nationalDiseaseOutbreakEventId: "tnhWg7zKmNF",
date: "2024-08-27",
},
{
id: "qrezSaY5G0U",
manager: "user, dev (dev.user)",
creationDate: "2024-08-22 13:25:24.505",
province: "zm Zambia Ministry of Health",
suspectedDisease: "Measles",
event: "Measles June 2024",
era1: "63",
era2: "55",
era3: "",
era4: "",
era5: "",
era6: "",
era7: "53",
detect7d: "3",
notify1d: "2",
cases: "5",
teiId: "cOWooRCVHqa",
deaths: "5",
province: " ce Central Province ",
orgUnit: "Central Province",
orgUnitType: "Province",
detect7d: "2",
duration: "111d",
notify1d: "1",
respond7d: "-1",
eventEBSId: "12345",
eventIBSId: "",
hazardType: "Biological: Animal",
incidentStatus: "Alert",
incidentManager: "Zebra Test 2",
suspectedDisease: "Acute VHF",
nationalDiseaseOutbreakEventId: "LALS50e9Zea",
date: "2024-08-27",
},
]);
}
Expand Down
9 changes: 8 additions & 1 deletion src/domain/entities/OrgUnit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { CodedNamedRef } from "./Ref";

export type OrgUnitLevelType = "National" | "Province" | "District";
export type OrgUnitLevelType = "National" | "Province" | "District" | "Health Facility";

export type OrgUnit = CodedNamedRef & {
level: OrgUnitLevelType;
};

export const orgUnitLevelTypeByLevelNumber: Record<number, OrgUnitLevelType> = {
1: "National",
2: "Province",
3: "District",
4: "Health Facility",
};
Loading

0 comments on commit 2e97e67

Please sign in to comment.