Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/models/ProjectsList.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import _ from "lodash";
import { TableSorting } from "@eyeseetea/d2-ui-components";
import { D2Api, D2OrganisationUnitSchema, SelectedPick, Id, Pager, Ref } from "../types/d2-api";
import { Config } from "./Config";
import moment, { Moment } from "moment";
Expand Down Expand Up @@ -399,3 +398,8 @@ function getOrgUnitsFilter(filters: FiltersForList, currentUser: User) {
: userCountryIds;
return filterCountryIds ? { "parent.id": { in: filterCountryIds } } : {};
}

export type TableSorting<T> = {
field: keyof T;
order: "asc" | "desc";
};
16 changes: 1 addition & 15 deletions src/pages/unique-periods/UniquePeriodsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,14 @@ import {
import i18n from "../../locales";
import { Maybe } from "../../types/utils";
import { getErrors } from "../../domain/entities/generic/Errors";
import { months } from "../../utils/date";

export type UniquePeriodsFormProps = {
existingPeriod?: UniqueBeneficiariesPeriodsAttrs;
onClose: () => void;
onSubmit: (uniquePeriods: UniqueBeneficiariesPeriod) => void;
};

export const months = [
{ value: "1", text: i18n.t("January") },
{ value: "2", text: i18n.t("February") },
{ value: "3", text: i18n.t("March") },
{ value: "4", text: i18n.t("April") },
{ value: "5", text: i18n.t("May") },
{ value: "6", text: i18n.t("June") },
{ value: "7", text: i18n.t("July") },
{ value: "8", text: i18n.t("August") },
{ value: "9", text: i18n.t("September") },
{ value: "10", text: i18n.t("October") },
{ value: "11", text: i18n.t("November") },
{ value: "12", text: i18n.t("December") },
];

function getValueByAttribute(
value: string,
attribute: keyof UniqueBeneficiariesPeriod
Expand Down
138 changes: 138 additions & 0 deletions src/scripts/remove-paired-dataelement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import _ from "lodash";
import parse from "parse-typed-args";
import { promiseMap } from "../migrations/utils";
import { getConfig } from "../models/Config";
import { D2Api } from "../types/d2-api";
import fs from "fs";

async function main() {
const parser = parse({
opts: {
url: {},
auth: {},
codes: {},
persist: { switch: true },
},
});
const { opts } = parser(process.argv);
const { url, auth, codes, persist } = opts;

const usage =
"npx tsx src/scripts/remove-paired-dataelement.ts --url=<DHIS2 URL> [--auth=user:pass] [--codes=deCode1,deCode2] [--persist]";
if (!url) {
console.error(usage);
process.exit(1);
}

if (!codes || codes.length === 0) {
console.error(usage);
process.exit(1);
}

const [username, password] = auth ? auth.split(":") : ["", ""];
const api = new D2Api({ baseUrl: url, auth: { password, username }, agent: {} });
const config = await getConfig(api);

// TODO: request in chunks
const responseDes = await api.models.dataElements
.get({
fields: { id: true, attributeValues: { attribute: { id: true }, value: true } },
filter: { code: { in: codes.split(",") } },
paging: false,
})
.getData();

if (responseDes.objects.length === 0) {
console.debug("No data elements found with the provided codes");
return;
}

const dataElements = responseDes.objects.map((de): DataElement => {
return {
id: de.id,
pairedDataElement: de.attributeValues?.find(
av => av.attribute.id === config.attributes.pairedDataElement.id
)?.value,
};
});

const dataElementsWithPaired = dataElements.filter(de => de.pairedDataElement);

console.debug(`Found ${dataElementsWithPaired.length} dataElements with paired data elements`);

const allDeIds = dataElementsWithPaired.map(de => de.id);

const allStats = await promiseMap(_(allDeIds).chunk(100).value(), async dataElementIds => {
const response = await api.models.dataElements
.get({
fields: { $owner: true },
filter: { id: { in: dataElementIds } },
paging: false,
})
.getData();

const dataElementsToUpdate = dataElementIds.map(dataElementId => {
const existingDe = response.objects.find(de => de.id === dataElementId);

const dataElement = dataElementsWithPaired.find(de => de.id === dataElementId);
if (!dataElement) {
throw Error("Cannot find dataElement");
}

const newAttributeValues = existingDe?.attributeValues.map(d2Attribute => {
if (d2Attribute.attribute.id === config.attributes.pairedDataElement.id) {
return {
...d2Attribute,
value: "",
};
}
return d2Attribute;
});

return { ...(existingDe || {}), attributeValues: newAttributeValues };
});

const persistResponse = await api.metadata
.post(
{ dataElements: dataElementsToUpdate },
{ importMode: persist ? "COMMIT" : "VALIDATE", importStrategy: "UPDATE" }
)
.getData();

// @ts-ignore
const stats = persistResponse.response.stats;
return { stats: stats, payload: dataElementsToUpdate };
});

console.debug(
"Stats: ",
allStats.reduce(
(acum, stat) => {
return {
created: (acum.created || 0) + (stat.stats.created || 0),
updated: (acum.updated || 0) + (stat.stats.updated || 0),
deleted: (acum.deleted || 0) + (stat.stats.deleted || 0),
ignored: (acum.ignored || 0) + (stat.stats.ignored || 0),
};
},
{ created: 0, updated: 0, deleted: 0, ignored: 0 }
)
);

// save payload to disk
fs.writeFileSync(
"data_elements_paired_dataelements.json",
JSON.stringify(
allStats.flatMap(stat => stat.payload),
null,
2
)
);
}

type DataElement = {
id: string;
pairedDataElement?: string;
};

main();
17 changes: 16 additions & 1 deletion src/utils/date.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import moment, { Moment } from "moment";
import { months } from "../pages/unique-periods/UniquePeriodsForm";
import i18n from "../locales";

export function toISOString(date: Moment) {
return date.format("YYYY-MM-DDTHH:mm:ss");
Expand Down Expand Up @@ -58,3 +58,18 @@ export function buildMonthYearFormatDate(dateIsoString: string): string {
export function getMonthNameFromNumber(monthNumber: string | number): string {
return months.find(month => month.value === monthNumber.toString())?.text || "";
}

export const months = [
{ value: "1", text: i18n.t("January") },
{ value: "2", text: i18n.t("February") },
{ value: "3", text: i18n.t("March") },
{ value: "4", text: i18n.t("April") },
{ value: "5", text: i18n.t("May") },
{ value: "6", text: i18n.t("June") },
{ value: "7", text: i18n.t("July") },
{ value: "8", text: i18n.t("August") },
{ value: "9", text: i18n.t("September") },
{ value: "10", text: i18n.t("October") },
{ value: "11", text: i18n.t("November") },
{ value: "12", text: i18n.t("December") },
];
Loading