Skip to content

Commit 47e9a0e

Browse files
fix: Fix enrollment and event tables [DHIS2-12600]
1 parent 97fb8ad commit 47e9a0e

File tree

8 files changed

+94
-16
lines changed

8 files changed

+94
-16
lines changed

dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/objectbundle/hooks/ProgramObjectBundleHook.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundle;
3636
import org.hisp.dhis.feedback.ErrorCode;
3737
import org.hisp.dhis.feedback.ErrorReport;
38+
import org.hisp.dhis.organisationunit.OrganisationUnitService;
3839
import org.hisp.dhis.preheat.PreheatIdentifier;
3940
import org.hisp.dhis.program.Enrollment;
4041
import org.hisp.dhis.program.EnrollmentStatus;
@@ -58,6 +59,8 @@ public class ProgramObjectBundleHook extends AbstractObjectBundleHook<Program> {
5859

5960
private final ProgramStageService programStageService;
6061

62+
private final OrganisationUnitService organisationUnitService;
63+
6164
private final AclService aclService;
6265

6366
private final IdentifiableObjectManager identifiableObjectManager;
@@ -133,6 +136,8 @@ private void addProgramInstance(Program program) {
133136
enrollment.setProgram(program);
134137
enrollment.setStatus(EnrollmentStatus.ACTIVE);
135138
enrollment.setStoredBy("system-process");
139+
enrollment.setOrganisationUnit(
140+
organisationUnitService.getRootOrganisationUnits().iterator().next());
136141

137142
identifiableObjectManager.save(enrollment);
138143
}

dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata/objectbundle/hooks/ProgramObjectBundleHookTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import org.hisp.dhis.common.IdentifiableObjectManager;
4646
import org.hisp.dhis.feedback.ErrorCode;
4747
import org.hisp.dhis.feedback.ErrorReport;
48+
import org.hisp.dhis.organisationunit.OrganisationUnit;
49+
import org.hisp.dhis.organisationunit.OrganisationUnitService;
4850
import org.hisp.dhis.program.Enrollment;
4951
import org.hisp.dhis.program.EnrollmentStatus;
5052
import org.hisp.dhis.program.EventProgramEnrollmentService;
@@ -71,6 +73,8 @@ class ProgramObjectBundleHookTest {
7173

7274
@Mock private ProgramStageService programStageService;
7375

76+
@Mock private OrganisationUnitService organisationUnitService;
77+
7478
@Mock private AclService aclService;
7579

7680
@Mock private IdentifiableObjectManager identifiableObjectManager;
@@ -83,6 +87,7 @@ public void setUp() {
8387
new ProgramObjectBundleHook(
8488
eventProgramEnrollmentService,
8589
programStageService,
90+
organisationUnitService,
8691
aclService,
8792
identifiableObjectManager);
8893

@@ -106,6 +111,8 @@ void verifyMissingBundleIsIgnored() {
106111

107112
@Test
108113
void verifyProgramInstanceIsSavedForEventProgram() {
114+
when(organisationUnitService.getRootOrganisationUnits())
115+
.thenReturn(List.of(new OrganisationUnit()));
109116
ArgumentCaptor<Enrollment> argument = ArgumentCaptor.forClass(Enrollment.class);
110117

111118
programA.setProgramType(ProgramType.WITHOUT_REGISTRATION);

dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/enrollment/HibernateEnrollmentStore.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.hisp.dhis.organisationunit.OrganisationUnit;
5858
import org.hisp.dhis.program.Enrollment;
5959
import org.hisp.dhis.program.EnrollmentStatus;
60+
import org.hisp.dhis.program.ProgramType;
6061
import org.hisp.dhis.security.acl.AclService;
6162
import org.hisp.dhis.tracker.export.Order;
6263
import org.hisp.dhis.tracker.export.Page;
@@ -192,6 +193,9 @@ private QueryWithOrderBy buildEnrollmentHql(EnrollmentQueryParams params) {
192193
hql += hlp.whereAnd() + "en.program.uid = '" + params.getProgram().getUid() + "'";
193194
}
194195

196+
// TODO(DHIS2-17961) This will be removed when placeholder enrollments will not exist anymore
197+
hql += hlp.whereAnd() + "en.program.programType = '" + ProgramType.WITH_REGISTRATION + "'";
198+
195199
if (params.hasEnrollmentStatus()) {
196200
hql += hlp.whereAnd() + "en." + STATUS + " = '" + params.getEnrollmentStatus() + "'";
197201
}

dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/validation/validator/event/SecurityOwnershipValidator.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,7 @@ public void validate(
9696
// If event is newly created, or going to be deleted, capture scope
9797
// has to be checked
9898
if (program.isWithoutRegistration() || strategy.isCreate() || strategy.isDelete()) {
99-
if (organisationUnit == null) {
100-
log.warn(ORG_UNIT_NO_USER_ASSIGNED, event.getUid());
101-
} else {
102-
checkOrgUnitInCaptureScope(reporter, event, organisationUnit, bundle.getUser());
103-
}
99+
checkOrgUnitInCaptureScope(reporter, event, organisationUnit, bundle.getUser());
104100
}
105101

106102
UID teUid = getTeUidFromEvent(bundle, event, program);
@@ -304,9 +300,7 @@ private void checkEventOrgUnitWriteAccess(
304300
OrganisationUnit eventOrgUnit,
305301
boolean isCreatableInSearchScope,
306302
UserDetails user) {
307-
if (eventOrgUnit == null) {
308-
log.warn(ORG_UNIT_NO_USER_ASSIGNED, event.getUid());
309-
} else if (isCreatableInSearchScope
303+
if (isCreatableInSearchScope
310304
? !user.isInUserEffectiveSearchOrgUnitHierarchy(eventOrgUnit.getPath())
311305
: !user.isInUserHierarchy(eventOrgUnit.getPath())) {
312306
reporter.addError(event, ValidationCode.E1000, user, eventOrgUnit);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
-- Delete invalid events linked to invalid enrollments.
2+
delete from event e where e.enrollmentid in (
3+
select en.enrollmentid
4+
from enrollment en join program p on en.programid = p.programid
5+
where p.type = 'WITH_REGISTRATION'
6+
and en.trackedentityid is null
7+
);
8+
9+
-- Delete invalid enrollments that are part of a tracker program and
10+
-- have null tracked entity.
11+
delete from enrollment en where en.programid in (
12+
select p.programid
13+
from program p
14+
where p.type = 'WITH_REGISTRATION'
15+
)
16+
and en.trackedentityid is null;
17+
18+
-- Update null organisation unit of enrollments to organisation unit of one of its events
19+
update enrollment en set organisationunitid =
20+
(select distinct ev.organisationunitid
21+
from event ev
22+
where en.enrollmentid = ev.enrollmentid
23+
and ev.organisationunitid is not null
24+
limit 1)
25+
where en.organisationunitid is null;
26+
27+
-- If organisationunitid column is still null for any placeholder enrollment,
28+
-- update organisation unit to root organisation unit.
29+
-- Placeholder enrollments do not have a tracked entity, so we need to use one well-know
30+
-- organisation unit.
31+
-- Organisation unit for this enrollments is never used anyway but we still need to fill in a value.
32+
update enrollment en set organisationunitid = (
33+
select distinct organisationunitid
34+
from organisationunit
35+
where parentid is null
36+
limit 1
37+
)
38+
where en.organisationunitid is null
39+
and (select type from program p where en.programid = p.programid) = 'WITHOUT_REGISTRATION';
40+
41+
-- If organisationunitid column is still null for any enrollment that is not a placeholder,
42+
-- use the tracked entity organisation unit.
43+
-- Tracked entity organisation unit is guaranteed to be not null.
44+
update enrollment en set organisationunitid =
45+
(select te.organisationunitid
46+
from trackedentity te
47+
where en.trackedentityid = te.trackedentityid)
48+
where en.organisationunitid is null
49+
and (select type from program p where en.programid = p.programid) = 'WITH_REGISTRATION';
50+
51+
alter table enrollment alter column organisationunitid set not null;
52+
53+
-- Update null organisation unit of event to organisation unit the enrollment
54+
-- that at this point is guaranteed to be not null.
55+
update event ev set organisationunitid = (
56+
select organisationunitid
57+
from enrollment en
58+
where en.enrollmentid = ev.enrollmentid)
59+
where ev.organisationunitid is null;
60+
61+
alter table event alter column organisationunitid set not null;

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/maintenance/MaintenanceServiceTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ void testDeleteSoftDeletedEnrollmentLinkedToATrackedEntityDataValueAudit()
335335
eventA.setScheduledDate(enrollmentDate);
336336
eventA.setUid("UID-A");
337337
eventA.setAttributeOptionCombo(coA);
338+
eventA.setOrganisationUnit(organisationUnit);
338339
manager.save(eventA);
339340
TrackedEntityDataValueChangeLog trackedEntityDataValueChangeLog =
340341
new TrackedEntityDataValueChangeLog(
@@ -364,6 +365,7 @@ void testDeleteSoftDeletedEventLinkedToARelationshipItem() {
364365
eventA.setScheduledDate(enrollmentDate);
365366
eventA.setUid(UID.generate().getValue());
366367
eventA.setAttributeOptionCombo(coA);
368+
eventA.setOrganisationUnit(organisationUnit);
367369
manager.save(eventA);
368370
long idA = eventA.getId();
369371
Relationship r = new Relationship();

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/program/ProgramMessageStoreTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ void setUp() {
111111

112112
enrollmentA = new Enrollment(new Date(), new Date(), trackedEntityB, programA);
113113
enrollmentA.setUid(CodeGenerator.generateUid());
114+
enrollmentA.setOrganisationUnit(orgUnitA);
114115

115116
eventA = createEvent(stageA, enrollmentA, orgUnitA);
116117
eventA.setScheduledDate(new Date());

dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/program/notification/ProgramNotificationServiceTest.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,26 +171,28 @@ void setUp() {
171171
Date enrollmentDate = testDate2.toDate();
172172
enrollmentA = new Enrollment(enrollmentDate, incidenDate, trackedEntityA, programA);
173173
enrollmentA.setUid("UID-PIA");
174+
enrollmentA.setOrganisationUnit(organisationUnitA);
174175
manager.save(enrollmentA);
175176
enrollmentB = new Enrollment(enrollmentDate, incidenDate, trackedEntityB, programB);
177+
enrollmentB.setOrganisationUnit(organisationUnitB);
176178
manager.save(enrollmentB);
177-
Event eventA = new Event(enrollmentA, stageA);
179+
Event eventA = new Event(enrollmentA, stageA, organisationUnitA);
178180
eventA.setScheduledDate(enrollmentDate);
179181
eventA.setUid("UID-A");
180182
eventA.setAttributeOptionCombo(coA);
181-
Event eventB = new Event(enrollmentA, stageB);
183+
Event eventB = new Event(enrollmentA, stageB, organisationUnitA);
182184
eventB.setScheduledDate(enrollmentDate);
183185
eventB.setUid("UID-B");
184186
eventB.setAttributeOptionCombo(coA);
185-
Event eventC = new Event(enrollmentB, stageC);
187+
Event eventC = new Event(enrollmentB, stageC, organisationUnitA);
186188
eventC.setScheduledDate(enrollmentDate);
187189
eventC.setUid("UID-C");
188190
eventC.setAttributeOptionCombo(coA);
189-
Event eventD1 = new Event(enrollmentB, stageD);
191+
Event eventD1 = new Event(enrollmentB, stageD, organisationUnitA);
190192
eventD1.setScheduledDate(enrollmentDate);
191193
eventD1.setUid("UID-D1");
192194
eventD1.setAttributeOptionCombo(coA);
193-
Event eventD2 = new Event(enrollmentB, stageD);
195+
Event eventD2 = new Event(enrollmentB, stageD, organisationUnitA);
194196
eventD2.setScheduledDate(enrollmentDate);
195197
eventD2.setUid("UID-D2");
196198
eventD2.setAttributeOptionCombo(coA);
@@ -281,15 +283,15 @@ void testGetEventsWithScheduledNotifications() {
281283
cal.add(Calendar.DATE, -2);
282284
Date yesterday = cal.getTime();
283285
// Events
284-
Event eventA = new Event(enrollmentA, stageA);
286+
Event eventA = new Event(enrollmentA, stageA, organisationUnitA);
285287
eventA.setScheduledDate(tomorrow);
286288
eventA.setAttributeOptionCombo(coA);
287289
manager.save(eventA);
288-
Event eventB = new Event(enrollmentB, stageB);
290+
Event eventB = new Event(enrollmentB, stageB, organisationUnitA);
289291
eventB.setScheduledDate(today);
290292
eventB.setAttributeOptionCombo(coA);
291293
manager.save(eventB);
292-
Event eventC = new Event(enrollmentB, stageC);
294+
Event eventC = new Event(enrollmentB, stageC, organisationUnitA);
293295
eventC.setScheduledDate(yesterday);
294296
eventC.setAttributeOptionCombo(coA);
295297
manager.save(eventC);
@@ -415,8 +417,10 @@ void testGetEnrollmentsWithScheduledNotifications() {
415417
Date aWeekAgo = cal.getTime();
416418
// Enrollments
417419
Enrollment enrollmentC = new Enrollment(today, tomorrow, trackedEntityX, programA);
420+
enrollmentC.setOrganisationUnit(organisationUnitA);
418421
manager.save(enrollmentC);
419422
Enrollment enrollmentD = new Enrollment(aWeekAgo, yesterday, trackedEntityY, programA);
423+
enrollmentD.setOrganisationUnit(organisationUnitA);
420424
manager.save(enrollmentD);
421425
// Queries
422426
List<Enrollment> results;

0 commit comments

Comments
 (0)