Skip to content

Commit

Permalink
Merge pull request #299 from EyeSeeTea/development
Browse files Browse the repository at this point in the history
Release 1.6.18
  • Loading branch information
ifoche authored Aug 29, 2024
2 parents cd6ec3a + 4bba912 commit 0988c82
Show file tree
Hide file tree
Showing 29 changed files with 313 additions and 84 deletions.
19 changes: 14 additions & 5 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: 2024-07-26T10:31:32.732Z\n"
"PO-Revision-Date: 2024-07-26T10:31:32.732Z\n"
"POT-Creation-Date: 2024-08-07T18:05:19.338Z\n"
"PO-Revision-Date: 2024-08-07T18:05:19.338Z\n"

msgid "Template {{id}} not loaded"
msgstr ""
Expand Down Expand Up @@ -172,6 +172,9 @@ msgstr ""
msgid "You can add up to 6 datasets to this submission with different BATCH IDS."
msgstr ""

msgid "Validated Uploads, Review to complete"
msgstr ""

msgid "Uploads with errors, or discarded"
msgstr ""

Expand Down Expand Up @@ -359,9 +362,18 @@ msgstr ""
msgid "Delete"
msgstr ""

msgid "Complete"
msgstr ""

msgid "Failed to set completed status"
msgstr ""

msgid "Deleting Files"
msgstr ""

msgid "Loading"
msgstr ""

msgid "This might take several minutes, do not refresh the page or press back."
msgstr ""

Expand Down Expand Up @@ -608,9 +620,6 @@ msgstr ""
msgid "Choose a Dataset"
msgstr ""

msgid "Loading"
msgstr ""

msgid "Choose file type"
msgstr ""

Expand Down
17 changes: 13 additions & 4 deletions i18n/es.po
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: i18next-conv\n"
"POT-Creation-Date: 2024-07-26T10:31:32.732Z\n"
"POT-Creation-Date: 2024-08-07T18:05:19.338Z\n"
"PO-Revision-Date: 2018-10-25T09:02:35.143Z\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -173,6 +173,9 @@ msgid ""
"You can add up to 6 datasets to this submission with different BATCH IDS."
msgstr ""

msgid "Validated Uploads, Review to complete"
msgstr ""

msgid "Uploads with errors, or discarded"
msgstr ""

Expand Down Expand Up @@ -361,9 +364,18 @@ msgstr ""
msgid "Delete"
msgstr ""

msgid "Complete"
msgstr ""

msgid "Failed to set completed status"
msgstr ""

msgid "Deleting Files"
msgstr ""

msgid "Loading"
msgstr ""

msgid "This might take several minutes, do not refresh the page or press back."
msgstr ""

Expand Down Expand Up @@ -610,9 +622,6 @@ msgstr ""
msgid "Choose a Dataset"
msgstr ""

msgid "Loading"
msgstr ""

msgid "Choose file type"
msgstr ""

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "glass",
"description": "DHIS2 Glass App",
"version": "1.6.16",
"version": "1.6.18",
"license": "GPL-3.0",
"author": "EyeSeeTea team",
"homepage": ".",
Expand Down
4 changes: 4 additions & 0 deletions src/CompositionRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ import { GetMultipleDashboardUseCase } from "./domain/usecases/GetMultipleDashbo
import { DownloadAllDataButtonData } from "./domain/usecases/DownloadAllDataButtonData";
import { DownloadEmptyTemplateUseCase } from "./domain/usecases/DownloadEmptyTemplateUseCase";
import { DownloadPopulatedTemplateUseCase } from "./domain/usecases/DownloadPopulatedTemplateUseCase";
import { CountryDefaultRepository } from "./data/repositories/CountryDefaultRepository";
import { GetAllCountriesUseCase } from "./domain/usecases/GetAllCountriesUseCase";

