Skip to content

Commit

Permalink
Merge pull request #24 from EyeSeeTea/feature/bring_from_widp_add_ind…
Browse files Browse the repository at this point in the history
…icators_to_event_screen

Feature/bring from widp add indicators to event screen
  • Loading branch information
ifoche authored Jul 17, 2020
2 parents ecdbdd0 + 3338878 commit c8d8a7e
Show file tree
Hide file tree
Showing 22 changed files with 817 additions and 18 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ android {
applicationId "com.eyeseetea.widp"
dimension "default"
versionCode versions.vCode
versionName "1.0.0"
versionName "2.1.2-widp-fork-1"
}

psi {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/assets/paperwork.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"buildTime":"2020-07-17 17:34","gitSha":"46259d5e6"}
{"buildTime":"2020-07-17 18:27","gitSha":"ceaa6f433"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package org.dhis2.data.forms.dataentry;

import static android.text.TextUtils.isEmpty;

import android.database.Cursor;

import org.dhis2.data.forms.FormRepository;
import org.dhis2.utils.DateUtils;
import org.dhis2.utils.Result;
import org.hisp.dhis.android.core.D2;
import org.hisp.dhis.android.core.common.BaseIdentifiableObject;
import org.hisp.dhis.rules.RuleEngine;
import org.hisp.dhis.rules.models.RuleDataValue;
import org.hisp.dhis.rules.models.RuleEffect;
import org.hisp.dhis.rules.models.RuleEvent;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Nonnull;

import androidx.annotation.NonNull;
import io.reactivex.Flowable;

public final class EventsRuleEngineRepository implements RuleEngineRepository {
private static final String QUERY_EVENT = "SELECT Event.uid,\n" +
" Event.programStage,\n" +
" Event.status,\n" +
" Event.eventDate,\n" +
" Event.dueDate,\n" +
" Event.organisationUnit,\n" +
" ProgramStage.displayName\n" +
"FROM Event\n" +
"JOIN ProgramStage ON ProgramStage.uid = Event.programStage\n" +
"WHERE Event.uid = ?\n" +
" AND Event.deleted != 1\n" +
"LIMIT 1;";

private static final String QUERY_VALUES = "SELECT " +
" Event.eventDate," +
" Event.programStage," +
" TrackedEntityDataValue.dataElement," +
" TrackedEntityDataValue.value," +
" ProgramRuleVariable.useCodeForOptionSet," +
" Option.code," +
" Option.name" +
" FROM TrackedEntityDataValue " +
" INNER JOIN Event ON TrackedEntityDataValue.event = Event.uid " +
" INNER JOIN DataElement ON DataElement.uid = TrackedEntityDataValue.dataElement " +
" LEFT JOIN ProgramRuleVariable ON ProgramRuleVariable.dataElement = DataElement.uid " +
" LEFT JOIN Option ON (Option.optionSet = DataElement.optionSet AND Option.code = TrackedEntityDataValue.value) " +
" WHERE Event.uid = ? AND value IS NOT NULL AND Event.deleted != 1;";

@NonNull
private final D2 d2;

@NonNull
private final FormRepository formRepository;

@NonNull
private final String eventUid;

public EventsRuleEngineRepository(@NonNull D2 d2,
@NonNull FormRepository formRepository, @NonNull String eventUid) {
this.d2 = d2;
this.formRepository = formRepository;
this.eventUid = eventUid;
}

@Override
public Flowable<RuleEngine> updateRuleEngine() {
return formRepository.restartRuleEngine();
}

@NonNull
@Override
public Flowable<Result<RuleEffect>> calculate() {
return queryDataValues()
.switchMap(this::queryEvent)
.switchMap(event -> formRepository.ruleEngine()
.switchMap(ruleEngine -> Flowable.fromCallable(ruleEngine.evaluate(event))
.map(Result::success)
.onErrorReturn(error -> Result.failure(new Exception(error)))
)
);
}

@NonNull
@Override
public Flowable<Result<RuleEffect>> reCalculate() {
return calculate();
}

@NonNull
private Flowable<RuleEvent> queryEvent(@NonNull List<RuleDataValue> dataValues) {
RuleEvent ruleEvent = null;

Cursor cursor = d2.databaseAdapter().rawQuery(QUERY_EVENT, eventUid == null ? "" : eventUid);

if (cursor != null && cursor.moveToFirst()) {

String eventUid = cursor.getString(0);
String programStageUid = cursor.getString(1);
RuleEvent.Status status = RuleEvent.Status.valueOf(cursor.getString(2));
Date eventDate = null;
try {
eventDate = cursor.isNull(3) ? null : parseDate(cursor.getString(3));
} catch (ParseException e) {
e.printStackTrace();
}
Date dueDate = null;
try {
dueDate = cursor.isNull(4) ? eventDate : parseDate(cursor.getString(4));
} catch (ParseException e) {
e.printStackTrace();
}
String orgUnit = cursor.getString(5);
String orgUnitCode = getOrgUnitCode(orgUnit);
String programStageName = cursor.getString(6);

ruleEvent = RuleEvent.builder()
.event(eventUid)
.programStage(programStageUid)
.programStageName(programStageName)
.status(status)
.eventDate(eventDate == null ? dueDate : eventDate)
.dueDate(dueDate)
.organisationUnit(orgUnit)
.organisationUnitCode(orgUnitCode)
.dataValues(dataValues)
.build();

cursor.close();
}

return Flowable.just(ruleEvent);
}

@Nonnull
private String getOrgUnitCode(String orgUnitUid) {
String ouCode = "";
try (Cursor cursor = d2.databaseAdapter().rawQuery("SELECT code FROM OrganisationUnit WHERE uid = ? LIMIT 1", orgUnitUid)) {
if (cursor != null && cursor.moveToFirst() && cursor.getString(0) != null) {
ouCode = cursor.getString(0);
}
}
return ouCode;
}

@NonNull
private Flowable<List<RuleDataValue>> queryDataValues() {
List<RuleDataValue> dataValues = new ArrayList<>();

Cursor cursor = d2.databaseAdapter().rawQuery(QUERY_VALUES, eventUid == null ? "" : eventUid);

if (cursor != null && cursor.moveToFirst()) {
//add row to list
while (cursor.moveToNext()) {
Date eventDate = null;
try {
eventDate = DateUtils.databaseDateFormat().parse(cursor.getString(0));
} catch (ParseException e) {
e.printStackTrace();
}
String programStage = cursor.getString(1);
String dataElement = cursor.getString(2);
String value = cursor.getString(3) != null ? cursor.getString(3) : "";
Boolean useCode = cursor.getInt(4) == 1;
String optionCode = cursor.getString(5);
String optionName = cursor.getString(6);
if (!isEmpty(optionCode) && !isEmpty(optionName))
value = useCode ? optionCode : optionName; //If de has optionSet then check if value should be code or name for program rules
dataValues.add(RuleDataValue.create(eventDate, programStage, dataElement, value));
}

cursor.close();
}

return Flowable.fromIterable(dataValues).toList().toFlowable();
}

@NonNull
private static Date parseDate(@NonNull String date) throws ParseException {
return BaseIdentifiableObject.DATE_FORMAT.parse(date);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.dhis2.data.forms.dataentry.fields.FieldViewModel;
import org.dhis2.databinding.ActivityEventCaptureBinding;
import org.dhis2.databinding.WidgetDatepickerBinding;
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.indicators.EventIndicatorsDialogFragment;
import org.dhis2.usescases.eventsWithoutRegistration.eventInitial.EventInitialActivity;
import org.dhis2.usescases.general.ActivityGlobalAbstract;
import org.dhis2.utils.ColorUtils;
Expand All @@ -48,6 +49,8 @@

import javax.inject.Inject;

import androidx.fragment.app.FragmentManager;
import io.reactivex.functions.Consumer;
import timber.log.Timber;

import static org.dhis2.utils.Constants.PROGRAM_UID;
Expand All @@ -70,6 +73,17 @@ public class EventCaptureActivity extends ActivityGlobalAbstract implements Even
private EventMode eventMode;
public EventCaptureComponent eventCaptureComponent;

private String programUid;
private String eventUid;

public String getProgramUid() {
return programUid;
}

public String getEventUid() {
return eventUid;
}

public static Bundle getActivityBundle(@NonNull String eventUid, @NonNull String programUid, @NonNull EventMode eventMode) {
Bundle bundle = new Bundle();
bundle.putString(Constants.EVENT_UID, eventUid);
Expand All @@ -80,10 +94,12 @@ public static Bundle getActivityBundle(@NonNull String eventUid, @NonNull String

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
programUid = getIntent().getStringExtra(Constants.PROGRAM_UID);
eventUid = getIntent().getStringExtra(Constants.EVENT_UID);

eventCaptureComponent = (ExtensionsKt.app(this)).userComponent().plus(
new EventCaptureModule(
this,
getIntent().getStringExtra(Constants.EVENT_UID)));
this, eventUid, programUid));
eventCaptureComponent.inject(this);
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_event_capture);
Expand Down Expand Up @@ -399,6 +415,11 @@ public void showMoreOptions(View view) {
Timber.e(e);
}
popupMenu.getMenuInflater().inflate(R.menu.event_menu, popupMenu.getMenu());

if(binding.indicators.getVisibility() == View.GONE){
popupMenu.getMenu().removeItem(R.id.menu_indicators);
}

popupMenu.setOnMenuItemClickListener(item -> {
switch (item.getItemId()) {
case R.id.showHelp:
Expand All @@ -411,6 +432,9 @@ public void showMoreOptions(View view) {
case R.id.menu_overview:
goToInitialScreen();
break;
case R.id.menu_indicators:
showIndicators();
break;
default:
break;
}
Expand All @@ -420,6 +444,29 @@ public void showMoreOptions(View view) {
popupMenu.show();
}

public void showIndicators(View view) {
showIndicators();
}

public void showIndicators() {
FragmentManager fm = getSupportFragmentManager();

EventIndicatorsDialogFragment eventIndicatorsDialogFragment =
EventIndicatorsDialogFragment.Companion.create();

eventIndicatorsDialogFragment.show(fm);
}

@Override
public void showIndicatorsIcon() {
binding.indicators.setVisibility(View.VISIBLE);
}

@Override
public void hideIndicatorsIcon() {
binding.indicators.setVisibility(View.GONE);
}

@Override
public void showTutorial(boolean shaked) {
showToast(getString(R.string.no_intructions));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
import org.dhis2.data.dagger.PerActivity;
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.EventCaptureFragment.EventCaptureFormComponent;
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.EventCaptureFragment.EventCaptureFormModule;
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.indicators.EventIndicatorsComponent;
import org.dhis2.usescases.eventsWithoutRegistration.eventCapture.indicators.EventIndicatorsModule;

import androidx.annotation.NonNull;
import dagger.Subcomponent;

@PerActivity
@Subcomponent(modules = EventCaptureModule.class)
public interface EventCaptureComponent {

void inject(EventCaptureActivity activity);

@NonNull
EventIndicatorsComponent plus(EventIndicatorsModule eventIndicatorsModule);

EventCaptureFormComponent plus(EventCaptureFormModule formModule);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
import org.dhis2.data.forms.dataentry.DataEntryStore;
import org.dhis2.data.forms.dataentry.fields.FieldViewModel;
import org.dhis2.data.tuples.Pair;
import org.dhis2.data.tuples.Trio;
import org.dhis2.usescases.general.AbstractActivityContracts;
import org.dhis2.utils.Result;
import org.dhis2.utils.RulesActionCallbacks;
import org.hisp.dhis.android.core.event.EventStatus;
import org.hisp.dhis.android.core.organisationunit.OrganisationUnitLevel;
import org.hisp.dhis.android.core.program.ProgramIndicator;
import org.hisp.dhis.rules.models.RuleEffect;
import org.jetbrains.annotations.NotNull;

Expand Down Expand Up @@ -64,6 +65,10 @@ public interface View extends AbstractActivityContracts.View {

void updateNoteBadge(int numberOfNotes);

void showIndicatorsIcon();

void hideIndicatorsIcon();

void showLoopWarning();

void goBack();
Expand Down Expand Up @@ -169,6 +174,10 @@ public interface EventCaptureRepository {
Single<Integer> getNoteCount();

List<String> getOptionsFromGroups(List<String> optionGroupUids);

Flowable<List<ProgramIndicator>> getIndicators( String programUid);

Observable<Trio<ProgramIndicator, String, String>> getLegendColorForIndicator(ProgramIndicator programIndicator, String value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ public class EventCaptureModule {

private final String eventUid;
private final EventCaptureContract.View view;
private final String programUid;

public EventCaptureModule(EventCaptureContract.View view, String eventUid) {
public EventCaptureModule(EventCaptureContract.View view, String eventUid, String programUid) {
this.view = view;
this.eventUid = eventUid;
this.programUid = programUid;
}

@Provides
Expand All @@ -41,7 +43,7 @@ EventCaptureContract.Presenter providePresenter(@NonNull EventCaptureContract.Ev
@NonNull RulesUtilsProvider ruleUtils,
@NonNull ValueStore valueStore,
SchedulerProvider schedulerProvider) {
return new EventCapturePresenterImpl(view, eventUid, eventCaptureRepository, ruleUtils, valueStore, schedulerProvider);
return new EventCapturePresenterImpl(view, eventUid,programUid, eventCaptureRepository, ruleUtils, valueStore, schedulerProvider);
}

@Provides
Expand Down
Loading

0 comments on commit c8d8a7e

Please sign in to comment.