Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit 8b52d0d

Browse files
Add symptoms onset and sample latest collection date columns in case directory SORMAS-Foundation#3272 (SORMAS-Foundation#3576)
* Add latest collection date column in case directory detailed view SORMAS-Foundation#3272 * Add symptoms onset date column in case directory detailed view SORMAS-Foundation#3272 * Hide sampleCount when there's no latestSampleDateTime in latest collection date column SORMAS-Foundation#3272 * Use ID instead of UUID to get latest sample date SORMAS-Foundation#3272 * Use Symptoms.onsetDate instead of CaseData.symptomsOnsetDate SORMAS-Foundation#3272 * Rename CaseIndexDetailedDto's symptomsOnsetDate to symptomOnsetDate SORMAS-Foundation#3272 * Set latestSampleDateTimeAndSampleCount column caption explicitly SORMAS-Foundation#3272
1 parent a6ee61a commit 8b52d0d

7 files changed

Lines changed: 102 additions & 4 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/caze/CaseIndexDetailedDto.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ public class CaseIndexDetailedDto extends CaseIndexDto {
3030
public static final String LATEST_EVENT_ID = "latestEventId";
3131
public static final String LATEST_EVENT_STATUS = "latestEventStatus";
3232
public static final String LATEST_EVENT_TITLE = "latestEventTitle";
33+
public static final String LATEST_SAMPLE_DATE_TIME = "latestSampleDateTime";
34+
public static final String SAMPLE_COUNT = "sampleCount";
35+
public static final String SYMPTOM_ONSET_DATE = "symptomOnsetDate";
3336

3437
@PersonalData
3538
@SensitiveData
@@ -53,6 +56,9 @@ public class CaseIndexDetailedDto extends CaseIndexDto {
5356
private String latestEventId;
5457
private String latestEventTitle;
5558
private EventStatus latestEventStatus;
59+
private Date latestSampleDateTime;
60+
private Long sampleCount;
61+
private Date symptomOnsetDate;
5662

5763
private UserReferenceDto reportingUser;
5864

@@ -66,7 +72,8 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte
6672
Integer age, ApproximateAgeType ageType, Integer birthdateDD, Integer birthdateMM, Integer birthdateYYYY, Sex sex,
6773
Date quarantineTo, Float completeness, FollowUpStatus followUpStatus, Date followUpUntil, Date changeDate, Long facilityId,
6874
String city, String street, String houseNumber, String additionalInformation, String postalCode, String phone,
69-
String reportingUserFirstName, String reportingUserLastName, int visitCount, long eventCount) {
75+
String reportingUserFirstName, String reportingUserLastName, Date symptomOnsetDate,
76+
int visitCount, long eventCount, Date latestSampleDateTime, long sampleCount) {
7077

7178
super(id, uuid, epidNumber, externalID, personFirstName, personLastName, disease, diseaseDetails, caseClassification, investigationStatus,
7279
presentCondition, reportDate, reportingUserUuid, creationDate, regionUuid, districtUuid, districtName, communityUuid,
@@ -83,6 +90,9 @@ public CaseIndexDetailedDto(long id, String uuid, String epidNumber, String exte
8390
this.phone = phone;
8491
this.reportingUser = new UserReferenceDto(reportingUserUuid, reportingUserFirstName, reportingUserLastName, null);
8592
this.eventCount = eventCount;
93+
this.latestSampleDateTime = latestSampleDateTime;
94+
this.sampleCount = sampleCount;
95+
this.symptomOnsetDate = symptomOnsetDate;
8696
}
8797

8898
public String getCity() {
@@ -144,4 +154,16 @@ public EventStatus getLatestEventStatus() {
144154
public void setLatestEventStatus(EventStatus latestEventStatus) {
145155
this.latestEventStatus = latestEventStatus;
146156
}
157+
158+
public Date getLatestSampleDateTime() {
159+
return latestSampleDateTime;
160+
}
161+
162+
public Long getSampleCount() {
163+
return sampleCount;
164+
}
165+
166+
public Date getSymptomOnsetDate() {
167+
return symptomOnsetDate;
168+
}
147169
}

sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ public interface Captions {
229229
String CaseData_latestEventId = "CaseData.latestEventId";
230230
String CaseData_latestEventStatus = "CaseData.latestEventStatus";
231231
String CaseData_latestEventTitle = "CaseData.latestEventTitle";
232+
String CaseData_latestSampleDateTime = "CaseData.latestSampleDateTime";
232233
String CaseData_maternalHistory = "CaseData.maternalHistory";
233234
String CaseData_nationalLevelDate = "CaseData.nationalLevelDate";
234235
String CaseData_noneHealthFacilityDetails = "CaseData.noneHealthFacilityDetails";

sormas-api/src/main/resources/captions.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ CaseData.eventCount=Number of events
382382
CaseData.latestEventId=Latest event ID
383383
CaseData.latestEventStatus=Latest event status
384384
CaseData.latestEventTitle=Latest event title
385+
CaseData.latestSampleDateTime=Latest collection date
385386
CaseData.caseIdIsm=Case-ID ISM
386387
CaseData.covidTestReason=Reason for COVID-19-Test
387388
CaseData.covidTestReasonDetails=Other reason

sormas-backend/src/main/java/de/symeda/sormas/backend/caze/CaseListCriteriaBuilder.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.symeda.sormas.backend.caze;
22

3+
import java.sql.Timestamp;
34
import java.util.ArrayList;
45
import java.util.Arrays;
56
import java.util.Collections;
@@ -19,6 +20,7 @@
1920
import javax.persistence.criteria.Join;
2021
import javax.persistence.criteria.JoinType;
2122
import javax.persistence.criteria.Order;
23+
import javax.persistence.criteria.Path;
2224
import javax.persistence.criteria.Predicate;
2325
import javax.persistence.criteria.Root;
2426
import javax.persistence.criteria.Selection;
@@ -39,6 +41,8 @@
3941
import de.symeda.sormas.backend.region.Community;
4042
import de.symeda.sormas.backend.region.District;
4143
import de.symeda.sormas.backend.region.Region;
44+
import de.symeda.sormas.backend.sample.Sample;
45+
import de.symeda.sormas.backend.symptoms.Symptoms;
4246
import de.symeda.sormas.backend.user.User;
4347
import de.symeda.sormas.backend.util.ModelConstants;
4448
import de.symeda.sormas.utils.CaseJoins;
@@ -73,7 +77,7 @@ private <T> CriteriaQuery<T> buildIndexCriteria(
7377
CaseCriteria caseCriteria,
7478
OrderExpressionProvider orderExpressionProvider,
7579
List<SortProperty> sortProperties,
76-
boolean withEventInfo) {
80+
boolean detailed) {
7781

7882
CriteriaBuilder cb = em.getCriteriaBuilder();
7983
CriteriaQuery<T> cq = cb.createQuery(type);
@@ -88,7 +92,7 @@ private <T> CriteriaQuery<T> buildIndexCriteria(
8892
visitCountSq.select(cb.size(visitCountRoot.get(Case.VISITS)));
8993
selectionList.add(visitCountSq);
9094

91-
if (withEventInfo) {
95+
if (detailed) {
9296
// Events count subquery
9397
Subquery<Long> eventCountSq = cq.subquery(Long.class);
9498
Root<EventParticipant> eventCountRoot = eventCountSq.from(EventParticipant.class);
@@ -102,6 +106,21 @@ private <T> CriteriaQuery<T> buildIndexCriteria(
102106
cb.isFalse(eventCountRoot.get(EventParticipant.DELETED))));
103107
eventCountSq.select(cb.countDistinct(event.get(Event.ID)));
104108
selectionList.add(eventCountSq);
109+
110+
// Latest sampleDateTime subquery
111+
Subquery<Timestamp> latestSampleDateTimeSq = cq.subquery(Timestamp.class);
112+
Root<Sample> sample = latestSampleDateTimeSq.from(Sample.class);
113+
Path<Timestamp> sampleDateTime = sample.get(Sample.SAMPLE_DATE_TIME);
114+
latestSampleDateTimeSq.where(cb.equal(sample.get(Sample.ID), joins.getSamples().get(Sample.ID)), cb.isFalse(sample.get(Sample.DELETED)));
115+
latestSampleDateTimeSq.select(cb.greatest(sampleDateTime));
116+
selectionList.add(latestSampleDateTimeSq);
117+
118+
// Samples count subquery
119+
Subquery<Long> sampleCountSq = cq.subquery(Long.class);
120+
Root<Sample> sampleRoot = sampleCountSq.from(Sample.class);
121+
sampleCountSq.where(cb.equal(sampleRoot.get(Sample.ID), joins.getSamples().get(Sample.ID)), cb.isFalse(sampleRoot.get(Sample.DELETED)));
122+
sampleCountSq.select(cb.countDistinct(sampleRoot.get(Sample.ID)));
123+
selectionList.add(sampleCountSq);
105124
}
106125
cq.multiselect(selectionList);
107126
cq.distinct(true);
@@ -240,7 +259,8 @@ private List<Selection<?>> getCaseIndexDetailedSelections(Root<Case> caze, CaseJ
240259
joins.getAddress().get(Location.POSTAL_CODE),
241260
joins.getPerson().get(Person.PHONE),
242261
joins.getReportingUser().get(User.FIRST_NAME),
243-
joins.getReportingUser().get(User.LAST_NAME)));
262+
joins.getReportingUser().get(User.LAST_NAME),
263+
joins.getSymptoms().get(Symptoms.ONSET_DATE)));
244264

245265
return selections;
246266
}
@@ -258,6 +278,8 @@ private List<Expression<?>> getIndexDetailOrders(SortProperty sortProperty, Root
258278
return Collections.singletonList(joins.getPerson().get(sortProperty.propertyName));
259279
case CaseIndexDetailedDto.REPORTING_USER:
260280
return Arrays.asList(joins.getReportingUser().get(User.FIRST_NAME), joins.getReportingUser().get(User.LAST_NAME));
281+
case CaseIndexDetailedDto.SYMPTOM_ONSET_DATE:
282+
return Collections.singletonList(joins.getSymptoms().get(Symptoms.ONSET_DATE));
261283
default:
262284
return getIndexOrders(sortProperty, caze, joins);
263285
}

sormas-backend/src/main/java/de/symeda/sormas/utils/CaseJoins.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import de.symeda.sormas.backend.region.Community;
3636
import de.symeda.sormas.backend.region.District;
3737
import de.symeda.sormas.backend.region.Region;
38+
import de.symeda.sormas.backend.sample.Sample;
3839
import de.symeda.sormas.backend.symptoms.Symptoms;
3940
import de.symeda.sormas.backend.user.User;
4041
import de.symeda.sormas.backend.util.AbstractDomainObjectJoins;
@@ -63,6 +64,7 @@ public class CaseJoins<T extends AbstractDomainObject> extends AbstractDomainObj
6364
private Join<ClinicalCourse, HealthConditions> healthConditions;
6465
private Join<Case, EventParticipant> eventParticipants;
6566
private Join<Person, List<Location>> personAddresses;
67+
private Join<Case, Sample> samples;
6668

6769
public CaseJoins(From<T, Case> caze) {
6870
super(caze);
@@ -235,4 +237,12 @@ public Join<Person, List<Location>> getPersonAddresses() {
235237
private void setPersonAddresses(Join<Person, List<Location>> personAddresses) {
236238
this.personAddresses = personAddresses;
237239
}
240+
241+
public Join<Case, Sample> getSamples() {
242+
return getOrCreate(samples, Case.SAMPLES, JoinType.LEFT, this::setSamples);
243+
}
244+
245+
private void setSamples(Join<Case, Sample> samples) {
246+
this.samples = samples;
247+
}
238248
}

sormas-ui/src/main/java/de/symeda/sormas/ui/caze/AbstractCaseGrid.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ protected Stream<String> getGridColumns() {
187187
CaseIndexDto.INVESTIGATION_STATUS),
188188
getPersonColumns(),
189189
getEventColumns(),
190+
getSymptomsColumns(),
191+
getSampleColumns(),
190192
Stream.of(
191193
CaseIndexDto.DISTRICT_NAME,
192194
CaseIndexDto.HEALTH_FACILITY_NAME,
@@ -206,6 +208,14 @@ protected Stream<String> getEventColumns() {
206208
return Stream.empty();
207209
}
208210

211+
protected Stream<String> getSymptomsColumns() {
212+
return Stream.empty();
213+
}
214+
215+
protected Stream<String> getSampleColumns() {
216+
return Stream.empty();
217+
}
218+
209219
public void reload() {
210220

211221
if (getSelectionModel().isUserSelectionAllowed()) {

sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseGridDetailed.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package de.symeda.sormas.ui.caze;
22

3+
import java.util.Date;
34
import java.util.List;
45
import java.util.stream.Stream;
56

7+
import com.vaadin.ui.renderers.DateRenderer;
68
import com.vaadin.ui.renderers.TextRenderer;
79

810
import de.symeda.sormas.api.FacadeProvider;
@@ -11,15 +13,19 @@
1113
import de.symeda.sormas.api.caze.CaseIndexDetailedDto;
1214
import de.symeda.sormas.api.i18n.I18nProperties;
1315
import de.symeda.sormas.api.person.PersonHelper;
16+
import de.symeda.sormas.api.symptoms.SymptomsDto;
1417
import de.symeda.sormas.api.utils.SortProperty;
1518
import de.symeda.sormas.ui.ControllerProvider;
19+
import de.symeda.sormas.ui.utils.DateFormatHelper;
1620
import de.symeda.sormas.ui.utils.ShowDetailsListener;
1721
import de.symeda.sormas.ui.utils.UuidRenderer;
1822

1923
public class CaseGridDetailed extends AbstractCaseGrid<CaseIndexDetailedDto> {
2024

2125
private static final long serialVersionUID = 3734206041728541742L;
2226

27+
private static final String LATEST_SAMPLE_DATE_TIME_AND_SAMPLE_COUNT = "latestSampleDateTimeAndSampleCount";
28+
2329
public CaseGridDetailed(CaseCriteria criteria) {
2430
super(CaseIndexDetailedDto.class, criteria);
2531
}
@@ -58,10 +64,31 @@ protected Stream<String> getPersonColumns() {
5864
CaseIndexDetailedDto.PHONE));
5965
}
6066

67+
@Override
68+
protected Stream<String> getSymptomsColumns() {
69+
return Stream.concat(super.getSampleColumns(), Stream.of(CaseIndexDetailedDto.SYMPTOM_ONSET_DATE));
70+
}
71+
72+
@Override
73+
protected Stream<String> getSampleColumns() {
74+
return Stream.concat(super.getSampleColumns(), Stream.of(LATEST_SAMPLE_DATE_TIME_AND_SAMPLE_COUNT));
75+
}
76+
6177
@SuppressWarnings("unchecked")
6278
@Override
6379
protected void initColumns() {
6480

81+
addColumn(caze -> {
82+
if (caze.getLatestSampleDateTime() != null) {
83+
return DateFormatHelper.formatLocalDateTime(caze.getLatestSampleDateTime()) + " [" + caze.getSampleCount() + "]";
84+
} else {
85+
return null;
86+
}
87+
}).setCaption(I18nProperties.getPrefixCaption(CaseIndexDetailedDto.I18N_PREFIX, CaseIndexDetailedDto.LATEST_SAMPLE_DATE_TIME))
88+
.setId(LATEST_SAMPLE_DATE_TIME_AND_SAMPLE_COUNT)
89+
.setSortable(false)
90+
.setWidth(150);
91+
6592
super.initColumns();
6693

6794
getColumn(CaseIndexDetailedDto.SEX).setWidth(80);
@@ -94,5 +121,10 @@ protected void initColumns() {
94121
value.getBirthdateYYYY(),
95122
I18nProperties.getUserLanguage()),
96123
new TextRenderer());
124+
125+
((Column<CaseIndexDetailedDto, Date>) getColumn(CaseIndexDetailedDto.SYMPTOM_ONSET_DATE))
126+
.setRenderer(new DateRenderer(DateFormatHelper.getDateFormat()))
127+
.setCaption(I18nProperties.getPrefixCaption(SymptomsDto.I18N_PREFIX, SymptomsDto.ONSET_DATE))
128+
.setWidth(80);
97129
}
98130
}

0 commit comments

Comments
 (0)