Skip to content

Commit

Permalink
#6062 - add feature type property to add soft/warning validation for … (
Browse files Browse the repository at this point in the history
#7526)

* #6062 - add feature type property to add soft/warning validation for follow up until field

* #6862 - Don't automatically overwrite follow-up until date when new property is enabled

* #6862 - Fixed merge conflicts

Co-authored-by: Maté Strysewske <mate.strysewske@vitagroup.ag>
  • Loading branch information
BarnaBartha and MateStrysewske committed Dec 17, 2021
1 parent a9c9b13 commit 967f4f0
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 55 deletions.
Expand Up @@ -28,14 +28,14 @@
import org.apache.commons.lang3.StringUtils;

import de.symeda.sormas.api.EntityDto;
import de.symeda.sormas.api.infrastructure.facility.FacilityType;
import de.symeda.sormas.api.followup.FollowUpLogic;
import de.symeda.sormas.api.followup.FollowUpPeriodDto;
import de.symeda.sormas.api.followup.FollowUpStartDateType;
import de.symeda.sormas.api.hospitalization.HospitalizationDto;
import de.symeda.sormas.api.hospitalization.PreviousHospitalizationDto;
import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto;
import de.symeda.sormas.api.infrastructure.district.DistrictReferenceDto;
import de.symeda.sormas.api.infrastructure.facility.FacilityType;
import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto;
import de.symeda.sormas.api.sample.SampleDto;
import de.symeda.sormas.api.utils.ValidationException;
Expand Down Expand Up @@ -160,18 +160,18 @@ public static void handleHospitalization(CaseDataDto caze, CaseDataDto oldCase,
* the disease, the current follow-up until date and the date of the last cooperative visit.
*
* @param ignoreOverwrite
* Returns the expected follow-up until date based on case start date, follow-up duration of the disease and date of the
* last cooperative visit. Ignores current follow-up until date and whether or not follow-up until has been overwritten.
* Ignores current follow-up until date and whether or not follow-up until has been overwritten.
*/
public static FollowUpPeriodDto calculateFollowUpUntilDate(
CaseDataDto caze,
FollowUpPeriodDto followUpPeriod,
List<VisitDto> visits,
int followUpDuration,
boolean ignoreOverwrite) {
boolean ignoreOverwrite,
boolean allowFreeOverwrite) {

Date overwriteUntilDate = !ignoreOverwrite && caze.isOverwriteFollowUpUntil() ? caze.getFollowUpUntil() : null;
return FollowUpLogic.calculateFollowUpUntilDate(followUpPeriod, overwriteUntilDate, visits, followUpDuration);
return FollowUpLogic.calculateFollowUpUntilDate(followUpPeriod, overwriteUntilDate, visits, followUpDuration, allowFreeOverwrite);
}

public static RegionReferenceDto getRegionWithFallback(CaseDataDto caze) {
Expand Down
Expand Up @@ -77,9 +77,10 @@ public static FollowUpPeriodDto calculateFollowUpUntilDate(
FollowUpPeriodDto followUpPeriod,
List<VisitDto> visits,
int followUpDuration,
boolean ignoreOverwrite) {
boolean ignoreOverwrite,
boolean allowFreeOverwrite) {

Date overwriteUntilDate = !ignoreOverwrite && contact.isOverwriteFollowUpUntil() ? contact.getFollowUpUntil() : null;
return FollowUpLogic.calculateFollowUpUntilDate(followUpPeriod, overwriteUntilDate, visits, followUpDuration);
return FollowUpLogic.calculateFollowUpUntilDate(followUpPeriod, overwriteUntilDate, visits, followUpDuration, allowFreeOverwrite);
}
}
Expand Up @@ -37,7 +37,11 @@ public enum FeatureType {
true,
new FeatureType[] {
CASE_SURVEILANCE },
ImmutableMap.of(FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT, Boolean.TRUE)),
ImmutableMap.of(
FeatureTypeProperty.AUTOMATIC_RESPONSIBILITY_ASSIGNMENT,
Boolean.TRUE,
FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE,
Boolean.FALSE)),
EVENT_SURVEILLANCE(true, true, null, null),
SAMPLES_LAB(true,
true,
Expand Down Expand Up @@ -65,7 +69,7 @@ public enum FeatureType {
false,
new FeatureType[] {
CASE_SURVEILANCE },
null),
ImmutableMap.of(FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE, Boolean.FALSE)),
DOCUMENTS(true,
false,
new FeatureType[] {
Expand Down
Expand Up @@ -18,7 +18,8 @@
public enum FeatureTypeProperty {

REDUCED(Boolean.class),
AUTOMATIC_RESPONSIBILITY_ASSIGNMENT(Boolean.class);
AUTOMATIC_RESPONSIBILITY_ASSIGNMENT(Boolean.class),
ALLOW_FREE_FOLLOW_UP_OVERWRITE(Boolean.class);

private final Class<?> returnType;

Expand Down
Expand Up @@ -71,7 +71,9 @@ public static FollowUpPeriodDto calculateFollowUpUntilDate(
FollowUpPeriodDto followUpPeriod,
Date overwriteUntilDate,
List<VisitDto> visits,
int followUpDuration) {
int followUpDuration,
boolean allowFreeOverwrite) {

Date standardUntilDate = DateHelper.addDays(followUpPeriod.getFollowUpStartDate(), followUpDuration);
Date untilDate = overwriteUntilDate != null ? overwriteUntilDate : standardUntilDate;

Expand All @@ -94,8 +96,8 @@ public static FollowUpPeriodDto calculateFollowUpUntilDate(
}

// If the follow-up until date is before the standard follow-up until date for some reason (e.g. because the report date, last contact
// date or symptom onset date were changed), set it to the standard follow-up until date
if (DateHelper.getStartOfDay(untilDate).before(standardUntilDate)) {
// date or symptom onset date were changed), and allowFreeOverwrite is false, set it to the standard follow-up until date
if (!allowFreeOverwrite && DateHelper.getStartOfDay(untilDate).before(standardUntilDate)) {
untilDate = standardUntilDate;
}

Expand Down
Expand Up @@ -40,6 +40,7 @@ public interface Validations {
String caseClassificationInvalid = "caseClassificationInvalid";
String caseMultipleInfectionEnvironments = "caseMultipleInfectionEnvironments";
String contactFollowUpUntilDate = "contactFollowUpUntilDate";
String contactFollowUpUntilDateSoftValidation = "contactFollowUpUntilDateSoftValidation";
String contactWithoutInfrastructureData = "contactWithoutInfrastructureData";
String duplicateEpidNumber = "duplicateEpidNumber";
String duplicateExternalToken = "duplicateExternalToken";
Expand Down
1 change: 1 addition & 0 deletions sormas-api/src/main/resources/validations.properties
Expand Up @@ -138,6 +138,7 @@ caseMultipleInfectionEnvironments = This case already contains an exposure that
statisticsIncidenceOnlyNumbersAllowed = The incidence divisor must be a number. It has been reset to the previous value.
noPastDateAllowed = You need to enter a date in the present or future
contactFollowUpUntilDate = The follow-up until date must at least be on the day the standard follow-up duration for the disease would end.
contactFollowUpUntilDateSoftValidation = The follow-up until date should at least be on the day the standard follow-up duration for the disease would end.
emptyOverwrittenFollowUpUntilDate = The follow-up until date cannot be overwritten with an empty value.
textTooLong = The text you entered is too long. Maximum allowed length is {max}
textSizeNotInRange = The text you entered is not valid. It's length must be between {min} and {max}
Expand Down
Expand Up @@ -3550,7 +3550,8 @@ public FollowUpPeriodDto calculateFollowUpUntilDate(CaseDataDto caseDto, boolean
CaseLogic.getFollowUpStartDate(caseDto, sampleFacade.getByCaseUuids(Collections.singletonList(caseDto.getUuid()))),
visitFacade.getVisitsByCase(caseDto.toReference()),
diseaseConfigurationFacade.getCaseFollowUpDuration(caseDto.getDisease()),
ignoreOverwrite);
ignoreOverwrite,
featureConfigurationFacade.isPropertyValueTrue(FeatureType.CASE_FOLLOWUP, FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE));
}

public boolean isCaseEditAllowed(String caseUuid) {
Expand Down
Expand Up @@ -80,6 +80,7 @@
import de.symeda.sormas.api.externaldata.ExternalDataDto;
import de.symeda.sormas.api.externaldata.ExternalDataUpdateException;
import de.symeda.sormas.api.feature.FeatureType;
import de.symeda.sormas.api.feature.FeatureTypeProperty;
import de.symeda.sormas.api.followup.FollowUpLogic;
import de.symeda.sormas.api.infrastructure.facility.FacilityType;
import de.symeda.sormas.api.infrastructure.region.RegionReferenceDto;
Expand All @@ -97,6 +98,7 @@
import de.symeda.sormas.api.utils.criteria.CriteriaDateType;
import de.symeda.sormas.api.utils.criteria.ExternalShareDateType;
import de.symeda.sormas.backend.ExtendedPostgreSQL94Dialect;
import de.symeda.sormas.backend.caze.CaseFacadeEjb.CaseFacadeEjbLocal;
import de.symeda.sormas.backend.caze.transformers.CaseListEntryDtoResultTransformer;
import de.symeda.sormas.backend.caze.transformers.CaseSelectionDtoResultTransformer;
import de.symeda.sormas.backend.clinicalcourse.ClinicalCourse;
Expand Down Expand Up @@ -185,7 +187,7 @@ public class CaseService extends AbstractCoreAdoService<Case> {
@EJB
private DiseaseConfigurationFacadeEjb.DiseaseConfigurationFacadeEjbLocal diseaseConfigurationFacade;
@EJB
private CaseFacadeEjb.CaseFacadeEjbLocal caseFacade;
private CaseFacadeEjbLocal caseFacade;
@EJB
private VisitFacadeEjb.VisitFacadeEjbLocal visitFacade;

Expand Down Expand Up @@ -1226,7 +1228,7 @@ public void updateFollowUpDetails(Case caze, boolean followUpStatusChangedByUser
statusChangedBySystem = true;
}
} else {
CaseDataDto caseDto = caseFacade.toDto(caze);
CaseDataDto caseDto = CaseFacadeEjbLocal.toDto(caze);
Date currentFollowUpUntil = caseDto.getFollowUpUntil();

Date earliestSampleDate = null;
Expand All @@ -1237,15 +1239,15 @@ public void updateFollowUpDetails(Case caze, boolean followUpStatusChangedByUser
}
}

Date untilDate =
CaseLogic
.calculateFollowUpUntilDate(
caseDto,
CaseLogic.getFollowUpStartDate(caze.getSymptoms().getOnsetDate(), caze.getReportDate(), earliestSampleDate),
caze.getVisits().stream().map(visit -> visitFacade.toDto(visit)).collect(Collectors.toList()),
diseaseConfigurationFacade.getCaseFollowUpDuration(caze.getDisease()),
false)
.getFollowUpEndDate();
Date untilDate = CaseLogic
.calculateFollowUpUntilDate(
caseDto,
CaseLogic.getFollowUpStartDate(caze.getSymptoms().getOnsetDate(), caze.getReportDate(), earliestSampleDate),
caze.getVisits().stream().map(visit -> visitFacade.toDto(visit)).collect(Collectors.toList()),
diseaseConfigurationFacade.getCaseFollowUpDuration(caze.getDisease()),
false,
featureConfigurationFacade.isPropertyValueTrue(FeatureType.CASE_FOLLOWUP, FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE))
.getFollowUpEndDate();
caze.setFollowUpUntil(untilDate);
if (DateHelper.getStartOfDay(currentFollowUpUntil).before(DateHelper.getStartOfDay(untilDate))) {
caze.setOverwriteFollowUpUntil(false);
Expand Down
Expand Up @@ -97,6 +97,8 @@
import de.symeda.sormas.api.exposure.ExposureType;
import de.symeda.sormas.api.externaldata.ExternalDataDto;
import de.symeda.sormas.api.externaldata.ExternalDataUpdateException;
import de.symeda.sormas.api.feature.FeatureType;
import de.symeda.sormas.api.feature.FeatureTypeProperty;
import de.symeda.sormas.api.followup.FollowUpDto;
import de.symeda.sormas.api.followup.FollowUpPeriodDto;
import de.symeda.sormas.api.i18n.Captions;
Expand Down Expand Up @@ -1146,7 +1148,8 @@ public FollowUpPeriodDto calculateFollowUpUntilDate(ContactDto contactDto, boole
ContactLogic.getFollowUpStartDate(contactDto, sampleFacade.getByContactUuids(Collections.singletonList(contactDto.getUuid()))),
visitFacade.getVisitsByContact(contactDto.toReference()),
diseaseConfigurationFacade.getFollowUpDuration(contactDto.getDisease()),
ignoreOverwrite);
ignoreOverwrite,
featureConfigurationFacade.isPropertyValueTrue(FeatureType.CONTACT_TRACING, FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE));
}

@Override
Expand Down
Expand Up @@ -67,6 +67,8 @@
import de.symeda.sormas.api.dashboard.DashboardContactDto;
import de.symeda.sormas.api.externaldata.ExternalDataDto;
import de.symeda.sormas.api.externaldata.ExternalDataUpdateException;
import de.symeda.sormas.api.feature.FeatureType;
import de.symeda.sormas.api.feature.FeatureTypeProperty;
import de.symeda.sormas.api.followup.FollowUpLogic;
import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.api.i18n.Strings;
Expand All @@ -93,6 +95,7 @@
import de.symeda.sormas.backend.event.EventParticipant;
import de.symeda.sormas.backend.exposure.ExposureService;
import de.symeda.sormas.backend.externaljournal.ExternalJournalService;
import de.symeda.sormas.backend.feature.FeatureConfigurationFacadeEjb;
import de.symeda.sormas.backend.infrastructure.community.Community;
import de.symeda.sormas.backend.infrastructure.district.District;
import de.symeda.sormas.backend.infrastructure.region.Region;
Expand Down Expand Up @@ -143,6 +146,8 @@ public class ContactService extends AbstractCoreAdoService<Contact> {
private ExternalJournalService externalJournalService;
@EJB
private UserService userService;
@EJB
private FeatureConfigurationFacadeEjb.FeatureConfigurationFacadeEjbLocal featureConfigurationFacade;

public ContactService() {
super(Contact.class);
Expand Down Expand Up @@ -812,7 +817,9 @@ public void updateFollowUpDetails(Contact contact, boolean followUpStatusChanged
ContactLogic.getFollowUpStartDate(contact.getLastContactDate(), contact.getReportDateTime(), earliestSampleDate),
contact.getVisits().stream().map(visit -> visitFacade.toDto(visit)).collect(Collectors.toList()),
diseaseConfigurationFacade.getFollowUpDuration(contact.getDisease()),
false)
false,
featureConfigurationFacade
.isPropertyValueTrue(FeatureType.CONTACT_TRACING, FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE))
.getFollowUpEndDate();
contact.setFollowUpUntil(untilDate);
if (DateHelper.getStartOfDay(currentFollowUpUntil).before(DateHelper.getStartOfDay(untilDate))) {
Expand Down
57 changes: 43 additions & 14 deletions sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseDataForm.java
Expand Up @@ -45,8 +45,10 @@
import org.apache.commons.lang3.StringUtils;

import com.vaadin.icons.VaadinIcons;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.UserError;
import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.ui.Button;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Image;
Expand Down Expand Up @@ -90,6 +92,7 @@
import de.symeda.sormas.api.disease.DiseaseVariant;
import de.symeda.sormas.api.event.TypeOfPlace;
import de.symeda.sormas.api.feature.FeatureType;
import de.symeda.sormas.api.feature.FeatureTypeProperty;
import de.symeda.sormas.api.followup.FollowUpLogic;
import de.symeda.sormas.api.followup.FollowUpPeriodDto;
import de.symeda.sormas.api.i18n.Captions;
Expand Down Expand Up @@ -1239,20 +1242,46 @@ protected void addFields() {
symptoms.getOnsetDate(),
reportDate.getValue(),
FacadeProvider.getSampleFacade().getByCaseUuids(Collections.singletonList(caseUuid)));
Date minimumFollowUpUntilDate = FollowUpLogic
.calculateFollowUpUntilDate(
followUpPeriod,
null,
FacadeProvider.getVisitFacade().getVisitsByCase(new CaseReferenceDto(caseUuid)),
FacadeProvider.getDiseaseConfigurationFacade().getCaseFollowUpDuration((Disease) diseaseField.getValue()))
.getFollowUpEndDate();

dfFollowUpUntil.addValidator(
new DateRangeValidator(
I18nProperties.getValidationError(Validations.contactFollowUpUntilDate),
minimumFollowUpUntilDate,
null,
Resolution.DAY));
Date minimumFollowUpUntilDate =
FollowUpLogic
.calculateFollowUpUntilDate(
followUpPeriod,
null,
FacadeProvider.getVisitFacade().getVisitsByCase(new CaseReferenceDto(caseUuid)),
FacadeProvider.getDiseaseConfigurationFacade().getCaseFollowUpDuration((Disease) diseaseField.getValue()),
FacadeProvider.getFeatureConfigurationFacade()
.isPropertyValueTrue(FeatureType.CASE_FOLLOWUP, FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE))
.getFollowUpEndDate();

if (FacadeProvider.getFeatureConfigurationFacade()
.isPropertyValueTrue(FeatureType.CASE_FOLLOWUP, FeatureTypeProperty.ALLOW_FREE_FOLLOW_UP_OVERWRITE)) {
dfFollowUpUntil.addValueChangeListener(valueChangeEvent -> {

if (DateHelper.getEndOfDay(dfFollowUpUntil.getValue()).before(minimumFollowUpUntilDate)) {
dfFollowUpUntil.setComponentError(new ErrorMessage() {

@Override
public ErrorLevel getErrorLevel() {
return ErrorLevel.INFO;
}

@Override
public String getFormattedHtmlMessage() {
return I18nProperties.getValidationError(
Validations.contactFollowUpUntilDateSoftValidation,
I18nProperties.getPrefixCaption(CaseDataDto.I18N_PREFIX, CaseDataDto.FOLLOW_UP_UNTIL));
}
});
}
});
} else {
dfFollowUpUntil.addValidator(
new DateRangeValidator(
I18nProperties.getValidationError(Validations.contactFollowUpUntilDate),
minimumFollowUpUntilDate,
null,
Resolution.DAY));
}
}

// Overwrite visibility for quarantine fields
Expand Down

0 comments on commit 967f4f0

Please sign in to comment.