Skip to content

Commit

Permalink
Merge pull request #23 from EyeSeeTea/feat/d2-logger
Browse files Browse the repository at this point in the history
[feature] Integrate d2-logger (coding dojo)
  • Loading branch information
bhavananarayanan authored Jan 17, 2025
2 parents ed7c588 + 5d1479e commit 7a050ea
Show file tree
Hide file tree
Showing 34 changed files with 1,025 additions and 573 deletions.
4 changes: 2 additions & 2 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2025-01-14T15:51:01.421Z\n"
"PO-Revision-Date: 2025-01-14T15:51:01.421Z\n"
"POT-Creation-Date: 2025-01-15T17:33:26.984Z\n"
"PO-Revision-Date: 2025-01-15T17:33:26.984Z\n"

msgid "Low"
msgstr ""
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@emotion/react": "11.11.4",
"@emotion/styled": "11.11.5",
"@eyeseetea/d2-api": "1.16.0-beta.12",
"@eyeseetea/d2-logger": "^1.1.0",
"@eyeseetea/d2-ui-components": "v2.9.0-beta.2",
"@eyeseetea/feedback-component": "0.0.3",
"@material-ui/core": "4.12.4",
Expand Down
23 changes: 23 additions & 0 deletions src/data/entities/Instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export interface InstanceData {
url: string;
username?: string;
password?: string;
}

