From 2f7013f5cfc30ca302093ece961980e063db3634 Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Wed, 12 Jun 2024 22:13:23 +0530
Subject: [PATCH 1/8] feat: Domain entities for zebra
---
index.html | 13 +-
package.json | 10 +-
src/domain/entities/DiseaseOutbreak.ts | 56 +++++++++
src/domain/entities/OrgUnit.ts | 7 ++
src/domain/entities/Properties.ts | 32 +++++
src/domain/entities/Ref.ts | 6 +
.../incident-action-plan/ActionPlan.ts | 8 ++
.../IncidentActionPlan.ts | 12 ++
.../incident-action-plan/ResponseAction.ts | 20 +++
.../IncidentManagementTeam.ts | 17 +++
.../incident-management-team/TeamMember.ts | 21 ++++
.../risk-assessment/RiskAssessment.ts | 12 ++
.../risk-assessment/RiskAssessmentGrading.ts | 118 ++++++++++++++++++
.../RiskAssessmentQuestionnaire.ts | 8 ++
.../risk-assessment/RiskAssessmentSummary.ts | 8 ++
.../__tests__/RiskAssessmentGrading.spec.ts | 94 ++++++++++++++
src/webapp/pages/app/__tests__/App.spec.tsx | 31 -----
17 files changed, 434 insertions(+), 39 deletions(-)
create mode 100644 src/domain/entities/DiseaseOutbreak.ts
create mode 100644 src/domain/entities/OrgUnit.ts
create mode 100644 src/domain/entities/Properties.ts
create mode 100644 src/domain/entities/incident-action-plan/ActionPlan.ts
create mode 100644 src/domain/entities/incident-action-plan/IncidentActionPlan.ts
create mode 100644 src/domain/entities/incident-action-plan/ResponseAction.ts
create mode 100644 src/domain/entities/incident-management-team/IncidentManagementTeam.ts
create mode 100644 src/domain/entities/incident-management-team/TeamMember.ts
create mode 100644 src/domain/entities/risk-assessment/RiskAssessment.ts
create mode 100644 src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
create mode 100644 src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts
create mode 100644 src/domain/entities/risk-assessment/RiskAssessmentSummary.ts
create mode 100644 src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
delete mode 100644 src/webapp/pages/app/__tests__/App.spec.tsx
diff --git a/index.html b/index.html
index 492d83db..1e5a8d80 100644
--- a/index.html
+++ b/index.html
@@ -4,15 +4,22 @@
-
+
-
+
-
Vite + React + TS
+ Zebra
diff --git a/package.json b/package.json
index 321eefa8..d5f49e60 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,13 @@
{
- "name": "dhis2-app-skeleton",
- "description": "DHIS2 Skeleton App",
+ "name": "zebra",
+ "description": "Zambia Emergency Bridge for Response Application",
"version": "0.0.1",
"license": "GPL-3.0",
"author": "EyeSeeTea team",
"homepage": ".",
"repository": {
"type": "git",
- "url": "git+https://github.com/eyeseetea/dhis2-app-skeleton.git"
+ "url": "git+https://github.com/eyeseetea/zebra-dev.git"
},
"dependencies": {
"@dhis2/app-runtime": "2.8.0",
@@ -108,8 +108,8 @@
"script-example": "npx ts-node src/scripts/example.ts"
},
"manifest.webapp": {
- "name": "DHIS2 Skeleton App",
- "description": "DHIS2 Skeleton App",
+ "name": "zebra",
+ "description": "Zambia Emergency Bridge for Response Application",
"icons": {
"48": "icon.png"
},
diff --git a/src/domain/entities/DiseaseOutbreak.ts b/src/domain/entities/DiseaseOutbreak.ts
new file mode 100644
index 00000000..5e67512c
--- /dev/null
+++ b/src/domain/entities/DiseaseOutbreak.ts
@@ -0,0 +1,56 @@
+//Note: DiseaseOutbreak represents Event in the Figma.
+//Not using event as it is a keyword and can also be confused with dhis event
+import { Struct } from "./generic/Struct";
+import { IncidentActionPlan } from "./incident-action-plan/IncidentActionPlan";
+import { IncidentManagementTeam } from "./incident-management-team/IncidentManagementTeam";
+import { TeamMember } from "./incident-management-team/TeamMember";
+import { OrgUnit } from "./OrgUnit";
+import { NamedRef, Option } from "./Ref";
+import { RiskAssessment } from "./risk-assessment/RiskAssessment";
+
+type HazardType =
+ | "Biological:Human"
+ | "Biological:Animal"
+ | "Chemical"
+ | "Environmental"
+ | "Unknown";
+
+type IncidentStatusType = "Watch" | "Alert" | "Respond" | "Closed" | "Discarded";
+
+type DateWithNarrative = {
+ date: Date;
+ narrative: string;
+};
+
+interface DiseaseOutbreakAttrs extends NamedRef {
+ created: Date;
+ lastUpdated: Date;
+ createdBy: TeamMember;
+ hazardType: HazardType;
+ mainSyndrome: Option;
+ suspectedDisease: Option;
+ notificationSource: Option;
+ areasAffected: {
+ provinces: OrgUnit[];
+ districts: OrgUnit[];
+ };
+ incidentStatus: IncidentStatusType;
+ dateEmerged: DateWithNarrative;
+ dateDetected: DateWithNarrative;
+ dateNotified: DateWithNarrative;
+ responseNarrative: string;
+ incidentManager: TeamMember;
+ notes: string;
+ //when should risk assessment, IAP,IMT be fetched? Only when the user clicks on the risk assessment tab?
+ //Can we async get only 1 property in a class?
+ riskAssessments: RiskAssessment[];
+ //we need only response actions property from IncidentActionPlan. How can we map that?
+ IncidentActionPlan: IncidentActionPlan;
+ IncidentManagementTeam: IncidentManagementTeam;
+}
+
+export class DiseaseOutbreak extends Struct() {
+ static validateEventName() {
+ //Ensure event name is unique on event creation.
+ }
+}
diff --git a/src/domain/entities/OrgUnit.ts b/src/domain/entities/OrgUnit.ts
new file mode 100644
index 00000000..6c5c0875
--- /dev/null
+++ b/src/domain/entities/OrgUnit.ts
@@ -0,0 +1,7 @@
+import { CodedNamedRef } from "./Ref";
+
+type OrgUnitLevelType = "Province" | "District";
+
+export interface OrgUnit extends CodedNamedRef {
+ level: OrgUnitLevelType;
+}
diff --git a/src/domain/entities/Properties.ts b/src/domain/entities/Properties.ts
new file mode 100644
index 00000000..492723f3
--- /dev/null
+++ b/src/domain/entities/Properties.ts
@@ -0,0 +1,32 @@
+//TO DO : Can there be a better name for a generic property?
+import { CodedNamedRef } from "./Ref";
+
+type PropertTypes = "string" | "date" | "number" | "boolean";
+
+//TO DO : what other attributes of a generic domain property?
+interface BaseProperty extends CodedNamedRef {
+ text: string; //or label or key?
+ type: PropertTypes;
+}
+
+interface StringProperty extends BaseProperty {
+ type: "string";
+ value: string;
+}
+
+interface DateProperty extends BaseProperty {
+ type: "date";
+ value: Date;
+}
+
+interface NumberProperty extends BaseProperty {
+ type: "number";
+ value: number;
+}
+
+interface BooleanProperty extends BaseProperty {
+ type: "boolean";
+ value: boolean;
+}
+
+export type Property = StringProperty | DateProperty | NumberProperty | BooleanProperty;
diff --git a/src/domain/entities/Ref.ts b/src/domain/entities/Ref.ts
index 8b95ca2f..bdd6e18d 100644
--- a/src/domain/entities/Ref.ts
+++ b/src/domain/entities/Ref.ts
@@ -7,3 +7,9 @@ export interface Ref {
export interface NamedRef extends Ref {
name: string;
}
+
+export interface CodedNamedRef extends NamedRef {
+ code: string;
+}
+
+export type Option = CodedNamedRef;
diff --git a/src/domain/entities/incident-action-plan/ActionPlan.ts b/src/domain/entities/incident-action-plan/ActionPlan.ts
new file mode 100644
index 00000000..09336e77
--- /dev/null
+++ b/src/domain/entities/incident-action-plan/ActionPlan.ts
@@ -0,0 +1,8 @@
+import { Property } from "../Properties";
+import { Struct } from "../generic/Struct";
+
+interface ActionPlanAttrs {
+ properties: Property[];
+}
+
+export class ActionPlan extends Struct() {}
diff --git a/src/domain/entities/incident-action-plan/IncidentActionPlan.ts b/src/domain/entities/incident-action-plan/IncidentActionPlan.ts
new file mode 100644
index 00000000..222a8df2
--- /dev/null
+++ b/src/domain/entities/incident-action-plan/IncidentActionPlan.ts
@@ -0,0 +1,12 @@
+import { ActionPlan } from "./ActionPlan";
+import { Ref } from "../Ref";
+import { Struct } from "../generic/Struct";
+import { ResponseAction } from "./ResponseAction";
+
+interface IncidentActionPlanAttrs extends Ref {
+ lastUpdated: Date;
+ actionPlan: ActionPlan;
+ responseActions: ResponseAction[];
+}
+
+export class IncidentActionPlan extends Struct() {}
diff --git a/src/domain/entities/incident-action-plan/ResponseAction.ts b/src/domain/entities/incident-action-plan/ResponseAction.ts
new file mode 100644
index 00000000..efac906d
--- /dev/null
+++ b/src/domain/entities/incident-action-plan/ResponseAction.ts
@@ -0,0 +1,20 @@
+import { Struct } from "../generic/Struct";
+import { TeamMember } from "../incident-management-team/TeamMember";
+import { Option } from "../Ref";
+
+//TO DO : Should this be Option?
+type ResponseActionStatusType = "Not done" | "Pending" | "In Progress" | "Complete";
+type ResponseActionVerificationType = "Verified" | "Unverified";
+
+interface ResponseActionAttrs {
+ mainTask: Option;
+ subActivities: string;
+ subPillar: Option;
+ responsibleOfficer: TeamMember;
+ dueDate: Date;
+ timeLine: Option;
+ status: ResponseActionStatusType;
+ verification: ResponseActionVerificationType;
+}
+
+export class ResponseAction extends Struct() {}
diff --git a/src/domain/entities/incident-management-team/IncidentManagementTeam.ts b/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
new file mode 100644
index 00000000..89532595
--- /dev/null
+++ b/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
@@ -0,0 +1,17 @@
+import { Struct } from "../generic/Struct";
+import { TeamMember } from "./TeamMember";
+
+interface TeamRole {
+ role: string;
+ level: number;
+}
+
+interface RoleTeamMemberMap {
+ role: TeamRole;
+ teamMember: TeamMember;
+}
+interface IncidentManagementTeamAttrs {
+ teamHeirarchy: RoleTeamMemberMap[]; //Is there a better way to represent heirarchy? Maybe a tree?
+}
+
+export class IncidentManagementTeam extends Struct() {}
diff --git a/src/domain/entities/incident-management-team/TeamMember.ts b/src/domain/entities/incident-management-team/TeamMember.ts
new file mode 100644
index 00000000..ede7e5fd
--- /dev/null
+++ b/src/domain/entities/incident-management-team/TeamMember.ts
@@ -0,0 +1,21 @@
+import { NamedRef } from "../Ref";
+import { Struct } from "../generic/Struct";
+
+type PhoneNumber = string;
+type Email = string;
+type IncidentManagerStatus = "Available" | "Unavailable";
+
+interface TeamMemberAttrs extends NamedRef {
+ position: string;
+ phone: PhoneNumber;
+ email: Email;
+ status: IncidentManagerStatus;
+ photo: string; //URL to photo
+}
+
+export class TeamMember extends Struct() {
+ static validatePhAndEmail() {
+ //TO DO : any validations for phone number?
+ //TO DO : any validations for email?
+ }
+}
diff --git a/src/domain/entities/risk-assessment/RiskAssessment.ts b/src/domain/entities/risk-assessment/RiskAssessment.ts
new file mode 100644
index 00000000..d2b5f63f
--- /dev/null
+++ b/src/domain/entities/risk-assessment/RiskAssessment.ts
@@ -0,0 +1,12 @@
+import { Struct } from "../generic/Struct";
+import { RiskAssessmentGrading } from "./RiskAssessmentGrading";
+import { RiskAssessmentQuestionnaire } from "./RiskAssessmentQuestionnaire";
+import { RiskAssessmentSummary } from "./RiskAssessmentSummary";
+
+interface RiskAssessmentAttrs {
+ riskAssessmentGrading: RiskAssessmentGrading[];
+ riskAssessmentSummary: RiskAssessmentSummary;
+ riskAssessmentQuestionnaire: RiskAssessmentQuestionnaire[];
+}
+
+export class RiskAssessment extends Struct() {}
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
new file mode 100644
index 00000000..a035c19a
--- /dev/null
+++ b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
@@ -0,0 +1,118 @@
+import { Ref } from "../Ref";
+import { Struct } from "../generic/Struct";
+
+type WeightedOptions = {
+ label: "Low" | "Medium" | "High";
+ weight: 1 | 2 | 3;
+};
+
+export const LowWeightedOption: WeightedOptions = {
+ label: "Low",
+ weight: 1,
+};
+export const MediumWeightedOption: WeightedOptions = {
+ label: "Medium",
+ weight: 2,
+};
+export const HighWeightedOption: WeightedOptions = {
+ label: "High",
+ weight: 3,
+};
+
+type PopulationWeightOptions = {
+ label: "Less than 0.1%" | "Between 0.1% to 0.25%" | "Above 0.25%";
+ weight: 1 | 2 | 3;
+};
+
+export const LowPopulationAtRisk: PopulationWeightOptions = {
+ label: "Less than 0.1%",
+ weight: 1,
+};
+export const MediumPopulationAtRisk: PopulationWeightOptions = {
+ label: "Between 0.1% to 0.25%",
+ weight: 2,
+};
+export const HighPopulationAtRisk: PopulationWeightOptions = {
+ label: "Above 0.25%",
+ weight: 3,
+};
+
+type GeographicalSpreadOptions = {
+ label:
+ | "Within a district"
+ | "Within a province with more than one district affected"
+ | "More than one province affected with high threat of spread locally and internationally";
+ weight: 1 | 2 | 3;
+};
+
+export const LowGeographicalSpread: GeographicalSpreadOptions = {
+ label: "Within a district",
+ weight: 1,
+};
+export const MediumGeographicalSpread: GeographicalSpreadOptions = {
+ label: "Within a province with more than one district affected",
+ weight: 2,
+};
+export const HighGeographicalSpread: GeographicalSpreadOptions = {
+ label: "More than one province affected with high threat of spread locally and internationally",
+ weight: 3,
+};
+
+type CapacityOptions = {
+ label:
+ | "Available within the district with support from provincial and national level "
+ | "Available within the province with minimal support from national level"
+ | " Available at national with support required from international";
+ weight: 1 | 2 | 3;
+};
+
+export const LowCapacity: CapacityOptions = {
+ label: "Available within the district with support from provincial and national level ",
+ weight: 1,
+};
+export const MediumCapacity: CapacityOptions = {
+ label: "Available within the province with minimal support from national level",
+ weight: 2,
+};
+export const HighCapacity: CapacityOptions = {
+ label: " Available at national with support required from international",
+ weight: 3,
+};
+
+export type Grade = "Grade 1" | "Grade 2" | "Grade 3";
+
+interface RiskAssessmentGradingAttrs extends Ref {
+ lastUpdated: Date;
+ populationAtRisk: PopulationWeightOptions;
+ attackRate: WeightedOptions;
+ geographicalSpread: GeographicalSpreadOptions;
+ complexity: WeightedOptions;
+ capacity: CapacityOptions;
+ reputationalRisk: WeightedOptions;
+ severity: WeightedOptions;
+ // capability: WeightedOptions;
+ grade?: Grade;
+}
+
+export class RiskAssessmentGrading extends Struct() {
+ calculateAndSetGrade(): void {
+ const totalWeight =
+ this.populationAtRisk.weight +
+ this.attackRate.weight +
+ this.geographicalSpread.weight +
+ this.complexity.weight +
+ this.capacity.weight +
+ this.reputationalRisk.weight +
+ this.severity.weight;
+ // this.capability.weight;
+
+ if (totalWeight > 21) throw new Error("Invalid grade");
+
+ this.grade =
+ totalWeight <= 7
+ ? "Grade 1"
+ : totalWeight > 7 && totalWeight <= 14
+ ? "Grade 2"
+ : "Grade 3";
+ }
+}
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts b/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts
new file mode 100644
index 00000000..4a77cab4
--- /dev/null
+++ b/src/domain/entities/risk-assessment/RiskAssessmentQuestionnaire.ts
@@ -0,0 +1,8 @@
+import { Property } from "../Properties";
+import { Struct } from "../generic/Struct";
+
+interface RiskAssessmentQuestionnaireAttrs {
+ questions: Property[];
+}
+
+export class RiskAssessmentQuestionnaire extends Struct() {}
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentSummary.ts b/src/domain/entities/risk-assessment/RiskAssessmentSummary.ts
new file mode 100644
index 00000000..21b26ce2
--- /dev/null
+++ b/src/domain/entities/risk-assessment/RiskAssessmentSummary.ts
@@ -0,0 +1,8 @@
+import { Property } from "../Properties";
+import { Struct } from "../generic/Struct";
+
+interface RiskAssessmentSummaryAttrs {
+ properties: Property[];
+}
+
+export class RiskAssessmentSummary extends Struct() {}
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
new file mode 100644
index 00000000..7631ff17
--- /dev/null
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -0,0 +1,94 @@
+import { describe, expect, it } from "vitest";
+import {
+ HighCapacity,
+ HighGeographicalSpread,
+ HighPopulationAtRisk,
+ HighWeightedOption,
+ LowCapacity,
+ LowGeographicalSpread,
+ LowPopulationAtRisk,
+ LowWeightedOption,
+ MediumCapacity,
+ MediumGeographicalSpread,
+ MediumPopulationAtRisk,
+ MediumWeightedOption,
+ RiskAssessmentGrading,
+} from "../RiskAssessmentGrading";
+
+describe("RiskAssessmentGrading", () => {
+ it("should be Grade1 if total weight is less than or equal to 7", () => {
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
+ id: "1",
+ lastUpdated: new Date(),
+ populationAtRisk: LowPopulationAtRisk,
+ attackRate: LowWeightedOption,
+ geographicalSpread: LowGeographicalSpread,
+ complexity: LowWeightedOption,
+ capacity: LowCapacity,
+ reputationalRisk: LowWeightedOption,
+ severity: LowWeightedOption,
+ // capability: LowWeightedOption,
+ });
+
+ riskAssessmentGrading.calculateAndSetGrade();
+
+ expect(riskAssessmentGrading.grade).toBe("Grade 1");
+ });
+
+ it("should be Grade2 if total weight is greater than 7 and less than equal to 14", () => {
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
+ id: "2",
+ lastUpdated: new Date(),
+ populationAtRisk: MediumPopulationAtRisk,
+ attackRate: MediumWeightedOption,
+ geographicalSpread: MediumGeographicalSpread,
+ complexity: MediumWeightedOption,
+ capacity: MediumCapacity,
+ reputationalRisk: MediumWeightedOption,
+ severity: MediumWeightedOption,
+ // capability: MediumWeightedOption,
+ });
+
+ riskAssessmentGrading.calculateAndSetGrade();
+
+ expect(riskAssessmentGrading.grade).toBe("Grade 2");
+ });
+
+ it("should be Grade3 if score is greater than 14", () => {
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
+ id: "3",
+ lastUpdated: new Date(),
+ populationAtRisk: HighPopulationAtRisk,
+ attackRate: HighWeightedOption,
+ geographicalSpread: HighGeographicalSpread,
+ complexity: HighWeightedOption,
+ capacity: HighCapacity,
+ reputationalRisk: HighWeightedOption,
+ severity: HighWeightedOption,
+ // capability: MediumWeightedOption,
+ });
+
+ riskAssessmentGrading.calculateAndSetGrade();
+
+ expect(riskAssessmentGrading.grade).toBe("Grade 3");
+ });
+
+ it("should be Grade3 if score is greater than 14", () => {
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
+ id: "4",
+ lastUpdated: new Date(),
+ populationAtRisk: LowPopulationAtRisk,
+ attackRate: MediumWeightedOption,
+ geographicalSpread: HighGeographicalSpread,
+ complexity: MediumWeightedOption,
+ capacity: LowCapacity,
+ reputationalRisk: HighWeightedOption,
+ severity: HighWeightedOption,
+ // capability: MediumWeightedOption,
+ });
+
+ riskAssessmentGrading.calculateAndSetGrade();
+
+ expect(riskAssessmentGrading.grade).toBe("Grade 3");
+ });
+});
diff --git a/src/webapp/pages/app/__tests__/App.spec.tsx b/src/webapp/pages/app/__tests__/App.spec.tsx
deleted file mode 100644
index 8a974586..00000000
--- a/src/webapp/pages/app/__tests__/App.spec.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { fireEvent, render } from "@testing-library/react";
-
-import App from "../App";
-import { getTestContext } from "../../../../utils/tests";
-import { Provider } from "@dhis2/app-runtime";
-
-describe("App", () => {
- it("renders the feedback component", async () => {
- const view = getView();
-
- expect(await view.findByText("Send feedback")).toBeInTheDocument();
- });
-
- it("navigates to page", async () => {
- const view = getView();
-
- fireEvent.click(await view.findByText("John"));
-
- expect(await view.findByText("Hello John")).toBeInTheDocument();
- expect(view.asFragment()).toMatchSnapshot();
- });
-});
-
-function getView() {
- const { compositionRoot } = getTestContext();
- return render(
-
-
-
- );
-}
From 11a8739553c4023989a7696e3c4c0e22840bd3b5 Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Thu, 20 Jun 2024 22:35:28 +0530
Subject: [PATCH 2/8] refactor: ensure create used for creation of objects
instead of new
---
src/domain/entities/generic/Struct.ts | 2 +-
.../risk-assessment/RiskAssessmentGrading.ts | 24 +++++++++++++------
.../__tests__/RiskAssessmentGrading.spec.ts | 16 ++++---------
3 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/src/domain/entities/generic/Struct.ts b/src/domain/entities/generic/Struct.ts
index cf4d9816..6e268007 100644
--- a/src/domain/entities/generic/Struct.ts
+++ b/src/domain/entities/generic/Struct.ts
@@ -15,7 +15,7 @@
export function Struct() {
abstract class Base {
- constructor(_attributes: Attrs) {
+ private constructor(_attributes: Attrs) {
Object.assign(this, _attributes);
}
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
index a035c19a..ee4c9ee5 100644
--- a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
+++ b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
@@ -95,7 +95,18 @@ interface RiskAssessmentGradingAttrs extends Ref {
}
export class RiskAssessmentGrading extends Struct() {
- calculateAndSetGrade(): void {
+ private constructor(attrs: RiskAssessmentGradingAttrs) {
+ super(attrs);
+ }
+
+ public static createAndCalculateGrade(
+ attrs: RiskAssessmentGradingAttrs
+ ): RiskAssessmentGrading {
+ const riskAssessmentGrading = new RiskAssessmentGrading(attrs);
+ return riskAssessmentGrading._update({ grade: riskAssessmentGrading.calculateGrade() });
+ }
+
+ calculateGrade(): Grade {
const totalWeight =
this.populationAtRisk.weight +
this.attackRate.weight +
@@ -108,11 +119,10 @@ export class RiskAssessmentGrading extends Struct()
if (totalWeight > 21) throw new Error("Invalid grade");
- this.grade =
- totalWeight <= 7
- ? "Grade 1"
- : totalWeight > 7 && totalWeight <= 14
- ? "Grade 2"
- : "Grade 3";
+ return totalWeight <= 7
+ ? "Grade 1"
+ : totalWeight > 7 && totalWeight <= 14
+ ? "Grade 2"
+ : "Grade 3";
}
}
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
index 7631ff17..2c94b7ea 100644
--- a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -17,7 +17,7 @@ import {
describe("RiskAssessmentGrading", () => {
it("should be Grade1 if total weight is less than or equal to 7", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.create({
+ const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
id: "1",
lastUpdated: new Date(),
populationAtRisk: LowPopulationAtRisk,
@@ -30,13 +30,11 @@ describe("RiskAssessmentGrading", () => {
// capability: LowWeightedOption,
});
- riskAssessmentGrading.calculateAndSetGrade();
-
expect(riskAssessmentGrading.grade).toBe("Grade 1");
});
it("should be Grade2 if total weight is greater than 7 and less than equal to 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.create({
+ const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
id: "2",
lastUpdated: new Date(),
populationAtRisk: MediumPopulationAtRisk,
@@ -49,13 +47,11 @@ describe("RiskAssessmentGrading", () => {
// capability: MediumWeightedOption,
});
- riskAssessmentGrading.calculateAndSetGrade();
-
expect(riskAssessmentGrading.grade).toBe("Grade 2");
});
it("should be Grade3 if score is greater than 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.create({
+ const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
id: "3",
lastUpdated: new Date(),
populationAtRisk: HighPopulationAtRisk,
@@ -68,13 +64,11 @@ describe("RiskAssessmentGrading", () => {
// capability: MediumWeightedOption,
});
- riskAssessmentGrading.calculateAndSetGrade();
-
expect(riskAssessmentGrading.grade).toBe("Grade 3");
});
it("should be Grade3 if score is greater than 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.create({
+ const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
id: "4",
lastUpdated: new Date(),
populationAtRisk: LowPopulationAtRisk,
@@ -87,8 +81,6 @@ describe("RiskAssessmentGrading", () => {
// capability: MediumWeightedOption,
});
- riskAssessmentGrading.calculateAndSetGrade();
-
expect(riskAssessmentGrading.grade).toBe("Grade 3");
});
});
From 3da15ace29d573731cc36afee9990a89be9b481d Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Wed, 26 Jun 2024 14:28:05 +0530
Subject: [PATCH 3/8] refactor: apply coding standards, define types
consistently
---
src/domain/entities/DiseaseOutbreak.ts | 35 ++++++++++---------
src/domain/entities/OrgUnit.ts | 4 +--
src/domain/entities/Properties.ts | 23 ++++++------
src/domain/entities/Ref.ts | 2 --
src/domain/entities/generic/Struct.ts | 7 +---
.../incident-action-plan/ResponseAction.ts | 14 ++++----
.../IncidentManagementTeam.ts | 8 ++---
.../incident-management-team/TeamMember.ts | 5 +--
.../risk-assessment/RiskAssessment.ts | 6 ++--
.../risk-assessment/RiskAssessmentGrading.ts | 20 +++++------
.../__tests__/RiskAssessmentGrading.spec.ts | 16 ++++-----
11 files changed, 67 insertions(+), 73 deletions(-)
diff --git a/src/domain/entities/DiseaseOutbreak.ts b/src/domain/entities/DiseaseOutbreak.ts
index 5e67512c..a6ccc6e4 100644
--- a/src/domain/entities/DiseaseOutbreak.ts
+++ b/src/domain/entities/DiseaseOutbreak.ts
@@ -1,11 +1,9 @@
-//Note: DiseaseOutbreak represents Event in the Figma.
-//Not using event as it is a keyword and can also be confused with dhis event
import { Struct } from "./generic/Struct";
import { IncidentActionPlan } from "./incident-action-plan/IncidentActionPlan";
import { IncidentManagementTeam } from "./incident-management-team/IncidentManagementTeam";
import { TeamMember } from "./incident-management-team/TeamMember";
import { OrgUnit } from "./OrgUnit";
-import { NamedRef, Option } from "./Ref";
+import { CodedNamedRef, NamedRef } from "./Ref";
import { RiskAssessment } from "./risk-assessment/RiskAssessment";
type HazardType =
@@ -22,35 +20,40 @@ type DateWithNarrative = {
narrative: string;
};
-interface DiseaseOutbreakAttrs extends NamedRef {
+type Syndrome = CodedNamedRef;
+type Disease = CodedNamedRef;
+type NotificationSource = CodedNamedRef;
+
+type DiseaseOutbreakEventAttrs = NamedRef & {
created: Date;
lastUpdated: Date;
createdBy: TeamMember;
hazardType: HazardType;
- mainSyndrome: Option;
- suspectedDisease: Option;
- notificationSource: Option;
+ mainSyndrome: Syndrome;
+ suspectedDisease: Disease;
+ notificationSource: NotificationSource;
areasAffected: {
provinces: OrgUnit[];
districts: OrgUnit[];
};
incidentStatus: IncidentStatusType;
- dateEmerged: DateWithNarrative;
- dateDetected: DateWithNarrative;
- dateNotified: DateWithNarrative;
+ emerged: DateWithNarrative;
+ detected: DateWithNarrative;
+ notified: DateWithNarrative;
responseNarrative: string;
incidentManager: TeamMember;
notes: string;
- //when should risk assessment, IAP,IMT be fetched? Only when the user clicks on the risk assessment tab?
- //Can we async get only 1 property in a class?
riskAssessments: RiskAssessment[];
- //we need only response actions property from IncidentActionPlan. How can we map that?
IncidentActionPlan: IncidentActionPlan;
IncidentManagementTeam: IncidentManagementTeam;
-}
+};
+/**
+ * Note: DiseaseOutbreak represents Event in the Figma.
+ * Not using event as it is a keyword and can also be confused with dhis event
+ **/
-export class DiseaseOutbreak extends Struct() {
+export class DiseaseOutbreakEvent extends Struct() {
static validateEventName() {
- //Ensure event name is unique on event creation.
+ //TO DO : Ensure event name is unique on event creation.
}
}
diff --git a/src/domain/entities/OrgUnit.ts b/src/domain/entities/OrgUnit.ts
index 6c5c0875..554c0721 100644
--- a/src/domain/entities/OrgUnit.ts
+++ b/src/domain/entities/OrgUnit.ts
@@ -2,6 +2,6 @@ import { CodedNamedRef } from "./Ref";
type OrgUnitLevelType = "Province" | "District";
-export interface OrgUnit extends CodedNamedRef {
+export type OrgUnit = CodedNamedRef & {
level: OrgUnitLevelType;
-}
+};
diff --git a/src/domain/entities/Properties.ts b/src/domain/entities/Properties.ts
index 492723f3..4fe8844a 100644
--- a/src/domain/entities/Properties.ts
+++ b/src/domain/entities/Properties.ts
@@ -1,32 +1,29 @@
-//TO DO : Can there be a better name for a generic property?
import { CodedNamedRef } from "./Ref";
type PropertTypes = "string" | "date" | "number" | "boolean";
-//TO DO : what other attributes of a generic domain property?
-interface BaseProperty extends CodedNamedRef {
- text: string; //or label or key?
+type BaseProperty = CodedNamedRef & {
type: PropertTypes;
-}
+};
-interface StringProperty extends BaseProperty {
+type StringProperty = BaseProperty & {
type: "string";
value: string;
-}
+};
-interface DateProperty extends BaseProperty {
+type DateProperty = BaseProperty & {
type: "date";
value: Date;
-}
+};
-interface NumberProperty extends BaseProperty {
+type NumberProperty = BaseProperty & {
type: "number";
value: number;
-}
+};
-interface BooleanProperty extends BaseProperty {
+type BooleanProperty = BaseProperty & {
type: "boolean";
value: boolean;
-}
+};
export type Property = StringProperty | DateProperty | NumberProperty | BooleanProperty;
diff --git a/src/domain/entities/Ref.ts b/src/domain/entities/Ref.ts
index bdd6e18d..922a5d18 100644
--- a/src/domain/entities/Ref.ts
+++ b/src/domain/entities/Ref.ts
@@ -11,5 +11,3 @@ export interface NamedRef extends Ref {
export interface CodedNamedRef extends NamedRef {
code: string;
}
-
-export type Option = CodedNamedRef;
diff --git a/src/domain/entities/generic/Struct.ts b/src/domain/entities/generic/Struct.ts
index 6e268007..5a01041e 100644
--- a/src/domain/entities/generic/Struct.ts
+++ b/src/domain/entities/generic/Struct.ts
@@ -15,7 +15,7 @@
export function Struct() {
abstract class Base {
- private constructor(_attributes: Attrs) {
+ protected constructor(_attributes: Attrs) {
Object.assign(this, _attributes);
}
@@ -28,15 +28,10 @@ export function Struct() {
const ParentClass = this.constructor as new (values: Attrs) => typeof this;
return new ParentClass({ ...this._getAttributes(), ...partialAttrs });
}
-
- static create(this: new (attrs: Attrs) => U, attrs: Attrs): U {
- return new this(attrs);
- }
}
return Base as {
new (values: Attrs): Attrs & Base;
- create: (typeof Base)["create"];
};
}
diff --git a/src/domain/entities/incident-action-plan/ResponseAction.ts b/src/domain/entities/incident-action-plan/ResponseAction.ts
index efac906d..1d2c268c 100644
--- a/src/domain/entities/incident-action-plan/ResponseAction.ts
+++ b/src/domain/entities/incident-action-plan/ResponseAction.ts
@@ -1,18 +1,20 @@
+import { CodedNamedRef } from "../Ref";
import { Struct } from "../generic/Struct";
import { TeamMember } from "../incident-management-team/TeamMember";
-import { Option } from "../Ref";
-//TO DO : Should this be Option?
-type ResponseActionStatusType = "Not done" | "Pending" | "In Progress" | "Complete";
+type ResponseActionStatusType = "NotDone" | "Pending" | "InProgress" | "Complete";
type ResponseActionVerificationType = "Verified" | "Unverified";
+type MainTask = CodedNamedRef;
+type SubPillar = CodedNamedRef;
+type TimeLine = CodedNamedRef;
interface ResponseActionAttrs {
- mainTask: Option;
+ mainTask: MainTask;
subActivities: string;
- subPillar: Option;
+ subPillar: SubPillar;
responsibleOfficer: TeamMember;
dueDate: Date;
- timeLine: Option;
+ timeLine: TimeLine;
status: ResponseActionStatusType;
verification: ResponseActionVerificationType;
}
diff --git a/src/domain/entities/incident-management-team/IncidentManagementTeam.ts b/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
index 89532595..ba0b2832 100644
--- a/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
+++ b/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
@@ -1,17 +1,17 @@
+import { NamedRef } from "../Ref";
import { Struct } from "../generic/Struct";
import { TeamMember } from "./TeamMember";
-interface TeamRole {
- role: string;
+type TeamRole = NamedRef & {
level: number;
-}
+};
interface RoleTeamMemberMap {
role: TeamRole;
teamMember: TeamMember;
}
interface IncidentManagementTeamAttrs {
- teamHeirarchy: RoleTeamMemberMap[]; //Is there a better way to represent heirarchy? Maybe a tree?
+ teamHierarchy: RoleTeamMemberMap[];
}
export class IncidentManagementTeam extends Struct() {}
diff --git a/src/domain/entities/incident-management-team/TeamMember.ts b/src/domain/entities/incident-management-team/TeamMember.ts
index ede7e5fd..15d3a98b 100644
--- a/src/domain/entities/incident-management-team/TeamMember.ts
+++ b/src/domain/entities/incident-management-team/TeamMember.ts
@@ -4,13 +4,14 @@ import { Struct } from "../generic/Struct";
type PhoneNumber = string;
type Email = string;
type IncidentManagerStatus = "Available" | "Unavailable";
+type Postion = string; //TO DO : make a list once available from client.
interface TeamMemberAttrs extends NamedRef {
- position: string;
+ position: Postion;
phone: PhoneNumber;
email: Email;
status: IncidentManagerStatus;
- photo: string; //URL to photo
+ photo: URL;
}
export class TeamMember extends Struct() {
diff --git a/src/domain/entities/risk-assessment/RiskAssessment.ts b/src/domain/entities/risk-assessment/RiskAssessment.ts
index d2b5f63f..1a3fd827 100644
--- a/src/domain/entities/risk-assessment/RiskAssessment.ts
+++ b/src/domain/entities/risk-assessment/RiskAssessment.ts
@@ -4,9 +4,9 @@ import { RiskAssessmentQuestionnaire } from "./RiskAssessmentQuestionnaire";
import { RiskAssessmentSummary } from "./RiskAssessmentSummary";
interface RiskAssessmentAttrs {
- riskAssessmentGrading: RiskAssessmentGrading[];
- riskAssessmentSummary: RiskAssessmentSummary;
- riskAssessmentQuestionnaire: RiskAssessmentQuestionnaire[];
+ grading: RiskAssessmentGrading[];
+ summary: RiskAssessmentSummary;
+ questionnaire: RiskAssessmentQuestionnaire[];
}
export class RiskAssessment extends Struct() {}
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
index ee4c9ee5..92d9be49 100644
--- a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
+++ b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
@@ -1,5 +1,7 @@
+import i18n from "@eyeseetea/feedback-component/locales";
import { Ref } from "../Ref";
import { Struct } from "../generic/Struct";
+import { Maybe } from "../../../utils/ts-utils";
type WeightedOptions = {
label: "Low" | "Medium" | "High";
@@ -60,14 +62,14 @@ export const HighGeographicalSpread: GeographicalSpreadOptions = {
type CapacityOptions = {
label:
- | "Available within the district with support from provincial and national level "
+ | "Available within the district with support from provincial and national level"
| "Available within the province with minimal support from national level"
- | " Available at national with support required from international";
+ | "Available at national with support required from international";
weight: 1 | 2 | 3;
};
export const LowCapacity: CapacityOptions = {
- label: "Available within the district with support from provincial and national level ",
+ label: "Available within the district with support from provincial and national level",
weight: 1,
};
export const MediumCapacity: CapacityOptions = {
@@ -75,7 +77,7 @@ export const MediumCapacity: CapacityOptions = {
weight: 2,
};
export const HighCapacity: CapacityOptions = {
- label: " Available at national with support required from international",
+ label: "Available at national with support required from international",
weight: 3,
};
@@ -90,8 +92,7 @@ interface RiskAssessmentGradingAttrs extends Ref {
capacity: CapacityOptions;
reputationalRisk: WeightedOptions;
severity: WeightedOptions;
- // capability: WeightedOptions;
- grade?: Grade;
+ grade: Maybe;
}
export class RiskAssessmentGrading extends Struct() {
@@ -99,9 +100,7 @@ export class RiskAssessmentGrading extends Struct()
super(attrs);
}
- public static createAndCalculateGrade(
- attrs: RiskAssessmentGradingAttrs
- ): RiskAssessmentGrading {
+ public static create(attrs: RiskAssessmentGradingAttrs): RiskAssessmentGrading {
const riskAssessmentGrading = new RiskAssessmentGrading(attrs);
return riskAssessmentGrading._update({ grade: riskAssessmentGrading.calculateGrade() });
}
@@ -115,9 +114,8 @@ export class RiskAssessmentGrading extends Struct()
this.capacity.weight +
this.reputationalRisk.weight +
this.severity.weight;
- // this.capability.weight;
- if (totalWeight > 21) throw new Error("Invalid grade");
+ if (totalWeight > 21) throw new Error(i18n.t("Invalid grade"));
return totalWeight <= 7
? "Grade 1"
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
index 2c94b7ea..af543c81 100644
--- a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -17,7 +17,7 @@ import {
describe("RiskAssessmentGrading", () => {
it("should be Grade1 if total weight is less than or equal to 7", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "1",
lastUpdated: new Date(),
populationAtRisk: LowPopulationAtRisk,
@@ -27,14 +27,14 @@ describe("RiskAssessmentGrading", () => {
capacity: LowCapacity,
reputationalRisk: LowWeightedOption,
severity: LowWeightedOption,
- // capability: LowWeightedOption,
+ grade: undefined,
});
expect(riskAssessmentGrading.grade).toBe("Grade 1");
});
it("should be Grade2 if total weight is greater than 7 and less than equal to 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "2",
lastUpdated: new Date(),
populationAtRisk: MediumPopulationAtRisk,
@@ -44,14 +44,14 @@ describe("RiskAssessmentGrading", () => {
capacity: MediumCapacity,
reputationalRisk: MediumWeightedOption,
severity: MediumWeightedOption,
- // capability: MediumWeightedOption,
+ grade: undefined,
});
expect(riskAssessmentGrading.grade).toBe("Grade 2");
});
it("should be Grade3 if score is greater than 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "3",
lastUpdated: new Date(),
populationAtRisk: HighPopulationAtRisk,
@@ -61,14 +61,14 @@ describe("RiskAssessmentGrading", () => {
capacity: HighCapacity,
reputationalRisk: HighWeightedOption,
severity: HighWeightedOption,
- // capability: MediumWeightedOption,
+ grade: undefined,
});
expect(riskAssessmentGrading.grade).toBe("Grade 3");
});
it("should be Grade3 if score is greater than 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.createAndCalculateGrade({
+ const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "4",
lastUpdated: new Date(),
populationAtRisk: LowPopulationAtRisk,
@@ -78,7 +78,7 @@ describe("RiskAssessmentGrading", () => {
capacity: LowCapacity,
reputationalRisk: HighWeightedOption,
severity: HighWeightedOption,
- // capability: MediumWeightedOption,
+ grade: undefined,
});
expect(riskAssessmentGrading.grade).toBe("Grade 3");
From bf6384733004d96e168465b93bbddd4d57375715 Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Fri, 28 Jun 2024 13:57:11 +0530
Subject: [PATCH 4/8] refactor: file name change, getGrade as readonly, use
Either for error, add role to team member
---
...aseOutbreak.ts => DiseaseOutbreakEvent.ts} | 3 +-
.../IncidentManagementTeam.ts | 11 +-------
.../incident-management-team/TeamMember.ts | 7 +++--
.../risk-assessment/RiskAssessmentGrading.ts | 28 +++++++++++--------
.../__tests__/RiskAssessmentGrading.spec.ts | 18 ++++++------
5 files changed, 32 insertions(+), 35 deletions(-)
rename src/domain/entities/{DiseaseOutbreak.ts => DiseaseOutbreakEvent.ts} (96%)
diff --git a/src/domain/entities/DiseaseOutbreak.ts b/src/domain/entities/DiseaseOutbreakEvent.ts
similarity index 96%
rename from src/domain/entities/DiseaseOutbreak.ts
rename to src/domain/entities/DiseaseOutbreakEvent.ts
index a6ccc6e4..62bd4e29 100644
--- a/src/domain/entities/DiseaseOutbreak.ts
+++ b/src/domain/entities/DiseaseOutbreakEvent.ts
@@ -5,6 +5,7 @@ import { TeamMember } from "./incident-management-team/TeamMember";
import { OrgUnit } from "./OrgUnit";
import { CodedNamedRef, NamedRef } from "./Ref";
import { RiskAssessment } from "./risk-assessment/RiskAssessment";
+import { Maybe } from "../../utils/ts-utils";
type HazardType =
| "Biological:Human"
@@ -42,7 +43,7 @@ type DiseaseOutbreakEventAttrs = NamedRef & {
notified: DateWithNarrative;
responseNarrative: string;
incidentManager: TeamMember;
- notes: string;
+ notes: Maybe;
riskAssessments: RiskAssessment[];
IncidentActionPlan: IncidentActionPlan;
IncidentManagementTeam: IncidentManagementTeam;
diff --git a/src/domain/entities/incident-management-team/IncidentManagementTeam.ts b/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
index ba0b2832..cb9298bf 100644
--- a/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
+++ b/src/domain/entities/incident-management-team/IncidentManagementTeam.ts
@@ -1,17 +1,8 @@
-import { NamedRef } from "../Ref";
import { Struct } from "../generic/Struct";
import { TeamMember } from "./TeamMember";
-type TeamRole = NamedRef & {
- level: number;
-};
-
-interface RoleTeamMemberMap {
- role: TeamRole;
- teamMember: TeamMember;
-}
interface IncidentManagementTeamAttrs {
- teamHierarchy: RoleTeamMemberMap[];
+ teamHierarchy: TeamMember[];
}
export class IncidentManagementTeam extends Struct() {}
diff --git a/src/domain/entities/incident-management-team/TeamMember.ts b/src/domain/entities/incident-management-team/TeamMember.ts
index 15d3a98b..4e77678e 100644
--- a/src/domain/entities/incident-management-team/TeamMember.ts
+++ b/src/domain/entities/incident-management-team/TeamMember.ts
@@ -4,14 +4,17 @@ import { Struct } from "../generic/Struct";
type PhoneNumber = string;
type Email = string;
type IncidentManagerStatus = "Available" | "Unavailable";
-type Postion = string; //TO DO : make a list once available from client.
+
+export type TeamRole = NamedRef & {
+ level: number;
+};
interface TeamMemberAttrs extends NamedRef {
- position: Postion;
phone: PhoneNumber;
email: Email;
status: IncidentManagerStatus;
photo: URL;
+ role: TeamRole;
}
export class TeamMember extends Struct() {
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
index 92d9be49..b81ba2eb 100644
--- a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
+++ b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
@@ -1,13 +1,12 @@
import i18n from "@eyeseetea/feedback-component/locales";
import { Ref } from "../Ref";
import { Struct } from "../generic/Struct";
-import { Maybe } from "../../../utils/ts-utils";
+import { Either } from "../generic/Either";
type WeightedOptions = {
label: "Low" | "Medium" | "High";
weight: 1 | 2 | 3;
};
-
export const LowWeightedOption: WeightedOptions = {
label: "Low",
weight: 1,
@@ -92,7 +91,6 @@ interface RiskAssessmentGradingAttrs extends Ref {
capacity: CapacityOptions;
reputationalRisk: WeightedOptions;
severity: WeightedOptions;
- grade: Maybe;
}
export class RiskAssessmentGrading extends Struct() {
@@ -101,11 +99,14 @@ export class RiskAssessmentGrading extends Struct()
}
public static create(attrs: RiskAssessmentGradingAttrs): RiskAssessmentGrading {
- const riskAssessmentGrading = new RiskAssessmentGrading(attrs);
- return riskAssessmentGrading._update({ grade: riskAssessmentGrading.calculateGrade() });
+ return new RiskAssessmentGrading(attrs);
}
- calculateGrade(): Grade {
+ getGrade = (): Either => {
+ return this.calculateGrade();
+ };
+
+ calculateGrade(): Either {
const totalWeight =
this.populationAtRisk.weight +
this.attackRate.weight +
@@ -115,12 +116,15 @@ export class RiskAssessmentGrading extends Struct()
this.reputationalRisk.weight +
this.severity.weight;
- if (totalWeight > 21) throw new Error(i18n.t("Invalid grade"));
+ if (totalWeight > 21) return Either.error(new Error(i18n.t("Invalid grade")));
+
+ const grade: Grade =
+ totalWeight <= 7
+ ? "Grade 1"
+ : totalWeight > 7 && totalWeight <= 14
+ ? "Grade 2"
+ : "Grade 3";
- return totalWeight <= 7
- ? "Grade 1"
- : totalWeight > 7 && totalWeight <= 14
- ? "Grade 2"
- : "Grade 3";
+ return Either.success(grade);
}
}
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
index af543c81..d1564b7a 100644
--- a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -27,10 +27,9 @@ describe("RiskAssessmentGrading", () => {
capacity: LowCapacity,
reputationalRisk: LowWeightedOption,
severity: LowWeightedOption,
- grade: undefined,
});
-
- expect(riskAssessmentGrading.grade).toBe("Grade 1");
+ const grade = riskAssessmentGrading.getGrade().value.data;
+ expect(grade).toBe("Grade 1");
});
it("should be Grade2 if total weight is greater than 7 and less than equal to 14", () => {
@@ -44,10 +43,9 @@ describe("RiskAssessmentGrading", () => {
capacity: MediumCapacity,
reputationalRisk: MediumWeightedOption,
severity: MediumWeightedOption,
- grade: undefined,
});
-
- expect(riskAssessmentGrading.grade).toBe("Grade 2");
+ const grade = riskAssessmentGrading.getGrade().value.data;
+ expect(grade).toBe("Grade 2");
});
it("should be Grade3 if score is greater than 14", () => {
@@ -61,10 +59,10 @@ describe("RiskAssessmentGrading", () => {
capacity: HighCapacity,
reputationalRisk: HighWeightedOption,
severity: HighWeightedOption,
- grade: undefined,
});
- expect(riskAssessmentGrading.grade).toBe("Grade 3");
+ const grade = riskAssessmentGrading.getGrade().value.data;
+ expect(grade).toBe("Grade 3");
});
it("should be Grade3 if score is greater than 14", () => {
@@ -78,9 +76,9 @@ describe("RiskAssessmentGrading", () => {
capacity: LowCapacity,
reputationalRisk: HighWeightedOption,
severity: HighWeightedOption,
- grade: undefined,
});
- expect(riskAssessmentGrading.grade).toBe("Grade 3");
+ const grade = riskAssessmentGrading.getGrade().value.data;
+ expect(grade).toBe("Grade 3");
});
});
From 6cb5ff53f0a3cc4f5553940a73f183c1b01dca80 Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Mon, 1 Jul 2024 07:36:11 +0530
Subject: [PATCH 5/8] fix: translate labels in risk grading
---
i18n/en.pot | 56 ++++++++++-
i18n/es.po | 53 +++++++++-
.../risk-assessment/RiskAssessmentGrading.ts | 97 +++++++++++++------
.../__tests__/RiskAssessmentGrading.spec.ts | 23 +----
4 files changed, 177 insertions(+), 52 deletions(-)
diff --git a/i18n/en.pot b/i18n/en.pot
index 1ad98c3d..cab25e00 100644
--- a/i18n/en.pot
+++ b/i18n/en.pot
@@ -5,8 +5,60 @@ 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: 2023-09-18T13:40:05.079Z\n"
-"PO-Revision-Date: 2023-09-18T13:40:05.079Z\n"
+"POT-Creation-Date: 2024-07-01T02:04:44.570Z\n"
+"PO-Revision-Date: 2024-07-01T02:04:44.570Z\n"
+
+msgid "Low"
+msgstr ""
+
+msgid "Medium"
+msgstr ""
+
+msgid "High"
+msgstr ""
+
+msgid "Less than 0.1%"
+msgstr ""
+
+msgid "Between 0.1% to 0.25%"
+msgstr ""
+
+msgid "Above 0.25%"
+msgstr ""
+
+msgid "Within a district"
+msgstr ""
+
+msgid "Within a province with more than one district affected"
+msgstr ""
+
+msgid ""
+"More than one province affected with high threat of spread locally and "
+"internationally"
+msgstr ""
+
+msgid ""
+"Available within the district with support from provincial and national "
+"level"
+msgstr ""
+
+msgid "Available within the province with minimal support from national level"
+msgstr ""
+
+msgid "Available at national with support required from international"
+msgstr ""
+
+msgid "Grade 1"
+msgstr ""
+
+msgid "Grade 2"
+msgstr ""
+
+msgid "Grade 3"
+msgstr ""
+
+msgid "Invalid grade"
+msgstr ""
msgid "Add"
msgstr ""
diff --git a/i18n/es.po b/i18n/es.po
index 0250fb5a..2de05644 100644
--- a/i18n/es.po
+++ b/i18n/es.po
@@ -1,13 +1,64 @@
msgid ""
msgstr ""
"Project-Id-Version: i18next-conv\n"
-"POT-Creation-Date: 2023-09-18T10:19:02.458Z\n"
+"POT-Creation-Date: 2024-07-01T02:04:44.570Z\n"
"PO-Revision-Date: 2018-10-25T09:02:35.143Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+msgid "Low"
+msgstr ""
+
+msgid "Medium"
+msgstr ""
+
+msgid "High"
+msgstr ""
+
+msgid "Less than 0.1%"
+msgstr ""
+
+msgid "Between 0.1% to 0.25%"
+msgstr ""
+
+msgid "Above 0.25%"
+msgstr ""
+
+msgid "Within a district"
+msgstr ""
+
+msgid "Within a province with more than one district affected"
+msgstr ""
+
+msgid ""
+"More than one province affected with high threat of spread locally and "
+"internationally"
+msgstr ""
+
+msgid ""
+"Available within the district with support from provincial and national level"
+msgstr ""
+
+msgid "Available within the province with minimal support from national level"
+msgstr ""
+
+msgid "Available at national with support required from international"
+msgstr ""
+
+msgid "Grade 1"
+msgstr ""
+
+msgid "Grade 2"
+msgstr ""
+
+msgid "Grade 3"
+msgstr ""
+
+msgid "Invalid grade"
+msgstr ""
+
msgid "Add"
msgstr "AƱadir"
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
index b81ba2eb..8acc5b96 100644
--- a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
+++ b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
@@ -3,84 +3,119 @@ import { Ref } from "../Ref";
import { Struct } from "../generic/Struct";
import { Either } from "../generic/Either";
+type WeightedOptionTypes = "Low" | "Medium" | "High";
+type PopulationWeightOptionsTypes = "LessPercentage" | "MediumPercentage" | "HighPercentage";
+type GeographicalSpreadOptionsTypes =
+ | "WithinDistrict"
+ | "MoretThanOneDistrict"
+ | "MoreThanOneProvince";
+type CapacityOptionsTypes =
+ | "ProvincialNationalLevel"
+ | "ProvincialLevel"
+ | "NationalInternationalLevel";
+
type WeightedOptions = {
- label: "Low" | "Medium" | "High";
+ type: WeightedOptionTypes;
weight: 1 | 2 | 3;
};
export const LowWeightedOption: WeightedOptions = {
- label: "Low",
+ type: "Low",
weight: 1,
};
export const MediumWeightedOption: WeightedOptions = {
- label: "Medium",
+ type: "Medium",
weight: 2,
};
export const HighWeightedOption: WeightedOptions = {
- label: "High",
+ type: "High",
weight: 3,
};
type PopulationWeightOptions = {
- label: "Less than 0.1%" | "Between 0.1% to 0.25%" | "Above 0.25%";
+ type: PopulationWeightOptionsTypes;
weight: 1 | 2 | 3;
};
-
export const LowPopulationAtRisk: PopulationWeightOptions = {
- label: "Less than 0.1%",
+ type: "LessPercentage",
weight: 1,
};
export const MediumPopulationAtRisk: PopulationWeightOptions = {
- label: "Between 0.1% to 0.25%",
+ type: "MediumPercentage",
weight: 2,
};
export const HighPopulationAtRisk: PopulationWeightOptions = {
- label: "Above 0.25%",
+ type: "HighPercentage",
weight: 3,
};
type GeographicalSpreadOptions = {
- label:
- | "Within a district"
- | "Within a province with more than one district affected"
- | "More than one province affected with high threat of spread locally and internationally";
+ type: GeographicalSpreadOptionsTypes;
weight: 1 | 2 | 3;
};
-
export const LowGeographicalSpread: GeographicalSpreadOptions = {
- label: "Within a district",
+ type: "WithinDistrict",
weight: 1,
};
export const MediumGeographicalSpread: GeographicalSpreadOptions = {
- label: "Within a province with more than one district affected",
+ type: "MoretThanOneDistrict",
weight: 2,
};
export const HighGeographicalSpread: GeographicalSpreadOptions = {
- label: "More than one province affected with high threat of spread locally and internationally",
+ type: "MoreThanOneProvince",
weight: 3,
};
type CapacityOptions = {
- label:
- | "Available within the district with support from provincial and national level"
- | "Available within the province with minimal support from national level"
- | "Available at national with support required from international";
+ type: CapacityOptionsTypes;
weight: 1 | 2 | 3;
};
-
export const LowCapacity: CapacityOptions = {
- label: "Available within the district with support from provincial and national level",
+ type: "ProvincialNationalLevel",
weight: 1,
};
export const MediumCapacity: CapacityOptions = {
- label: "Available within the province with minimal support from national level",
+ type: "ProvincialLevel",
weight: 2,
};
export const HighCapacity: CapacityOptions = {
- label: "Available at national with support required from international",
+ type: "NationalInternationalLevel",
weight: 3,
};
-export type Grade = "Grade 1" | "Grade 2" | "Grade 3";
+export type Grade = "Grade1" | "Grade2" | "Grade3";
+
+type AllOptionTypes =
+ | WeightedOptionTypes
+ | PopulationWeightOptionsTypes
+ | GeographicalSpreadOptionsTypes
+ | CapacityOptionsTypes
+ | Grade;
+
+const translations: Record = {
+ Low: i18n.t("Low"),
+ Medium: i18n.t("Medium"),
+ High: i18n.t("High"),
+ LessPercentage: i18n.t("Less than 0.1%"),
+ MediumPercentage: i18n.t("Between 0.1% to 0.25%"),
+ HighPercentage: i18n.t("Above 0.25%"),
+ WithinDistrict: i18n.t("Within a district"),
+ MoretThanOneDistrict: i18n.t("Within a province with more than one district affected"),
+ MoreThanOneProvince: i18n.t(
+ "More than one province affected with high threat of spread locally and internationally"
+ ),
+ ProvincialNationalLevel: i18n.t(
+ "Available within the district with support from provincial and national level"
+ ),
+ ProvincialLevel: i18n.t(
+ "Available within the province with minimal support from national level"
+ ),
+ NationalInternationalLevel: i18n.t(
+ "Available at national with support required from international"
+ ),
+ Grade1: i18n.t("Grade 1"),
+ Grade2: i18n.t("Grade 2"),
+ Grade3: i18n.t("Grade 3"),
+};
interface RiskAssessmentGradingAttrs extends Ref {
lastUpdated: Date;
@@ -102,6 +137,10 @@ export class RiskAssessmentGrading extends Struct()
return new RiskAssessmentGrading(attrs);
}
+ public static getTranslatedLabel(key: AllOptionTypes): string {
+ return translations[key];
+ }
+
getGrade = (): Either => {
return this.calculateGrade();
};
@@ -120,10 +159,10 @@ export class RiskAssessmentGrading extends Struct()
const grade: Grade =
totalWeight <= 7
- ? "Grade 1"
+ ? "Grade1"
: totalWeight > 7 && totalWeight <= 14
- ? "Grade 2"
- : "Grade 3";
+ ? "Grade2"
+ : "Grade3";
return Either.success(grade);
}
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
index d1564b7a..3296b142 100644
--- a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -29,7 +29,7 @@ describe("RiskAssessmentGrading", () => {
severity: LowWeightedOption,
});
const grade = riskAssessmentGrading.getGrade().value.data;
- expect(grade).toBe("Grade 1");
+ if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 1");
});
it("should be Grade2 if total weight is greater than 7 and less than equal to 14", () => {
@@ -45,7 +45,7 @@ describe("RiskAssessmentGrading", () => {
severity: MediumWeightedOption,
});
const grade = riskAssessmentGrading.getGrade().value.data;
- expect(grade).toBe("Grade 2");
+ if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 2");
});
it("should be Grade3 if score is greater than 14", () => {
@@ -62,23 +62,6 @@ describe("RiskAssessmentGrading", () => {
});
const grade = riskAssessmentGrading.getGrade().value.data;
- expect(grade).toBe("Grade 3");
- });
-
- it("should be Grade3 if score is greater than 14", () => {
- const riskAssessmentGrading = RiskAssessmentGrading.create({
- id: "4",
- lastUpdated: new Date(),
- populationAtRisk: LowPopulationAtRisk,
- attackRate: MediumWeightedOption,
- geographicalSpread: HighGeographicalSpread,
- complexity: MediumWeightedOption,
- capacity: LowCapacity,
- reputationalRisk: HighWeightedOption,
- severity: HighWeightedOption,
- });
-
- const grade = riskAssessmentGrading.getGrade().value.data;
- expect(grade).toBe("Grade 3");
+ if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 3");
});
});
From 40a3647ba464d1fef96cb69d8d22b02ffebcd000 Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Mon, 1 Jul 2024 17:45:25 +0530
Subject: [PATCH 6/8] refactor: couple type and weight for options
---
src/domain/entities/DiseaseOutbreakEvent.ts | 2 +-
src/domain/entities/generic/Either.ts | 7 ++
.../risk-assessment/RiskAssessmentGrading.ts | 106 ++++++++----------
.../__tests__/RiskAssessmentGrading.spec.ts | 35 +++---
4 files changed, 70 insertions(+), 80 deletions(-)
diff --git a/src/domain/entities/DiseaseOutbreakEvent.ts b/src/domain/entities/DiseaseOutbreakEvent.ts
index 62bd4e29..ad19ab9f 100644
--- a/src/domain/entities/DiseaseOutbreakEvent.ts
+++ b/src/domain/entities/DiseaseOutbreakEvent.ts
@@ -49,7 +49,7 @@ type DiseaseOutbreakEventAttrs = NamedRef & {
IncidentManagementTeam: IncidentManagementTeam;
};
/**
- * Note: DiseaseOutbreak represents Event in the Figma.
+ * Note: DiseaseOutbreakEvent represents Event in the Figma.
* Not using event as it is a keyword and can also be confused with dhis event
**/
diff --git a/src/domain/entities/generic/Either.ts b/src/domain/entities/generic/Either.ts
index 33234090..ecca6888 100644
--- a/src/domain/entities/generic/Either.ts
+++ b/src/domain/entities/generic/Either.ts
@@ -17,6 +17,13 @@
export class Either {
constructor(public value: EitherValue) {}
+ getOrThrow(): Data | undefined {
+ if (this.isError()) {
+ throw this.value.error;
+ }
+ return this.value.data;
+ }
+
match(matchObj: MatchObject): Res {
switch (this.value.type) {
case "success":
diff --git a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
index 8acc5b96..3b053d60 100644
--- a/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
+++ b/src/domain/entities/risk-assessment/RiskAssessmentGrading.ts
@@ -14,72 +14,56 @@ type CapacityOptionsTypes =
| "ProvincialLevel"
| "NationalInternationalLevel";
-type WeightedOptions = {
- type: WeightedOptionTypes;
- weight: 1 | 2 | 3;
+export type LowWeightedOption = {
+ type: "Low";
+ weight: 1;
};
-export const LowWeightedOption: WeightedOptions = {
- type: "Low",
- weight: 1,
+export type MediumWeightedOption = {
+ type: "Medium";
+ weight: 2;
};
-export const MediumWeightedOption: WeightedOptions = {
- type: "Medium",
- weight: 2,
-};
-export const HighWeightedOption: WeightedOptions = {
- type: "High",
- weight: 3,
+export type HighWeightedOption = {
+ type: "High";
+ weight: 3;
};
-type PopulationWeightOptions = {
- type: PopulationWeightOptionsTypes;
- weight: 1 | 2 | 3;
-};
-export const LowPopulationAtRisk: PopulationWeightOptions = {
- type: "LessPercentage",
- weight: 1,
+export type LowPopulationAtRisk = {
+ type: "LessPercentage";
+ weight: 1;
};
-export const MediumPopulationAtRisk: PopulationWeightOptions = {
- type: "MediumPercentage",
- weight: 2,
+export type MediumPopulationAtRisk = {
+ type: "MediumPercentage";
+ weight: 2;
};
-export const HighPopulationAtRisk: PopulationWeightOptions = {
- type: "HighPercentage",
- weight: 3,
+export type HighPopulationAtRisk = {
+ type: "HighPercentage";
+ weight: 3;
};
-type GeographicalSpreadOptions = {
- type: GeographicalSpreadOptionsTypes;
- weight: 1 | 2 | 3;
-};
-export const LowGeographicalSpread: GeographicalSpreadOptions = {
- type: "WithinDistrict",
- weight: 1,
+export type LowGeographicalSpread = {
+ type: "WithinDistrict";
+ weight: 1;
};
-export const MediumGeographicalSpread: GeographicalSpreadOptions = {
- type: "MoretThanOneDistrict",
- weight: 2,
+export type MediumGeographicalSpread = {
+ type: "MoretThanOneDistrict";
+ weight: 2;
};
-export const HighGeographicalSpread: GeographicalSpreadOptions = {
- type: "MoreThanOneProvince",
- weight: 3,
+export type HighGeographicalSpread = {
+ type: "MoreThanOneProvince";
+ weight: 3;
};
-type CapacityOptions = {
- type: CapacityOptionsTypes;
- weight: 1 | 2 | 3;
+export type LowCapacity = {
+ type: "ProvincialNationalLevel";
+ weight: 1;
};
-export const LowCapacity: CapacityOptions = {
- type: "ProvincialNationalLevel",
- weight: 1,
+export type MediumCapacity = {
+ type: "ProvincialLevel";
+ weight: 2;
};
-export const MediumCapacity: CapacityOptions = {
- type: "ProvincialLevel",
- weight: 2,
-};
-export const HighCapacity: CapacityOptions = {
- type: "NationalInternationalLevel",
- weight: 3,
+export type HighCapacity = {
+ type: "NationalInternationalLevel";
+ weight: 3;
};
export type Grade = "Grade1" | "Grade2" | "Grade3";
@@ -119,13 +103,13 @@ const translations: Record = {
interface RiskAssessmentGradingAttrs extends Ref {
lastUpdated: Date;
- populationAtRisk: PopulationWeightOptions;
- attackRate: WeightedOptions;
- geographicalSpread: GeographicalSpreadOptions;
- complexity: WeightedOptions;
- capacity: CapacityOptions;
- reputationalRisk: WeightedOptions;
- severity: WeightedOptions;
+ populationAtRisk: LowPopulationAtRisk | MediumPopulationAtRisk | HighPopulationAtRisk;
+ attackRate: LowWeightedOption | MediumWeightedOption | HighWeightedOption;
+ geographicalSpread: LowGeographicalSpread | MediumGeographicalSpread | HighGeographicalSpread;
+ complexity: LowWeightedOption | MediumWeightedOption | HighWeightedOption;
+ capacity: LowCapacity | MediumCapacity | HighCapacity;
+ reputationalRisk: LowWeightedOption | MediumWeightedOption | HighWeightedOption;
+ severity: LowWeightedOption | MediumWeightedOption | HighWeightedOption;
}
export class RiskAssessmentGrading extends Struct() {
@@ -141,9 +125,9 @@ export class RiskAssessmentGrading extends Struct()
return translations[key];
}
- getGrade = (): Either => {
+ getGrade(): Either {
return this.calculateGrade();
- };
+ }
calculateGrade(): Either {
const totalWeight =
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
index 3296b142..0e27d4b3 100644
--- a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -1,19 +1,18 @@
import { describe, expect, it } from "vitest";
-import {
- HighCapacity,
- HighGeographicalSpread,
- HighPopulationAtRisk,
- HighWeightedOption,
- LowCapacity,
- LowGeographicalSpread,
- LowPopulationAtRisk,
- LowWeightedOption,
- MediumCapacity,
- MediumGeographicalSpread,
- MediumPopulationAtRisk,
- MediumWeightedOption,
- RiskAssessmentGrading,
-} from "../RiskAssessmentGrading";
+import { RiskAssessmentGrading } from "../RiskAssessmentGrading";
+
+const LowPopulationAtRisk = { type: "LessPercentage" as const, weight: 1 as const };
+const MediumPopulationAtRisk = { type: "MediumPercentage" as const, weight: 2 as const };
+const HighPopulationAtRisk = { type: "HighPercentage" as const, weight: 3 as const };
+const LowWeightedOption = { type: "Low" as const, weight: 1 as const };
+const MediumWeightedOption = { type: "Medium" as const, weight: 2 as const };
+const HighWeightedOption = { type: "High" as const, weight: 3 as const };
+const LowGeographicalSpread = { type: "WithinDistrict" as const, weight: 1 as const };
+const MediumGeographicalSpread = { type: "MoretThanOneDistrict" as const, weight: 2 as const };
+const HighGeographicalSpread = { type: "MoreThanOneProvince" as const, weight: 3 as const };
+const LowCapacity = { type: "ProvincialNationalLevel" as const, weight: 1 as const };
+const MediumCapacity = { type: "ProvincialLevel" as const, weight: 2 as const };
+const HighCapacity = { type: "NationalInternationalLevel" as const, weight: 3 as const };
describe("RiskAssessmentGrading", () => {
it("should be Grade1 if total weight is less than or equal to 7", () => {
@@ -28,7 +27,7 @@ describe("RiskAssessmentGrading", () => {
reputationalRisk: LowWeightedOption,
severity: LowWeightedOption,
});
- const grade = riskAssessmentGrading.getGrade().value.data;
+ const grade = riskAssessmentGrading.getGrade().getOrThrow();
if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 1");
});
@@ -44,7 +43,7 @@ describe("RiskAssessmentGrading", () => {
reputationalRisk: MediumWeightedOption,
severity: MediumWeightedOption,
});
- const grade = riskAssessmentGrading.getGrade().value.data;
+ const grade = riskAssessmentGrading.getGrade().getOrThrow();
if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 2");
});
@@ -61,7 +60,7 @@ describe("RiskAssessmentGrading", () => {
severity: HighWeightedOption,
});
- const grade = riskAssessmentGrading.getGrade().value.data;
+ const grade = riskAssessmentGrading.getGrade().getOrThrow();
if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 3");
});
});
From 09e05e690326183473679cc605c8b0e752ffe27b Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Mon, 1 Jul 2024 17:54:05 +0530
Subject: [PATCH 7/8] fix: narrow Either.getOrThrow implementation
---
src/domain/entities/generic/Either.ts | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/domain/entities/generic/Either.ts b/src/domain/entities/generic/Either.ts
index ecca6888..adff2c62 100644
--- a/src/domain/entities/generic/Either.ts
+++ b/src/domain/entities/generic/Either.ts
@@ -17,11 +17,9 @@
export class Either {
constructor(public value: EitherValue) {}
- getOrThrow(): Data | undefined {
- if (this.isError()) {
- throw this.value.error;
- }
- return this.value.data;
+ getOrThrow(): Data {
+ if (this.value.data) return this.value.data;
+ else throw this.value.error;
}
match(matchObj: MatchObject): Res {
From 3ea234d5c9df727089a709648b32b9a774787ed5 Mon Sep 17 00:00:00 2001
From: 9sneha-n <9sneha.n@gmail.com>
Date: Mon, 1 Jul 2024 17:56:28 +0530
Subject: [PATCH 8/8] fix: naming convention for variables
---
.../__tests__/RiskAssessmentGrading.spec.ts | 66 +++++++++----------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
index 0e27d4b3..1f1b9e3c 100644
--- a/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
+++ b/src/domain/entities/risk-assessment/__tests__/RiskAssessmentGrading.spec.ts
@@ -1,31 +1,31 @@
import { describe, expect, it } from "vitest";
import { RiskAssessmentGrading } from "../RiskAssessmentGrading";
-const LowPopulationAtRisk = { type: "LessPercentage" as const, weight: 1 as const };
-const MediumPopulationAtRisk = { type: "MediumPercentage" as const, weight: 2 as const };
-const HighPopulationAtRisk = { type: "HighPercentage" as const, weight: 3 as const };
-const LowWeightedOption = { type: "Low" as const, weight: 1 as const };
-const MediumWeightedOption = { type: "Medium" as const, weight: 2 as const };
-const HighWeightedOption = { type: "High" as const, weight: 3 as const };
-const LowGeographicalSpread = { type: "WithinDistrict" as const, weight: 1 as const };
-const MediumGeographicalSpread = { type: "MoretThanOneDistrict" as const, weight: 2 as const };
-const HighGeographicalSpread = { type: "MoreThanOneProvince" as const, weight: 3 as const };
-const LowCapacity = { type: "ProvincialNationalLevel" as const, weight: 1 as const };
-const MediumCapacity = { type: "ProvincialLevel" as const, weight: 2 as const };
-const HighCapacity = { type: "NationalInternationalLevel" as const, weight: 3 as const };
+const lowPopulationAtRisk = { type: "LessPercentage" as const, weight: 1 as const };
+const mediumPopulationAtRisk = { type: "MediumPercentage" as const, weight: 2 as const };
+const highPopulationAtRisk = { type: "HighPercentage" as const, weight: 3 as const };
+const lowWeightedOption = { type: "Low" as const, weight: 1 as const };
+const mediumWeightedOption = { type: "Medium" as const, weight: 2 as const };
+const highWeightedOption = { type: "High" as const, weight: 3 as const };
+const lowGeographicalSpread = { type: "WithinDistrict" as const, weight: 1 as const };
+const mediumGeographicalSpread = { type: "MoretThanOneDistrict" as const, weight: 2 as const };
+const highGeographicalSpread = { type: "MoreThanOneProvince" as const, weight: 3 as const };
+const lowCapacity = { type: "ProvincialNationalLevel" as const, weight: 1 as const };
+const mediumCapacity = { type: "ProvincialLevel" as const, weight: 2 as const };
+const highCapacity = { type: "NationalInternationalLevel" as const, weight: 3 as const };
describe("RiskAssessmentGrading", () => {
it("should be Grade1 if total weight is less than or equal to 7", () => {
const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "1",
lastUpdated: new Date(),
- populationAtRisk: LowPopulationAtRisk,
- attackRate: LowWeightedOption,
- geographicalSpread: LowGeographicalSpread,
- complexity: LowWeightedOption,
- capacity: LowCapacity,
- reputationalRisk: LowWeightedOption,
- severity: LowWeightedOption,
+ populationAtRisk: lowPopulationAtRisk,
+ attackRate: lowWeightedOption,
+ geographicalSpread: lowGeographicalSpread,
+ complexity: lowWeightedOption,
+ capacity: lowCapacity,
+ reputationalRisk: lowWeightedOption,
+ severity: lowWeightedOption,
});
const grade = riskAssessmentGrading.getGrade().getOrThrow();
if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 1");
@@ -35,13 +35,13 @@ describe("RiskAssessmentGrading", () => {
const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "2",
lastUpdated: new Date(),
- populationAtRisk: MediumPopulationAtRisk,
- attackRate: MediumWeightedOption,
- geographicalSpread: MediumGeographicalSpread,
- complexity: MediumWeightedOption,
- capacity: MediumCapacity,
- reputationalRisk: MediumWeightedOption,
- severity: MediumWeightedOption,
+ populationAtRisk: mediumPopulationAtRisk,
+ attackRate: mediumWeightedOption,
+ geographicalSpread: mediumGeographicalSpread,
+ complexity: mediumWeightedOption,
+ capacity: mediumCapacity,
+ reputationalRisk: mediumWeightedOption,
+ severity: mediumWeightedOption,
});
const grade = riskAssessmentGrading.getGrade().getOrThrow();
if (grade) expect(RiskAssessmentGrading.getTranslatedLabel(grade)).toBe("Grade 2");
@@ -51,13 +51,13 @@ describe("RiskAssessmentGrading", () => {
const riskAssessmentGrading = RiskAssessmentGrading.create({
id: "3",
lastUpdated: new Date(),
- populationAtRisk: HighPopulationAtRisk,
- attackRate: HighWeightedOption,
- geographicalSpread: HighGeographicalSpread,
- complexity: HighWeightedOption,
- capacity: HighCapacity,
- reputationalRisk: HighWeightedOption,
- severity: HighWeightedOption,
+ populationAtRisk: highPopulationAtRisk,
+ attackRate: highWeightedOption,
+ geographicalSpread: highGeographicalSpread,
+ complexity: highWeightedOption,
+ capacity: highCapacity,
+ reputationalRisk: highWeightedOption,
+ severity: highWeightedOption,
});
const grade = riskAssessmentGrading.getGrade().getOrThrow();