export function getCompositionRoot(instance: Instance) {
const api = getD2APiFromInstance(instance);
Expand Down Expand Up @@ -127,6 +129,7 @@ export function getCompositionRoot(instance: Instance) {
const glassAtcRepository = new GlassATCDefaultRepository(dataStoreClient);
const atcRepository = new GlassATCDefaultRepository(dataStoreClient);
const eventVisualizationRepository = new EventVisualizationAnalyticsDefaultRepository(api);
const countryRepository = new CountryDefaultRepository(api);

return {
instance: getExecute({
Expand Down Expand Up @@ -243,6 +246,7 @@ export function getCompositionRoot(instance: Instance) {
}),
countries: getExecute({
getInformation: new GetCountryInformationUseCase(countryInformationRepository),
getAll: new GetAllCountriesUseCase(countryRepository),
}),
glassDashboard: getExecute({
getDashboard: new GetDashboardUseCase(glassModuleRepository),
Expand Down
44 changes: 44 additions & 0 deletions src/data/repositories/CountryDefaultRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { D2Api, MetadataPick } from "@eyeseetea/d2-api/2.34";
import { FutureData } from "../../domain/entities/Future";
import { apiToFuture } from "../../utils/futures";
import { CountryRepository } from "../../domain/repositories/CountryRepository";
import { Country } from "../../domain/entities/Country";

export class CountryDefaultRepository implements CountryRepository {
constructor(private api: D2Api) {}

public getAll(): FutureData<Country[]> {
return apiToFuture(
this.api.models.organisationUnits.get({
fields: organisationUnitsFields,
paging: false,
level: 3,
})
).map(response => {
return this.buildOrgUnits(response.objects);
});
}

private buildOrgUnits(d2OrgUnits: D2OrgUnit[]): Country[] {
return d2OrgUnits.map(d2OrgUnit => ({
id: d2OrgUnit.id,
name: d2OrgUnit.name,
shortName: d2OrgUnit.shortName,
code: d2OrgUnit.code,
}));
}
}

const organisationUnitsFields = {
id: true,
name: true,
shortName: true,
code: true,
description: { id: true, name: true },
geometry: true,
organisationUnitGroups: { id: true, name: true },
} as const;

type D2OrgUnit = MetadataPick<{
organisationUnits: { fields: typeof organisationUnitsFields };
}>["organisationUnits"][number];
1 change: 1 addition & 0 deletions src/data/repositories/InstanceDefaultRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export class InstanceDefaultRepository implements InstanceRepository {
moduleId: module.id,
moduleName: module.name,
populateCurrentYearInHistory: module.populateCurrentYearInHistory ? true : false,
startPeriod: module.startPeriod,
readAccess: readAccess,
captureAccess: writeAccess,
usergroups: [...module.userGroups.captureAccess, ...module.userGroups.readAccess],
Expand Down
6 changes: 6 additions & 0 deletions src/domain/entities/Country.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type Country = {
id: string;
name: string;
shortName: string;
code: string;
};
1 change: 1 addition & 0 deletions src/domain/entities/GlassModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface GlassModule {
programStageId: string;
}[];
populateCurrentYearInHistory?: boolean;
startPeriod?: number;
customDataColumns?: CustomDataColumns;
lineLists?: LineListDetails[];
chunkSizes?: ChunkSizes;
Expand Down
1 change: 1 addition & 0 deletions src/domain/entities/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface ModuleAccess {
captureAccess: boolean;
usergroups: UserGroup[];
populateCurrentYearInHistory: boolean;
startPeriod?: number;
}

export interface UserAccessInfo {
Expand Down
6 changes: 6 additions & 0 deletions src/domain/repositories/CountryRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Country } from "../entities/Country";
import { FutureData } from "../entities/Future";

export interface CountryRepository {
getAll(): FutureData<Country[]>;
}
12 changes: 12 additions & 0 deletions src/domain/usecases/GetAllCountriesUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { UseCase } from "../../CompositionRoot";
import { Country } from "../entities/Country";
import { FutureData } from "../entities/Future";
import { CountryRepository } from "../repositories/CountryRepository";

export class GetAllCountriesUseCase implements UseCase {
constructor(private countryRepository: CountryRepository) {}

public execute(): FutureData<Country[]> {
return this.countryRepository.getAll();
}
}
8 changes: 4 additions & 4 deletions src/domain/usecases/data-entry/ImportPrimaryFileUseCase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { InstanceDefaultRepository } from "../../../data/repositories/InstanceDe
import { GlassATCDefaultRepository } from "../../../data/repositories/GlassATCDefaultRepository";
import { AMCProductDataRepository } from "../../repositories/data-entry/AMCProductDataRepository";
import { AMCSubstanceDataRepository } from "../../repositories/data-entry/AMCSubstanceDataRepository";
import { OrgUnitAccess } from "../../entities/User";
import { Country } from "../../entities/Country";

export class ImportPrimaryFileUseCase {
constructor(
Expand Down Expand Up @@ -55,7 +55,7 @@ export class ImportPrimaryFileUseCase {
countryCode: string,
dryRun: boolean,
eventListId: string | undefined,
orgUnitsWithAccess: OrgUnitAccess[],
allCountries: Country[],
calculatedEventListFileId?: string
): FutureData<ImportSummary> {
switch (moduleName) {
Expand Down Expand Up @@ -113,7 +113,7 @@ export class ImportPrimaryFileUseCase {
module.programs !== undefined ? module.programs.at(0) : undefined,
module.name,
module.customDataColumns ? module.customDataColumns : [],
orgUnitsWithAccess
allCountries
);
});
}
Expand All @@ -140,7 +140,7 @@ export class ImportPrimaryFileUseCase {
orgUnitName,
moduleName,
period,
orgUnitsWithAccess,
allCountries,
calculatedEventListFileId
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { D2TrackerTrackedEntity } from "@eyeseetea/d2-api/api/trackerTrackedEnti
import { GlassATCDefaultRepository } from "../../../../data/repositories/GlassATCDefaultRepository";
import { GlassAtcVersionData, LAST_ATC_CODE_LEVEL, getAtcCodeByLevel } from "../../../entities/GlassAtcVersionData";
import { AMCProductDataRepository } from "../../../repositories/data-entry/AMCProductDataRepository";
import { OrgUnitAccess } from "../../../entities/User";
import { Country } from "../../../entities/Country";

const AMR_GLASS_AMC_TEA_ATC = "aK1JpD14imM";
const AMR_GLASS_AMC_TEA_COMBINATION = "mG49egdYK3G";
Expand Down Expand Up @@ -34,7 +34,7 @@ export class CustomValidationsAMCProductData {
orgUnitId: string,
orgUnitName: string,
period: string,
orgUnitsWithAccess: OrgUnitAccess[]
allCountries: Country[]
): FutureData<ValidationResult> {
return this.atcRepository.getCurrentAtcVersion().flatMap(atcVersion => {
return this.amcProductRepository
Expand All @@ -47,7 +47,7 @@ export class CustomValidationsAMCProductData {
orgUnitName,
period,
atcVersion,
orgUnitsWithAccess
allCountries
);

const dateErrors = this.checkSameEnrollmentDate(teis);
Expand Down Expand Up @@ -115,7 +115,7 @@ export class CustomValidationsAMCProductData {
countryName: string,
period: string,
atcVersion: GlassAtcVersionData,
orgUnitsWithAccess: OrgUnitAccess[]
allCountries: Country[]
): ConsistencyError[] {
const errors = _(
teis.map(tei => {
Expand Down Expand Up @@ -256,9 +256,7 @@ export class CustomValidationsAMCProductData {
}
}

const productManufacturerCountry = orgUnitsWithAccess.find(
orgUnit => orgUnit.orgUnitId === manufacturerCountryId
);
const productManufacturerCountry = allCountries.find(country => country.id === manufacturerCountryId);

if (manufacturerCountryId && !productManufacturerCountry) {
curErrors.push({
Expand Down
16 changes: 8 additions & 8 deletions src/domain/usecases/data-entry/amc/ImportAMCProductLevelData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import { CODE_PRODUCT_NOT_HAVE_ATC, COMB_CODE_PRODUCT_NOT_HAVE_ATC } from "../..
import { AMCSubstanceDataRepository } from "../../../repositories/data-entry/AMCSubstanceDataRepository";
import { downloadIdsAndDeleteTrackedEntities } from "../utils/downloadIdsAndDeleteTrackedEntities";
import { getStringFromFile } from "../utils/fileToString";
import { OrgUnitAccess } from "../../../entities/User";
import { getTEAValueFromOrganisationUnitCountryEntry } from "../utils/getTEAValueFromOrganisationUnitCountryEntry";
import { Country } from "../../../entities/Country";

export const AMC_PRODUCT_REGISTER_PROGRAM_ID = "G6ChA5zMW9n";
export const AMC_RAW_PRODUCT_CONSUMPTION_STAGE_ID = "GmElQHKXLIE";
Expand Down Expand Up @@ -57,7 +57,7 @@ export class ImportAMCProductLevelData {
orgUnitName: string,
moduleName: string,
period: string,
orgUnitsWithAccess: OrgUnitAccess[],
allCountries: Country[],
calculatedEventListFileId?: string
): FutureData<ImportSummary> {
return this.excelRepository.loadTemplate(file, AMC_PRODUCT_REGISTER_PROGRAM_ID).flatMap(_templateId => {
Expand All @@ -82,15 +82,15 @@ export class ImportAMCProductLevelData {
orgUnitId,
orgUnitName,
period,
orgUnitsWithAccess
allCountries
).flatMap(entities => {
return this.validateTEIsAndEvents(
entities,
orgUnitId,
orgUnitName,
period,
AMC_PRODUCT_REGISTER_PROGRAM_ID,
orgUnitsWithAccess
allCountries
).flatMap(validationResults => {
if (validationResults.blockingErrors.length > 0) {
const errorSummary: ImportSummary = {
Expand Down Expand Up @@ -169,7 +169,7 @@ export class ImportAMCProductLevelData {
orgUnitId: Id,
orgUnitName: string,
period: string,
orgUnitsWithAccess: OrgUnitAccess[]
allCountries: Country[]
): FutureData<D2TrackerTrackedEntity[]> {
return this.trackerRepository
.getProgramMetadata(AMC_PRODUCT_REGISTER_PROGRAM_ID, AMC_RAW_PRODUCT_CONSUMPTION_STAGE_ID)
Expand Down Expand Up @@ -201,7 +201,7 @@ export class ImportAMCProductLevelData {
} else if (attr.valueType === "ORGANISATION_UNIT") {
currentAttrVal = currentAttribute
? getTEAValueFromOrganisationUnitCountryEntry(
orgUnitsWithAccess,
allCountries,
currentAttribute.value,
true
)
Expand Down Expand Up @@ -300,7 +300,7 @@ export class ImportAMCProductLevelData {
orgUnitName: string,
period: string,
programId: string,
orgUnitsWithAccess: OrgUnitAccess[]
allCountries: Country[]
): FutureData<ValidationResult> {
//1. Before running validations, add ids to tei, enrollement and event so thier relationships can be processed.
const teisWithId = teis?.map((tei, teiIndex) => {
Expand Down Expand Up @@ -332,7 +332,7 @@ export class ImportAMCProductLevelData {
orgUnitId,
orgUnitName,
period,
orgUnitsWithAccess
allCountries
),
}).flatMap(({ programRuleValidationResults, customRuleValidationsResults }) => {
//4. After processing, remove ids to tei, enrollement and events so that they can be imported
Expand Down
Loading

0 comments on commit 0988c82

Please sign in to comment.