Skip to content

Commit

Permalink
chore: Load all events for rule-engine context [DHIS2-18089]
Browse files Browse the repository at this point in the history
  • Loading branch information
enricocolasante committed Oct 15, 2024
1 parent 0ae2a2d commit 07a3d76
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.hisp.dhis.dxf2.events.event.EventQueryParams;
import org.hisp.dhis.dxf2.events.event.EventService;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramInstance;
import org.hisp.dhis.program.ProgramStageInstance;
import org.hisp.dhis.program.ProgramStageInstanceService;
import org.hisp.dhis.programrule.engine.ProgramRuleEngine;
import org.hisp.dhis.rules.models.RuleEffects;
import org.hisp.dhis.trackedentity.TrackedEntityInstance;
Expand Down Expand Up @@ -79,6 +82,10 @@ public class DefaultTrackerProgramRuleService implements TrackerProgramRuleServi
private final TrackerConverterService<Attribute, TrackedEntityAttributeValue>
attributeValueTrackerConverterService;

private final EventService eventService;

private final ProgramStageInstanceService programStageInstanceService;

/**
* This method is calling rule engine for every enrollment and all the linked events, for all
* events linked to an enrollment not present in the payload and for all the program events.
Expand Down Expand Up @@ -196,22 +203,19 @@ private ProgramInstance getEnrollment(TrackerBundle bundle, String enrollmentUid
}

private Set<ProgramStageInstance> getEventsFromEnrollment(
String enrollment, TrackerBundle bundle) {
List<String> bundleEventUids =
bundle.getEvents().stream().map(Event::getUid).collect(Collectors.toList());
String enrollmentUid, TrackerBundle bundle) {
EventQueryParams eventQueryParams = new EventQueryParams();
eventQueryParams.setProgramInstances(Set.of(enrollmentUid));
List<org.hisp.dhis.dxf2.events.event.Event> events =
eventService.getEvents(eventQueryParams).getEvents();

// Get all programStageInstances from preheat that are linked to
// enrollment
// and are not present in the payload
Stream<ProgramStageInstance> programStageInstances =
bundle.getPreheat().getEvents().values().stream()
.filter(e -> e.getProgramInstance().getUid().equals(enrollment))
.filter(e -> !bundleEventUids.contains(e.getUid()));
events.stream().map(e -> programStageInstanceService.getProgramStageInstance(e.getUid()));

// All events in the payload that are linked to enrollment
Stream<ProgramStageInstance> bundleEvents =
bundle.getEvents().stream()
.filter(e -> e.getEnrollment().equals(enrollment))
.filter(e -> e.getEnrollment().equals(enrollmentUid))
.map(
event ->
eventTrackerConverterService.fromForRuleEngine(bundle.getPreheat(), event));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ protected void setUpTest() throws IOException {
user.getGroups().add(userGroup);
manager.update(user);

injectSecurityContext(user);

templateForEnrollment =
createProgramNotification(
"enrollment",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,27 @@
import static org.hisp.dhis.tracker.report.TrackerErrorCode.E1307;
import static org.hisp.dhis.tracker.report.TrackerErrorCode.E1308;
import static org.hisp.dhis.tracker.report.TrackerErrorCode.E1310;
import static org.hisp.dhis.utils.Assertions.assertContainsOnly;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import org.hisp.dhis.dataelement.DataElement;
import org.hisp.dhis.dxf2.metadata.objectbundle.ObjectBundle;
import org.hisp.dhis.eventdatavalue.EventDataValue;
import org.hisp.dhis.preheat.PreheatIdentifier;
import org.hisp.dhis.program.Program;
import org.hisp.dhis.program.ProgramStage;
import org.hisp.dhis.program.ProgramStageInstance;
import org.hisp.dhis.programrule.ProgramRule;
import org.hisp.dhis.programrule.ProgramRuleAction;
import org.hisp.dhis.programrule.ProgramRuleActionService;
import org.hisp.dhis.programrule.ProgramRuleActionType;
import org.hisp.dhis.programrule.ProgramRuleService;
import org.hisp.dhis.programrule.ProgramRuleVariable;
import org.hisp.dhis.programrule.ProgramRuleVariableService;
import org.hisp.dhis.programrule.ProgramRuleVariableSourceType;
import org.hisp.dhis.setting.SettingKey;
import org.hisp.dhis.setting.SystemSettingManager;
import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
Expand All @@ -56,7 +62,10 @@
import org.hisp.dhis.tracker.TrackerImportStrategy;
import org.hisp.dhis.tracker.TrackerTest;
import org.hisp.dhis.tracker.report.TrackerImportReport;
import org.hisp.dhis.util.DateUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.springframework.beans.factory.annotation.Autowired;

class ProgramRuleAssignActionTest extends TrackerTest {
Expand All @@ -74,15 +83,16 @@ class ProgramRuleAssignActionTest extends TrackerTest {

private DataElement dataElement1;

private DataElement dataElement2;

private TrackedEntityAttribute attribute1;

@Override
public void initTest() throws IOException {
ObjectBundle bundle = setUpMetadata("tracker/simple_metadata.json");
program = bundle.getPreheat().get(PreheatIdentifier.UID, Program.class, "BFcipDERJnf");
dataElement1 = bundle.getPreheat().get(PreheatIdentifier.UID, DataElement.class, "DATAEL00001");
DataElement dataElement2 =
bundle.getPreheat().get(PreheatIdentifier.UID, DataElement.class, "DATAEL00002");
dataElement2 = bundle.getPreheat().get(PreheatIdentifier.UID, DataElement.class, "DATAEL00002");
attribute1 =
bundle.getPreheat().get(PreheatIdentifier.UID, TrackedEntityAttribute.class, "dIVt4l5vIOa");
TrackedEntityAttribute attribute2 =
Expand All @@ -94,17 +104,22 @@ public void initTest() throws IOException {
programRuleVariableService.addProgramRuleVariable(programRuleVariable);
programRuleVariableService.addProgramRuleVariable(programRuleVariableAttribute);

ProgramRuleVariable programRuleVariablePreviousEvent =
createProgramRuleVariableWithDataElement('C', program, dataElement1);
programRuleVariablePreviousEvent.setSourceType(
ProgramRuleVariableSourceType.DATAELEMENT_PREVIOUS_EVENT);
programRuleVariableService.addProgramRuleVariable(programRuleVariablePreviousEvent);

injectAdminUser();

assignProgramRule();
trackerImportService.importTracker(
fromJson("tracker/programrule/tei_enrollment_completed_event.json"));
}

@Test
void shouldNotImportWithWarningWhenAttributeWithSameValueIsAssignedByAssignRule()
throws IOException {

assignProgramRule();
TrackerImportParams params =
fromJson("tracker/programrule/te_enrollment_update_attribute_same_value.json");
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
Expand All @@ -115,9 +130,44 @@ void shouldNotImportWithWarningWhenAttributeWithSameValueIsAssignedByAssignRule(
assertEquals(E1310, importReport.getValidationReport().getWarnings().get(0).getWarningCode());
}

@ParameterizedTest
@CsvSource({"2024-02-10,THIRD", "2024-01-28,SECOND", "2024-01-19,FIRST"})
void shouldImportEventAndCorrectlyAssignPreviousEventDataValue(
String eventOccurredDate, String previousEventDataValue) throws IOException {
TrackerImportParams params =
fromJson("tracker/programrule/three_events_with_different_dates.json");
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);

trackerImportService.importTracker(params);

assignPreviousEventProgramRule();

dbmsManager.clearSession();
dbmsManager.flushSession();

params = fromJson("tracker/programrule/event_with_data_value.json");

params.getEvents().get(0).setOccurredAt(DateUtils.instantFromDateAsString(eventOccurredDate));

TrackerImportReport importReport = trackerImportService.importTracker(params);
assertEquals(E1308, importReport.getValidationReport().getWarnings().get(0).getWarningCode());

ProgramStageInstance event = manager.get(ProgramStageInstance.class, "D9PbzJY8bZZ");

List<String> eventDataValues =
event.getEventDataValues().stream()
.filter(dv -> dv.getDataElement().equals("DATAEL00002"))
.map(EventDataValue::getValue)
.collect(Collectors.toList());
assertContainsOnly(List.of(previousEventDataValue), eventDataValues);
}

@Test
void shouldImportWithWarningWhenDataElementWithSameValueIsAssignedByAssignRule()
throws IOException {
assignProgramRule();
dbmsManager.clearSession();
dbmsManager.flushSession();
TrackerImportParams params =
fromJson("tracker/programrule/event_update_datavalue_same_value.json");
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
Expand All @@ -130,6 +180,7 @@ void shouldImportWithWarningWhenDataElementWithSameValueIsAssignedByAssignRule()

@Test
void shouldNotImportWhenDataElementWithDifferentValueIsAssignedByAssignRule() throws IOException {
assignProgramRule();
TrackerImportParams params =
fromJson("tracker/programrule/event_update_datavalue_different_value.json");
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
Expand All @@ -143,6 +194,7 @@ void shouldNotImportWhenDataElementWithDifferentValueIsAssignedByAssignRule() th
void
shouldImportWithWarningWhenDataElementWithDifferentValueIsAssignedByAssignRuleAndOverwriteKeyIsTrue()
throws IOException {
assignProgramRule();
systemSettingManager.saveSystemSetting(SettingKey.RULE_ENGINE_ASSIGN_OVERWRITE, true);
TrackerImportParams params =
fromJson("tracker/programrule/event_update_datavalue_different_value.json");
Expand All @@ -158,7 +210,10 @@ void shouldNotImportWhenDataElementWithDifferentValueIsAssignedByAssignRule() th
void
shouldImportWithWarningWhenDataElementWithDifferentAndEmptyValueIsAssignedByAssignRuleAndOverwriteKeyIsTrue()
throws IOException {
assignProgramRule();
systemSettingManager.saveSystemSetting(SettingKey.RULE_ENGINE_ASSIGN_OVERWRITE, true);
dbmsManager.clearSession();
dbmsManager.flushSession();
TrackerImportParams params =
fromJson("tracker/programrule/event_update_datavalue_empty_value.json");
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
Expand All @@ -183,6 +238,16 @@ private void assignProgramRule() {
programRuleService.updateProgramRule(programRule);
}

private void assignPreviousEventProgramRule() {
ProgramRule programRule = createProgramRule('G', program, null, "true");
programRuleService.addProgramRule(programRule);
ProgramRuleAction programRuleAction =
createProgramRuleAction(programRule, ASSIGN, dataElement2, "#{ProgramRuleVariableC}");
programRuleActionService.addProgramRuleAction(programRuleAction);
programRule.getProgramRuleActions().add(programRuleAction);
programRuleService.updateProgramRule(programRule);
}

private ProgramRule createProgramRule(
char uniqueCharacter, Program program, ProgramStage programStage, String condition) {
ProgramRule programRule = createProgramRule(uniqueCharacter, program);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"enrollments": [],
"events": [
{
"event": "D9PbzJY8bJO",
"event": "D9PbzJY8bJX",
"status": "COMPLETED",
"program": {
"idScheme": "UID",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"trackedEntities": [],
"enrollments": [],
"events": [
{
"event": "D9PbzJY8bZZ",
"status": "COMPLETED",
"program": {
"idScheme": "UID",
"identifier": "BFcipDERJnf"
},
"programStage": {
"idScheme": "UID",
"identifier": "NpsdDv6kKSO"
},
"enrollment": "TvctPPhpD8u",
"orgUnit": {
"idScheme": "UID",
"identifier": "h4w96yEMlzO"
},
"relationships": [],
"scheduledAt": "2019-01-25T12:10:38.100",
"storedBy": "admin",
"deleted": false,
"attributeOptionCombo": {
"idScheme": "UID"
},
"attributeCategoryOptions": [],

"dataValues": [
{
"storedBy": "admin",
"providedElsewhere": false,
"dataElement": {
"idScheme": "UID",
"identifier": "DATAEL00001"
},
"value": "LAST"
}
],
"notes": []
}
],
"relationships": []
}
Loading

0 comments on commit 07a3d76

Please sign in to comment.