diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateAnonymizeDataDto.java b/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateAnonymizeDataDto.java new file mode 100644 index 00000000000..7cee1c7240e --- /dev/null +++ b/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateAnonymizeDataDto.java @@ -0,0 +1,104 @@ +package de.symeda.sormas.api.report; + +import java.util.Objects; + +import de.symeda.sormas.api.EntityDto; + +@SuppressWarnings("serial") +public class AggregateAnonymizeDataDto extends EntityDto { + + /** + * + */ + private static final long serialVersionUID = -2839807582334824493L; + + public Long valueSum; + public String disease; + public String sex; + public String districtuuid; + public String agegroup; + public Long deaths; + public Long cases; + public AggregateAnonymizeDataDto(Long valueSum, String disease, String sex, String districtuuid, String agegroup, + Long deaths, Long cases) { + super(); + this.valueSum = valueSum; + this.disease = disease; + this.sex = sex; + this.districtuuid = districtuuid; + this.agegroup = agegroup; + this.deaths = deaths; + this.cases = cases; + } + public Long getValueSum() { + return valueSum; + } + public void setValueSum(Long valueSum) { + this.valueSum = valueSum; + } + public String getDisease() { + return disease; + } + public void setDisease(String disease) { + this.disease = disease; + } + public String getSex() { + return sex; + } + public void setSex(String sex) { + this.sex = sex; + } + public String getDistrictuuid() { + return districtuuid; + } + public void setDistrictuuid(String districtuuid) { + this.districtuuid = districtuuid; + } + public String getAgegroup() { + return agegroup; + } + public void setAgegroup(String agegroup) { + this.agegroup = agegroup; + } + public Long getDeaths() { + return deaths; + } + public void setDeaths(Long deaths) { + this.deaths = deaths; + } + public Long getCases() { + return cases; + } + public void setCases(Long cases) { + this.cases = cases; + } + public static long getSerialversionuid() { + return serialVersionUID; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Objects.hash(agegroup, cases, deaths, disease, districtuuid, sex, valueSum); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + AggregateAnonymizeDataDto other = (AggregateAnonymizeDataDto) obj; + return Objects.equals(agegroup, other.agegroup) && Objects.equals(cases, other.cases) + && Objects.equals(deaths, other.deaths) && Objects.equals(disease, other.disease) + && Objects.equals(districtuuid, other.districtuuid) && Objects.equals(sex, other.sex) + && Objects.equals(valueSum, other.valueSum); + } + + + +} \ No newline at end of file diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateReportFacade.java b/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateReportFacade.java index 1271be32558..ca04d6470f6 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateReportFacade.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/report/AggregateReportFacade.java @@ -32,4 +32,6 @@ public interface AggregateReportFacade { long countWithCriteria(AggregateReportCriteria criteria); void validate(AggregateReportDto dto); + + List getAggregateAnonymizeData(String toDate, String fromDate); } diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/report/AggregateReportFacadeEjb.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/report/AggregateReportFacadeEjb.java index d371c3219a7..04f06f27fca 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/report/AggregateReportFacadeEjb.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/report/AggregateReportFacadeEjb.java @@ -1,5 +1,6 @@ package de.symeda.sormas.backend.report; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -36,6 +37,7 @@ import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Validations; +import de.symeda.sormas.api.report.AggregateAnonymizeDataDto; import de.symeda.sormas.api.report.AggregateCaseCountDto; import de.symeda.sormas.api.report.AggregateReportCriteria; import de.symeda.sormas.api.report.AggregateReportDto; @@ -730,6 +732,47 @@ public long countWithCriteria(AggregateReportCriteria criteria) { return em.createQuery(cq).getSingleResult(); } + + + @Override + public List getAggregateAnonymizeData(String toDate, String fromDate) { + + String sqlBuild = "SELECT COUNT(c.id) AS case_count, c.disease, p.sex, d.uuid,\n" + + " CASE \n" + + " WHEN p.approximateagetype = 'DAYS' AND p.approximateage <= 28 THEN '0-28 Days'\n" + + " WHEN p.approximateagetype = 'DAYS' AND p.approximateage > 28 AND p.approximateage <= 365 THEN '29d - 11 months'\n" + + " WHEN p.approximateagetype = 'MONTHS' AND p.approximateage <= 11 THEN '29d - 11 months'\n" + + " WHEN p.approximateagetype = 'DAYS' AND p.approximateage > 365 AND p.approximateage <= 1825 THEN '12-59 months'\n" + + " WHEN p.approximateagetype = 'MONTHS' AND p.approximateage >= 12 AND p.approximateage <= 59 THEN '12-59 months'\n" + + " WHEN p.approximateagetype = 'MONTHS' AND p.approximateage >= 1 AND p.approximateage < 5 THEN '12-59 months'\n" + + " WHEN p.approximateagetype = 'YEARS' AND p.approximateage >= 5 AND p.approximateage < 10 THEN '5-9 years'\n" + + " WHEN p.approximateagetype = 'YEARS' AND p.approximateage >= 10 AND p.approximateage < 20 THEN '10-19 years'\n" + + " WHEN p.approximateagetype = 'YEARS' AND p.approximateage >= 20 AND p.approximateage <= 40 THEN '20-40 years'\n" + + " WHEN p.approximateagetype = 'YEARS' AND p.approximateage > 40 THEN '>40 years'\n" + + " ELSE 'Other'\n" + + " END AS age_group,\n" + + " COUNT(CASE WHEN c.outcome = 'DECEASED' THEN 1 END) AS DEATHS,\n" + + " COUNT(CASE WHEN c.caseclassification = 'CONFIRMED' THEN 1 END) AS cases \n" + + " FROM cases c \n" + + " LEFT OUTER JOIN person p ON c.person_id = p.id\n" + + " LEFT OUTER JOIN district d on c.responsibledistrict_id = d.id \n" + + " WHERE c.reportdate BETWEEN '" + fromDate + "' AND '" + toDate + "' \n" + + " GROUP BY c.disease, p.sex, age_group, d.uuid;"; + + @SuppressWarnings("unchecked") + List resultList = em.createNativeQuery(sqlBuild).getResultList(); + + List resultData = new ArrayList<>(); + + resultData.addAll(resultList.stream() + .map((result) -> new AggregateAnonymizeDataDto(((BigInteger) result[0]).longValue(), + (String) result[1].toString(), (String) result[2].toString(), (String) result[3].toString(), + (String) result[4].toString(), ((BigInteger) result[5]).longValue(), + ((BigInteger) result[6]).longValue())) + .collect(Collectors.toList())); + + return resultData; + } @LocalBean @Stateless diff --git a/sormas-rest/src/main/java/de/symeda/sormas/rest/resources/AggregateReportResource.java b/sormas-rest/src/main/java/de/symeda/sormas/rest/resources/AggregateReportResource.java index 76047da955a..04b41f80b3e 100644 --- a/sormas-rest/src/main/java/de/symeda/sormas/rest/resources/AggregateReportResource.java +++ b/sormas-rest/src/main/java/de/symeda/sormas/rest/resources/AggregateReportResource.java @@ -15,9 +15,12 @@ package de.symeda.sormas.rest.resources; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.function.UnaryOperator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -29,6 +32,7 @@ import javax.ws.rs.core.Response; import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.report.AggregateAnonymizeDataDto; import de.symeda.sormas.api.report.AggregateCaseCountDto; import de.symeda.sormas.api.report.AggregateReportCriteria; import de.symeda.sormas.api.report.AggregateReportDto; @@ -39,6 +43,11 @@ @Consumes(MediaType.APPLICATION_JSON + "; charset=UTF-8") public class AggregateReportResource extends EntityDtoResource { + private static final String DATE_PATTERN = "^\\d{4}\\-(0[1-9]|1[012])\\-(0[1-9]|[12][0-9]|3[01])$"; + + // Compile the pattern + private static final Pattern pattern = Pattern.compile(DATE_PATTERN); + @GET @Path("/all/{since}") public List getAllAggregateReports(@PathParam("since") long since) { @@ -72,4 +81,25 @@ public UnaryOperator getSave() { public Response postEntityDtos(List aggregateReportDtos) { return super.postEntityDtos(aggregateReportDtos); } + + @GET + @Path("/anonymize/{fromDate}/{toDate}") + public List getAggregateAnonymizeData(@PathParam("toDate") String toDate, + @PathParam("fromDate") String fromDate) { + + if (toDate != null && !toDate.isEmpty() && fromDate != null && !fromDate.isEmpty()) { + if (isValidDate(toDate) && isValidDate(fromDate)) { + List result = FacadeProvider.getAggregateReportFacade() + .getAggregateAnonymizeData(toDate, fromDate); + return result; + } + } + List empty = new ArrayList<>(); + return empty; + } + + public static boolean isValidDate(String date) { + Matcher matcher = pattern.matcher(date); + return matcher.matches(); + } }