Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#13190 - Add date range filter for birthdate (from-to) to Persons, Ca… #13215

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ public class CaseCriteria extends CriteriaWithDateType implements ExternalShareC
private Date newCaseDateTo;
private Date creationDateFrom;
private Date creationDateTo;
private Date birthdateFrom;
private Date birthdateTo;
private boolean includePartialMatch;
private CriteriaDateType newCaseDateType;
// Used to re-construct whether users have filtered by epi weeks or dates
private DateFilterOption dateFilterOption = DateFilterOption.DATE;
Expand Down Expand Up @@ -552,6 +555,31 @@ public CaseCriteria creationDateTo(Date creationDateTo) {
return this;
}

public Date getBirthdateFrom() {
return birthdateFrom;
}

public void setBirthdateFrom(Date birthdateFrom) {
this.birthdateFrom = birthdateFrom;
}

public Date getBirthdateTo() {
return birthdateTo;
}

public void setBirthdateTo(Date birthdateTo) {
this.birthdateTo = birthdateTo;
}

@IgnoreForUrl
public boolean isIncludePartialMatch() {
return includePartialMatch;
}

public void setIncludePartialMatch(boolean includePartialMatch) {
this.includePartialMatch = includePartialMatch;
}

public Date getQuarantineTo() {
return quarantineTo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ public class ContactCriteria extends BaseCriteria implements Serializable {
private Boolean onlyContactsFromOtherInstances;
private Date creationDateFrom;
private Date creationDateTo;
private Date birthdateFrom;
private Date birthdateTo;
private boolean includePartialMatch;
private String reportingUserLike;
private String personLike;
private boolean excludeLimitedSyncRestrictions;
Expand Down Expand Up @@ -665,6 +668,31 @@ public ContactCriteria creationDateTo(Date creationDateTo) {
return this;
}

public Date getBirthdateFrom() {
return birthdateFrom;
}

public void setBirthdateFrom(Date birthdateFrom) {
this.birthdateFrom = birthdateFrom;
}

public Date getBirthdateTo() {
return birthdateTo;
}

public void setBirthdateTo(Date birthdateTo) {
this.birthdateTo = birthdateTo;
}

@IgnoreForUrl
public boolean isIncludePartialMatch() {
return includePartialMatch;
}

public void setIncludePartialMatch(boolean includePartialMatch) {
this.includePartialMatch = includePartialMatch;
}

public String getReportingUserLike() {
return reportingUserLike;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ public interface Captions {
String assignmentDate = "assignmentDate";
String assignToMe = "assignToMe";
String BAGExport = "BAGExport";
String birthdateFilter = "birthdateFilter";
String bulkActionCreatDocuments = "bulkActionCreatDocuments";
String bulkActions = "bulkActions";
String bulkCancelFollowUp = "bulkCancelFollowUp";
Expand Down Expand Up @@ -1993,6 +1994,7 @@ public interface Captions {
String importSkips = "importSkips";
String importValueSeparator = "importValueSeparator";
String inaccessibleValue = "inaccessibleValue";
String includePartialBirthdates = "includePartialBirthdates";
String info = "info";
String infrastructureImportAllowOverwrite = "infrastructureImportAllowOverwrite";
String lastName = "lastName";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ public interface Strings {
String headingImportSelfReports = "headingImportSelfReports";
String headingImportSubcontinents = "headingImportSubcontinents";
String headingImportTravelEntries = "headingImportTravelEntries";
String headingIncorrectDateRange = "headingIncorrectDateRange";
String headingInformationSource = "headingInformationSource";
String headingInfrastructureLocked = "headingInfrastructureLocked";
String headingIntroduction = "headingIntroduction";
Expand Down Expand Up @@ -921,6 +922,7 @@ public interface Strings {
String infoAutomaticDeletionTooltipYears = "infoAutomaticDeletionTooltipYears";
String infoBAGExport = "infoBAGExport";
String infoBasicExport = "infoBasicExport";
String infoBirthdateFilter = "infoBirthdateFilter";
String infoBulkProcess = "infoBulkProcess";
String infoBulkProcessCancelled = "infoBulkProcessCancelled";
String infoBulkProcessFinished = "infoBulkProcessFinished";
Expand Down Expand Up @@ -1419,6 +1421,7 @@ public interface Strings {
String messageImportSuccessful = "messageImportSuccessful";
String messageImportSuccessfulWithSkips = "messageImportSuccessfulWithSkips";
String messageIncompleteGpsCoordinates = "messageIncompleteGpsCoordinates";
String messageIncorrectDateRange = "messageIncorrectDateRange";
String messageInfrastructureLocked = "messageInfrastructureLocked";
String messageInvalidDatesLineListing = "messageInvalidDatesLineListing";
String messageLaboratoriesArchived = "messageLaboratoriesArchived";
Expand Down Expand Up @@ -1680,6 +1683,8 @@ public interface Strings {
String promptAllDistricts = "promptAllDistricts";
String promptAllRegions = "promptAllRegions";
String promptArea = "promptArea";
String promptBirthdateFrom = "promptBirthdateFrom";
String promptBirthdateTo = "promptBirthdateTo";
String promptCampaign = "promptCampaign";
String promptCampaignSearch = "promptCampaignSearch";
String promptCaseOrContactEventSearchField = "promptCaseOrContactEventSearchField";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.symeda.sormas.api.person;

import java.util.Date;
import java.util.Set;

import de.symeda.sormas.api.infrastructure.community.CommunityReferenceDto;
Expand Down Expand Up @@ -37,6 +38,9 @@ public class PersonCriteria extends BaseCriteria implements Cloneable {
private CommunityReferenceDto community;
private PersonAssociation personAssociation;
private Set<String> uuids;
private Date birthdateFrom;
private Date birthdateTo;
private boolean includePartialMatch;

public PersonCriteria() {

Expand Down Expand Up @@ -127,6 +131,31 @@ public PersonCriteria personAssociation(PersonAssociation personAssociation) {
return this;
}

public Date getBirthdateFrom() {
return birthdateFrom;
}

public void setBirthdateFrom(Date birthdateFrom) {
this.birthdateFrom = birthdateFrom;
}

public Date getBirthdateTo() {
return birthdateTo;
}

public void setBirthdateTo(Date birthdateTo) {
this.birthdateTo = birthdateTo;
}

@IgnoreForUrl
public boolean isIncludePartialMatch() {
return includePartialMatch;
}

public void setIncludePartialMatch(boolean includePartialMatch) {
this.includePartialMatch = includePartialMatch;
}

@IgnoreForUrl
public Set<String> getUuids() {
return uuids;
Expand Down
2 changes: 2 additions & 0 deletions sormas-api/src/main/resources/captions.properties
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ creationDate=Creation date
changeDate=Date of last change
notAvailableShort=NA
inaccessibleValue=Confidential
includePartialBirthdates = Include partial birthdates
numberOfCharacters=Number of characters: %d / %d
remove=Remove
notTestedYet=Not tested yet
Expand All @@ -71,6 +72,7 @@ adoptHomeAddressOfCasePersonIfRelationMatches=Adopt home address of the case per
casePersonAddress=Address of the case person
viewMessage=View message
primarySuffix=primary
birthdateFilter = Birthdate filter
# About
about=About
aboutAdditionalInfo=Additional Info
Expand Down
5 changes: 5 additions & 0 deletions sormas-api/src/main/resources/strings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ headingImportRegions= Import Regions
headingImportTravelEntries = Import Travel Entries
headingImportEnvironments = Import Environments
headingImportSelfReports = Import Self Reports
headingIncorrectDateRange = Incorrect date range
headingInformationSource = Source of Information
headingInfrastructureLocked = Infrastructure locked
headingIntroduction = Introduction
Expand Down Expand Up @@ -1115,6 +1116,7 @@ infoAefiSelectPrimarySuspectVaccine = The list below contains all vaccinations o
infoArchivedAefiEntries = Adverse event entries are automatically archived after %d days without changes to the data.
infoNoAefiInvestigations = No investigations have been created for this adverse event
infoHeadingAefiDashboardMap=Adverse events are shown using the GPS coordinate of the facility or person's home address.
infoBirthdateFilter = If checked the search will include also the persons that have incomplete birthdate and have only higher level match eg. only year or only year and month

# Messages
messageActionOutsideJurisdictionDeletionDenied = The action outside user's jurisdiction cannot be deleted
Expand Down Expand Up @@ -1314,6 +1316,7 @@ messageImportSuccessful = <b>Import successful!</b><br/>All rows have been impor
messageImportSuccessfulWithSkips = <b>Import successful!</b><br/>The import has been successful, but some of the rows were skipped. You can now close this window.
messageUploadSuccessful = Upload successful! You can now close this window.
messageIncompleteGpsCoordinates = GPS coordinates are incomplete
messageIncorrectDateRange = Date from is after date to
messageExternalMessagesAssigned = The assignee has been changed for all selected messages
messageLoginFailed = Please check your username and password and try again
messageMissingCases = Please generate some cases before generating contacts
Expand Down Expand Up @@ -1651,6 +1654,8 @@ promptActionChangeDateFrom = Date of action change from...
promptActionChangeDateTo = ... to
promptActionChangeEpiWeekFrom = Date of action change from epi week...
promptActionChangeEpiWeekTo = ... to epi week
promptBirthdateFrom = Birthdate from
promptBirthdateTo = Birthdate to
promptCampaignSearch = ID, name
promptCasesDateFrom = New cases from...
promptCasesEpiWeekFrom = New cases from epi week...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@
import de.symeda.sormas.backend.user.User;
import de.symeda.sormas.backend.user.UserRole;
import de.symeda.sormas.backend.user.UserService;
import de.symeda.sormas.backend.util.BirthdateRangeFilterPredicate;
import de.symeda.sormas.backend.util.ExternalDataUtil;
import de.symeda.sormas.backend.util.IterableHelper;
import de.symeda.sormas.backend.util.JurisdictionHelper;
Expand Down Expand Up @@ -912,6 +913,15 @@ public <T extends AbstractDomainObject> Predicate createCriteriaFilter(CaseCrite
filter = CriteriaBuilderHelper.and(cb, filter, likeFilters);
}
}

filter = BirthdateRangeFilterPredicate.createBirthdateRangeFilter(
caseCriteria.getBirthdateFrom(),
caseCriteria.getBirthdateTo(),
caseCriteria.isIncludePartialMatch(),
cb,
joins.getPerson(),
filter);

if (caseCriteria.getBirthdateYYYY() != null) {
filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(joins.getPerson().get(Person.BIRTHDATE_YYYY), caseCriteria.getBirthdateYYYY()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
import de.symeda.sormas.backend.user.User;
import de.symeda.sormas.backend.user.UserRole;
import de.symeda.sormas.backend.user.UserService;
import de.symeda.sormas.backend.util.BirthdateRangeFilterPredicate;
import de.symeda.sormas.backend.util.ExternalDataUtil;
import de.symeda.sormas.backend.util.IterableHelper;
import de.symeda.sormas.backend.util.JurisdictionHelper;
Expand Down Expand Up @@ -1419,6 +1420,15 @@ public Predicate buildCriteriaFilter(ContactCriteria contactCriteria, ContactQue
if (contactCriteria.getPerson() != null) {
filter = CriteriaBuilderHelper.and(cb, filter, cb.equal(joins.getPerson().get(Person.UUID), contactCriteria.getPerson().getUuid()));
}

filter = BirthdateRangeFilterPredicate.createBirthdateRangeFilter(
contactCriteria.getBirthdateFrom(),
contactCriteria.getBirthdateTo(),
contactCriteria.isIncludePartialMatch(),
cb,
joins.getPerson(),
filter);

if (contactCriteria.getBirthdateYYYY() != null) {
filter =
CriteriaBuilderHelper.and(cb, filter, cb.equal(joins.getPerson().get(Person.BIRTHDATE_YYYY), contactCriteria.getBirthdateYYYY()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
import de.symeda.sormas.backend.travelentry.services.TravelEntryService;
import de.symeda.sormas.backend.user.User;
import de.symeda.sormas.backend.user.UserService;
import de.symeda.sormas.backend.util.BirthdateRangeFilterPredicate;
import de.symeda.sormas.backend.util.ExternalDataUtil;
import de.symeda.sormas.backend.util.IterableHelper;
import de.symeda.sormas.backend.util.JurisdictionHelper;
Expand Down Expand Up @@ -386,6 +387,15 @@ public Predicate buildCriteriaFilter(PersonCriteria personCriteria, PersonQueryC
filter = andEquals(cb, personFrom, filter, personCriteria.getBirthdateYYYY(), Person.BIRTHDATE_YYYY);
filter = andEquals(cb, personFrom, filter, personCriteria.getBirthdateMM(), Person.BIRTHDATE_MM);
filter = andEquals(cb, personFrom, filter, personCriteria.getBirthdateDD(), Person.BIRTHDATE_DD);

filter = BirthdateRangeFilterPredicate.createBirthdateRangeFilter(
personCriteria.getBirthdateFrom(),
personCriteria.getBirthdateTo(),
personCriteria.isIncludePartialMatch(),
cb,
personFrom,
filter);

if (personCriteria.getNameAddressPhoneEmailLike() != null) {

String[] textFilters = personCriteria.getNameAddressPhoneEmailLike().split("\\s+");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package de.symeda.sormas.backend.util;

import java.util.Calendar;
import java.util.Date;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Predicate;

import de.symeda.sormas.backend.common.CriteriaBuilderHelper;
import de.symeda.sormas.backend.person.Person;

public class BirthdateRangeFilterPredicate {

public static Predicate createBirthdateRangeFilter(
Date birthdateFrom,
Date birthdateTo,
boolean includePartialMatch,
CriteriaBuilder cb,
From<?, Person> personFrom,
Predicate filter) {
if (birthdateFrom != null) {
Calendar calendarBirthdateFrom = Calendar.getInstance();
calendarBirthdateFrom.setTime(birthdateFrom);
int birthdateFromCriteriaYear = calendarBirthdateFrom.get(Calendar.YEAR);
int birthdateFromCriteriaMonth = calendarBirthdateFrom.get(Calendar.MONTH) + 1;
int birthdateFromCriteriaDay = calendarBirthdateFrom.get(Calendar.DAY_OF_MONTH);

Predicate yearPredicate = cb.greaterThan(personFrom.get(Person.BIRTHDATE_YYYY), birthdateFromCriteriaYear);

Predicate monthPredicate = cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateFromCriteriaYear);
monthPredicate = cb.and(monthPredicate, cb.greaterThan(personFrom.get(Person.BIRTHDATE_MM), birthdateFromCriteriaMonth));

Predicate dayPredicate = cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateFromCriteriaYear);
dayPredicate = cb.and(dayPredicate, cb.equal(personFrom.get(Person.BIRTHDATE_MM), birthdateFromCriteriaMonth));
dayPredicate = cb.and(dayPredicate, cb.greaterThanOrEqualTo(personFrom.get(Person.BIRTHDATE_DD), birthdateFromCriteriaDay));

if (includePartialMatch) {
Predicate sameYearPartialMatchPredicate = cb
.and(cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateFromCriteriaYear), cb.isNull(personFrom.get(Person.BIRTHDATE_MM)));
Predicate sameYearMonthPartialMatchPredicate = cb.and(
cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateFromCriteriaYear),
cb.equal(personFrom.get(Person.BIRTHDATE_MM), birthdateFromCriteriaMonth),
cb.isNull(personFrom.get(Person.BIRTHDATE_DD)));
filter = CriteriaBuilderHelper.and(
cb,
filter,
cb.or(yearPredicate, monthPredicate, dayPredicate, sameYearPartialMatchPredicate, sameYearMonthPartialMatchPredicate));
} else {
filter = CriteriaBuilderHelper.and(cb, filter, cb.or(yearPredicate, monthPredicate, dayPredicate));
}
}

if (birthdateTo != null) {
Calendar calendarBirthdateTo = Calendar.getInstance();
calendarBirthdateTo.setTime(birthdateTo);
int birthdateToCriteriaYear = calendarBirthdateTo.get(Calendar.YEAR);
int birthdateToCriteriaMonth = calendarBirthdateTo.get(Calendar.MONTH) + 1;
int birthdateToCriteriaDay = calendarBirthdateTo.get(Calendar.DAY_OF_MONTH);

Predicate yearPredicate = cb.lessThan(personFrom.get(Person.BIRTHDATE_YYYY), birthdateToCriteriaYear);

Predicate monthPredicate = cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateToCriteriaYear);
monthPredicate = cb.and(monthPredicate, cb.lessThan(personFrom.get(Person.BIRTHDATE_MM), birthdateToCriteriaMonth));

Predicate dayPredicate = cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateToCriteriaYear);
dayPredicate = cb.and(dayPredicate, cb.equal(personFrom.get(Person.BIRTHDATE_MM), birthdateToCriteriaMonth));
dayPredicate = cb.and(dayPredicate, cb.lessThanOrEqualTo(personFrom.get(Person.BIRTHDATE_DD), birthdateToCriteriaDay));

if (includePartialMatch) {
Predicate sameYearPartialMatchPredicate =
cb.and(cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateToCriteriaYear), cb.isNull(personFrom.get(Person.BIRTHDATE_MM)));
Predicate sameYearMonthPartialMatchPredicate = cb.and(
cb.equal(personFrom.get(Person.BIRTHDATE_YYYY), birthdateToCriteriaYear),
cb.equal(personFrom.get(Person.BIRTHDATE_MM), birthdateToCriteriaMonth),
cb.isNull(personFrom.get(Person.BIRTHDATE_DD)));
filter = CriteriaBuilderHelper.and(
cb,
filter,
cb.or(yearPredicate, monthPredicate, dayPredicate, sameYearPartialMatchPredicate, sameYearMonthPartialMatchPredicate));
} else {
filter = CriteriaBuilderHelper.and(cb, filter, cb.or(yearPredicate, monthPredicate, dayPredicate));
}
}
return filter;
}
}
Loading
Loading