diff --git a/src/data/transformations/__tests__/integration/teiTransformations-api.spec.ts b/src/data/transformations/__tests__/integration/teiTransformations-api.spec.ts index d88e1cbb2..f081bfff6 100644 --- a/src/data/transformations/__tests__/integration/teiTransformations-api.spec.ts +++ b/src/data/transformations/__tests__/integration/teiTransformations-api.spec.ts @@ -135,13 +135,48 @@ function setupMockEndpoints(local: Server, remote: Server) { instances: [], })); - remote.get("/metadata", async () => ({ - categoryOptions: [{ id: "default5" }], - categories: [{ id: "default6" }], - categoryCombos: [{ id: "default7" }], - categoryOptionCombos: [{ id: "default8" }], - dataElements: [{ id: "id2", name: "Test data element 2" }], - })); + remote.get("/metadata", async (_schema, request) => { + if (request.queryParams.filter === "id:in:[program1]") { + return { + programs: [ + { + name: "Test program", + id: "program1", + programStages: [ + { + programStageDataElements: [ + { + dataElement: { + name: "Test data element", + id: "id1", + displayFormName: "Test data element", + }, + }, + ], + }, + ], + programIndicators: [], + programType: "WITH_REGISTRATION", + programTrackedEntityAttributes: [ + { + trackedEntityAttribute: { + id: "attribute1", + }, + }, + ], + }, + ], + }; + } else { + return { + categoryOptions: [{ id: "default5" }], + categories: [{ id: "default6" }], + categoryCombos: [{ id: "default7" }], + categoryOptionCombos: [{ id: "default8" }], + dataElements: [{ id: "id2", name: "Test data element 2" }], + }; + } + }); local.get("/dataStore/metadata-synchronization/instances", async () => [ { diff --git a/src/domain/tracked-entity-instances/entities/Enrollment.ts b/src/domain/tracked-entity-instances/entities/Enrollment.ts index 5e3f8c3bb..e24c11f76 100644 --- a/src/domain/tracked-entity-instances/entities/Enrollment.ts +++ b/src/domain/tracked-entity-instances/entities/Enrollment.ts @@ -19,7 +19,7 @@ export interface Enrollment { attributes: EnrollmentAttribute[]; } -interface EnrollmentAttribute { +export interface EnrollmentAttribute { attribute: string; value: string; } diff --git a/src/domain/tracked-entity-instances/mapper/teis-payload-mapper/TEIsPayloadMapper.ts b/src/domain/tracked-entity-instances/mapper/teis-payload-mapper/TEIsPayloadMapper.ts index 84851fdd2..272a7eadb 100644 --- a/src/domain/tracked-entity-instances/mapper/teis-payload-mapper/TEIsPayloadMapper.ts +++ b/src/domain/tracked-entity-instances/mapper/teis-payload-mapper/TEIsPayloadMapper.ts @@ -4,7 +4,7 @@ import { MetadataMappingDictionary } from "../../../mapping/entities/MetadataMap import { SynchronizationPayload } from "../../../synchronization/entities/SynchronizationPayload"; import { PayloadMapper } from "../../../synchronization/mapper/PayloadMapper"; import { cleanOrgUnitPath } from "../../../synchronization/utils"; -import { Enrollment } from "../../entities/Enrollment"; +import { Enrollment, EnrollmentAttribute } from "../../entities/Enrollment"; import { Relationship } from "../../entities/Relationship"; import { TEIsPackage } from "../../entities/TEIsPackage"; import { TrakedEntityAttribute } from "../../entities/TrackedEntityAttribute"; @@ -26,6 +26,22 @@ export class TEIsPayloadMapper implements PayloadMapper { } = this.mapping; const mappedOrgUnit = organisationUnits[tei.orgUnit]?.mappedId ?? tei.orgUnit; + const mapAttributes = (attributes: T[]): T[] => { + return attributes.map(att => { + const mappedAttributeId = trackedEntityAttributesToTEI[att.attribute]?.mappedId ?? att.attribute; + + const mappedValue = mapOptionValue(att.value, [ + trackedEntityAttributesToTEI[att.attribute]?.mapping ?? {}, + this.mapping, + ]); + + return { + ...att, + attribute: mappedAttributeId, + value: mappedValue, + }; + }); + }; return { ...tei, @@ -47,6 +63,7 @@ export class TEIsPayloadMapper implements PayloadMapper { return { ...enrollment, + attributes: mapAttributes(enrollment.attributes), orgUnit: cleanOrgUnitPath(mappedOrgUnit), program: mappedProgram, }; @@ -59,20 +76,7 @@ export class TEIsPayloadMapper implements PayloadMapper { relationshipType: mappedRelTypeId, }; }), - attributes: tei.attributes.map(att => { - const mappedAttributeId = trackedEntityAttributesToTEI[att.attribute]?.mappedId ?? att.attribute; - - const mappedValue = mapOptionValue(att.value, [ - trackedEntityAttributesToTEI[att.attribute]?.mapping ?? {}, - this.mapping, - ]); - - return { - ...att, - attribute: mappedAttributeId, - value: mappedValue, - }; - }), + attributes: mapAttributes(tei.attributes), }; }); @@ -91,7 +95,18 @@ export class TEIsPayloadMapper implements PayloadMapper { return { ...tei, programOwners: tei.programOwners.filter(item => !this.isDisabledProgramOwner(item)), - enrollments: tei.enrollments.filter(item => !this.isDisabledEnrollment(item)), + enrollments: tei.enrollments + .filter(item => !this.isDisabledEnrollment(item)) + .map(enrollment => { + const enrollmentAttributes = enrollment.attributes.filter( + itemAttribute => !this.isDisabledTrackedEntityAttribute(itemAttribute) + ); + + return { + ...enrollment, + attributes: enrollmentAttributes, + }; + }), relationships: tei.relationships.filter(item => !this.isDisabledRelationship(item)), attributes: tei.attributes.filter(item => !this.isDisabledTrackedEntityAttribute(item)), }; @@ -130,7 +145,18 @@ export class TEIsPayloadMapper implements PayloadMapper { programOwners: tei.programOwners.filter( item => !destinationEventProgramsIds.includes(item.program) ), - enrollments: tei.enrollments.filter(item => !destinationEventProgramsIds.includes(item.program)), + enrollments: tei.enrollments + .filter(item => !destinationEventProgramsIds.includes(item.program)) + .map(enrollment => { + const enrollmentAttributes = enrollment.attributes.filter(attr => + destinationTrackerProgramAttributes.includes(attr.attribute) + ); + + return { + ...enrollment, + attributes: enrollmentAttributes, + }; + }), attributes: tei.attributes.filter(item => destinationTrackerProgramAttributes.includes(item.attribute) ), @@ -175,7 +201,7 @@ export class TEIsPayloadMapper implements PayloadMapper { return item.relationshipType === "DISABLED"; } - private isDisabledTrackedEntityAttribute(item: TrakedEntityAttribute): boolean { + private isDisabledTrackedEntityAttribute(item: TrakedEntityAttribute | EnrollmentAttribute): boolean { return item.attribute === "DISABLED" || item.value === "DISABLED"; } }