export class Instance {
public readonly url: string;
private username: string | undefined;
private password: string | undefined;

constructor(data: InstanceData) {
this.url = data.url;
this.username = data.username;
this.password = data.password;
}

public get auth(): { username: string; password: string } | undefined {
return this.username && this.password
? { username: this.username, password: this.password }
: undefined;
}
}
108 changes: 30 additions & 78 deletions src/data/repositories/AlertD2Repository.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { D2Api } from "@eyeseetea/d2-api/2.36";
import { apiToFuture, FutureData } from "../api-futures";
import {
RTSL_ZEBRA_ALERTS_DISEASE_TEA_ID,
RTSL_ZEBRA_ALERTS_EVENT_TYPE_TEA_ID,
RTSL_ZEBRA_ALERTS_NATIONAL_DISEASE_OUTBREAK_EVENT_ID_TEA_ID,
RTSL_ZEBRA_ALERTS_NATIONAL_INCIDENT_STATUS_TEA_ID,
RTSL_ZEBRA_ALERTS_PROGRAM_ID,
Expand All @@ -12,32 +10,26 @@ import { AlertOptions, AlertRepository } from "../../domain/repositories/AlertRe
import { Id } from "../../domain/entities/Ref";
import _ from "../../domain/entities/generic/Collection";
import { Future } from "../../domain/entities/generic/Future";
import {
D2TrackerTrackedEntity,
TrackedEntitiesGetResponse,
} from "@eyeseetea/d2-api/api/trackerTrackedEntities";
import { D2TrackerTrackedEntity } from "@eyeseetea/d2-api/api/trackerTrackedEntities";
import { Maybe } from "../../utils/ts-utils";
import { DataSource } from "../../domain/entities/disease-outbreak-event/DiseaseOutbreakEvent";
import { Alert } from "../../domain/entities/alert/Alert";

export type Filter = {
id: Id;
value: Maybe<string>;
};
import { OutbreakData } from "../../domain/entities/alert/OutbreakAlert";
import { getAllTrackedEntitiesAsync } from "./utils/getAllTrackedEntities";
import { outbreakDataSourceMapping, outbreakTEAMapping } from "./utils/AlertOutbreakMapper";

export class AlertD2Repository implements AlertRepository {
constructor(private api: D2Api) {}

updateAlerts(alertOptions: AlertOptions): FutureData<Alert[]> {
const { dataSource, eventId, hazardTypeCode, incidentStatus, suspectedDiseaseCode } =
alertOptions;
const filter = this.getAlertFilter(dataSource, suspectedDiseaseCode, hazardTypeCode);
const { dataSource, eventId, incidentStatus, outbreakValue } = alertOptions;
const outbreakData = this.getAlertOutbreakData(dataSource, outbreakValue);

return this.getTrackedEntitiesByTEACode({
program: RTSL_ZEBRA_ALERTS_PROGRAM_ID,
orgUnit: RTSL_ZEBRA_ORG_UNIT_ID,
ouMode: "DESCENDANTS",
filter: filter,
filter: outbreakData,
}).flatMap(alertTrackedEntities => {
const alertsToMap: Alert[] = alertTrackedEntities.map(trackedEntity => ({
id: trackedEntity.trackedEntity || "",
Expand Down Expand Up @@ -79,78 +71,38 @@ export class AlertD2Repository implements AlertRepository {
});
}

private async getTrackedEntitiesByTEACodeAsync(options: {
private getTrackedEntitiesByTEACode(options: {
program: Id;
orgUnit: Id;
ouMode: "SELECTED" | "DESCENDANTS";
filter?: Filter;
}): Promise<D2TrackerTrackedEntity[]> {
filter: OutbreakData;
}): FutureData<D2TrackerTrackedEntity[]> {
const { program, orgUnit, ouMode, filter } = options;
const d2TrackerTrackedEntities: D2TrackerTrackedEntity[] = [];

const pageSize = 250;
let page = 1;
let result: TrackedEntitiesGetResponse;

try {
do {
result = await this.api.tracker.trackedEntities
.get({
program: program,
orgUnit: orgUnit,
ouMode: ouMode,
totalPages: true,
page: page,
pageSize: pageSize,
fields: {
attributes: true,
orgUnit: true,
trackedEntity: true,
trackedEntityType: true,
enrollments: {
events: {
createdAt: true,
dataValues: {
dataElement: true,
value: true,
},
event: true,
},
},
},
filter: filter ? `${filter.id}:eq:${filter.value}` : undefined,
})
.getData();

d2TrackerTrackedEntities.push(...result.instances);

page++;
} while (result.page < Math.ceil((result.total as number) / pageSize));
return d2TrackerTrackedEntities;
} catch {
return [];
}
return Future.fromPromise(
getAllTrackedEntitiesAsync(this.api, {
programId: program,
orgUnitId: orgUnit,
ouMode: ouMode,
filter: {
id: this.getOutbreakFilterId(filter),
value: filter.value,
},
})
);
}

getTrackedEntitiesByTEACode(options: {
program: Id;
orgUnit: Id;
ouMode: "SELECTED" | "DESCENDANTS";
filter?: Filter;
}): FutureData<D2TrackerTrackedEntity[]> {
return Future.fromPromise(this.getTrackedEntitiesByTEACodeAsync(options));
private getOutbreakFilterId(filter: OutbreakData): string {
return outbreakTEAMapping[filter.type];
}

private getAlertFilter(
private getAlertOutbreakData(
dataSource: DataSource,
suspectedDiseaseCode: Maybe<string>,
hazardTypeCode: Maybe<string>
): Filter {
switch (dataSource) {
case DataSource.RTSL_ZEB_OS_DATA_SOURCE_IBS:
return { id: RTSL_ZEBRA_ALERTS_DISEASE_TEA_ID, value: suspectedDiseaseCode };
case DataSource.RTSL_ZEB_OS_DATA_SOURCE_EBS:
return { id: RTSL_ZEBRA_ALERTS_EVENT_TYPE_TEA_ID, value: hazardTypeCode };
}
outbreakValue: Maybe<string>
): OutbreakData {
return {
type: outbreakDataSourceMapping[dataSource],
value: outbreakValue,
};
}
}
13 changes: 3 additions & 10 deletions src/data/repositories/AlertSyncDataStoreRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,7 @@ export class AlertSyncDataStoreRepository implements AlertSyncRepository {
}

saveAlertSyncData(options: AlertSyncOptions): FutureData<void> {
const {
alert,
dataSource,
hazardTypeCode,
suspectedDiseaseCode,
hazardTypes,
suspectedDiseases,
} = options;
const { alert, outbreakValue, dataSource, hazardTypes, suspectedDiseases } = options;

return this.getAlertTrackedEntity(alert).flatMap(alertTrackedEntity => {
const verificationStatus = getAlertValueFromMap(
Expand All @@ -45,7 +38,7 @@ export class AlertSyncDataStoreRepository implements AlertSyncRepository {
if (verificationStatus === VerificationStatus.RTSL_ZEB_AL_OS_VERIFICATION_VERIFIED) {
const outbreakKey = getOutbreakKey({
dataSource: dataSource,
outbreakValue: suspectedDiseaseCode || hazardTypeCode,
outbreakValue: outbreakValue,
hazardTypes: hazardTypes,
suspectedDiseases: suspectedDiseases,
});
Expand Down Expand Up @@ -79,7 +72,7 @@ export class AlertSyncDataStoreRepository implements AlertSyncRepository {
});
}

public getAlertTrackedEntity(alert: Alert): FutureData<D2TrackerTrackedEntity> {
private getAlertTrackedEntity(alert: Alert): FutureData<D2TrackerTrackedEntity> {
return apiToFuture(
this.api.tracker.trackedEntities.get({
program: RTSL_ZEBRA_ALERTS_PROGRAM_ID,
Expand Down
39 changes: 38 additions & 1 deletion src/data/repositories/DiseaseOutbreakEventD2Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
getCasesDataValuesFromDiseaseOutbreak,
isStringInCasesDataCodes,
} from "./consts/CaseDataConstants";
import { OutbreakData, OutbreakDataType } from "../../domain/entities/alert/OutbreakAlert";

export class DiseaseOutbreakEventD2Repository implements DiseaseOutbreakEventRepository {
constructor(private api: D2Api) {}
Expand All @@ -53,7 +54,10 @@ export class DiseaseOutbreakEventD2Repository implements DiseaseOutbreakEventRep

getAll(): FutureData<DiseaseOutbreakEventBaseAttrs[]> {
return Future.fromPromise(
getAllTrackedEntitiesAsync(this.api, RTSL_ZEBRA_PROGRAM_ID, RTSL_ZEBRA_ORG_UNIT_ID)
getAllTrackedEntitiesAsync(this.api, {
programId: RTSL_ZEBRA_PROGRAM_ID,
orgUnitId: RTSL_ZEBRA_ORG_UNIT_ID,
})
).map(trackedEntities => {
return trackedEntities
.map(trackedEntity => {
Expand All @@ -63,6 +67,34 @@ export class DiseaseOutbreakEventD2Repository implements DiseaseOutbreakEventRep
});
}

getEventByDiseaseOrHazardType(
filter: OutbreakData
): FutureData<DiseaseOutbreakEventBaseAttrs[]> {
return Future.fromPromise(
getAllTrackedEntitiesAsync(this.api, {
programId: RTSL_ZEBRA_PROGRAM_ID,
orgUnitId: RTSL_ZEBRA_ORG_UNIT_ID,
filter: {
id: this.getDiseaseOutbreakFilterId(filter),
value: filter.value,
},
})
).map(trackedEntities => {
return trackedEntities.map(trackedEntity => {
return mapTrackedEntityAttributesToDiseaseOutbreak(trackedEntity);
});
});
}

private getDiseaseOutbreakFilterId(filter: OutbreakData): string {
const mapping: Record<OutbreakDataType, TrackedEntityAttributeId> = {
disease: RTSL_ZEBRA_DISEASE_TEA_ID,
hazard: RTSL_ZEBRA_HAZARD_TEA_ID,
};

return mapping[filter.type];
}

save(diseaseOutbreak: DiseaseOutbreakEvent, haveChangedCasesData?: boolean): FutureData<Id> {
const hasNewCasesData = !diseaseOutbreak.id && !!diseaseOutbreak.uploadedCasesData;

Expand Down Expand Up @@ -308,3 +340,8 @@ export class DiseaseOutbreakEventD2Repository implements DiseaseOutbreakEventRep

//TO DO : Implement delete/archive after requirement confirmation
}

const RTSL_ZEBRA_DISEASE_TEA_ID = "jLvbkuvPdZ6";
const RTSL_ZEBRA_HAZARD_TEA_ID = "Dzrw3Tf0ukB";

type TrackedEntityAttributeId = Id;
Loading

0 comments on commit 7a050ea

Please sign in to comment.