Skip to content

Commit bda95f2

Browse files
Merge pull request #670 from nategbrown9/add-assessment-phase
DHP-1085 Add phase enum field to Assessment
2 parents c548217 + 5454fdf commit bda95f2

File tree

14 files changed

+337
-12
lines changed

14 files changed

+337
-12
lines changed

src/main/java/org/sagebionetworks/bridge/models/assessments/Assessment.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public static Assessment create(HibernateAssessment assessment) {
4747
dto.setMinAge(assessment.getMinAge());
4848
dto.setMaxAge(assessment.getMaxAge());
4949
dto.setAdditionalMetadata(assessment.getAdditionalMetadata());
50+
dto.setPhase(assessment.getPhase());
5051
return dto;
5152
}
5253

@@ -81,6 +82,7 @@ public static Assessment copy(Assessment assessment) {
8182
private Integer minAge;
8283
private Integer maxAge;
8384
private JsonNode additionalMetadata;
85+
private AssessmentPhase phase;
8486

8587
public String getAppId() {
8688
return appId;
@@ -262,4 +264,12 @@ public JsonNode getAdditionalMetadata() {
262264
public void setAdditionalMetadata(JsonNode additionalMetadata) {
263265
this.additionalMetadata = additionalMetadata;
264266
}
267+
268+
public AssessmentPhase getPhase() {
269+
return phase;
270+
}
271+
272+
public void setPhase(AssessmentPhase phase) {
273+
this.phase = phase;
274+
}
265275
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.sagebionetworks.bridge.models.assessments;
2+
3+
import com.google.common.collect.ImmutableMap;
4+
import com.google.common.collect.ImmutableSet;
5+
6+
import java.util.Map;
7+
import java.util.Set;
8+
9+
public enum AssessmentPhase {
10+
11+
/**
12+
* Assessment is still actively being developed. The AssessmentConfig associated with it can be edited.
13+
*/
14+
DRAFT,
15+
16+
/**
17+
* Assessment is ready to be included in a schedule for review and testing. The AssessmentConfig associated with it
18+
* cannot be edited. To update the AssessmentConfig the Assessment must be moved back into DRAFT phase.
19+
*/
20+
REVIEW,
21+
22+
/**
23+
* Assessment is now being used in a live study. The AssessmentConfig associated with it cannot be edited and the
24+
* phase can no longer be changed.
25+
*/
26+
PUBLISHED;
27+
28+
public String label() {
29+
return "“" + this.name().toLowerCase() + "”";
30+
}
31+
32+
public static final Map<AssessmentPhase, Set<AssessmentPhase>> ALLOWED_PHASE_TRANSITIONS = new ImmutableMap.Builder<AssessmentPhase, Set<AssessmentPhase>>()
33+
.put(DRAFT, ImmutableSet.of(REVIEW, PUBLISHED))
34+
.put(REVIEW, ImmutableSet.of(DRAFT, PUBLISHED))
35+
.put(PUBLISHED, ImmutableSet.of()).build();
36+
37+
public static final Set<AssessmentPhase> CAN_EDIT_ASSESSMENT_CONFIG = ImmutableSet.of(DRAFT);
38+
39+
}

src/main/java/org/sagebionetworks/bridge/models/assessments/HibernateAssessment.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import javax.persistence.Convert;
1717
import javax.persistence.Embedded;
1818
import javax.persistence.Entity;
19+
import javax.persistence.EnumType;
20+
import javax.persistence.Enumerated;
1921
import javax.persistence.Id;
2022
import javax.persistence.JoinColumn;
2123
import javax.persistence.JoinTable;
@@ -78,6 +80,7 @@ public static HibernateAssessment create(String appId, Assessment dto) {
7880
assessment.setMinAge(dto.getMinAge());
7981
assessment.setMaxAge(dto.getMaxAge());
8082
assessment.setAdditionalMetadata(dto.getAdditionalMetadata());
83+
assessment.setPhase(dto.getPhase());
8184
return assessment;
8285
}
8386

@@ -147,6 +150,8 @@ public static HibernateAssessment create(String appId, Assessment dto) {
147150
private Integer maxAge;
148151
@Convert(converter = JsonNodeAttributeConverter.class)
149152
private JsonNode additionalMetadata;
153+
@Enumerated(EnumType.STRING)
154+
private AssessmentPhase phase;
150155

151156
public String getGuid() {
152157
return guid;
@@ -313,5 +318,11 @@ public JsonNode getAdditionalMetadata() {
313318
public void setAdditionalMetadata(JsonNode additionalMetadata) {
314319
this.additionalMetadata = additionalMetadata;
315320
}
321+
public AssessmentPhase getPhase() {
322+
return phase;
323+
}
324+
public void setPhase(AssessmentPhase phase) {
325+
this.phase = phase;
326+
}
316327
}
317328

src/main/java/org/sagebionetworks/bridge/services/AssessmentConfigService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.fasterxml.jackson.databind.JsonNode;
1313

1414
import org.joda.time.DateTime;
15+
import org.sagebionetworks.bridge.models.assessments.AssessmentPhase;
1516
import org.springframework.beans.factory.annotation.Autowired;
1617
import org.springframework.stereotype.Component;
1718

@@ -86,6 +87,10 @@ public AssessmentConfig updateAssessmentConfig(String appId, String ownerId, Str
8687

8788
Assessment assessment = assessmentService.getAssessmentByGuid(appId, ownerId, guid);
8889
CAN_EDIT_ASSESSMENTS.checkAndThrow(ORG_ID, assessment.getOwnerId());
90+
if (!AssessmentPhase.CAN_EDIT_ASSESSMENT_CONFIG.contains(assessment.getPhase())) {
91+
throw new BadRequestException("Assessment config cannot be changed during assessment phase "
92+
+ assessment.getPhase().label() + ".");
93+
}
8994

9095
AssessmentConfig existing = dao.getAssessmentConfig(guid)
9196
.orElseThrow(() -> new EntityNotFoundException(AssessmentConfig.class));

src/main/java/org/sagebionetworks/bridge/services/AssessmentService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import static org.sagebionetworks.bridge.models.ResourceList.OFFSET_BY;
2828
import static org.sagebionetworks.bridge.models.ResourceList.PAGE_SIZE;
2929
import static org.sagebionetworks.bridge.models.ResourceList.TAGS;
30+
import static org.sagebionetworks.bridge.models.assessments.AssessmentPhase.ALLOWED_PHASE_TRANSITIONS;
31+
import static org.sagebionetworks.bridge.models.assessments.AssessmentPhase.PUBLISHED;
3032
import static org.sagebionetworks.bridge.util.BridgeCollectors.toImmutableSet;
3133

3234
import java.util.HashMap;
@@ -40,6 +42,8 @@
4042

4143
import org.apache.commons.lang3.StringUtils;
4244
import org.joda.time.DateTime;
45+
import org.sagebionetworks.bridge.models.assessments.AssessmentPhase;
46+
import org.sagebionetworks.bridge.models.studies.StudyPhase;
4347
import org.springframework.beans.factory.annotation.Autowired;
4448
import org.springframework.stereotype.Component;
4549

@@ -198,6 +202,11 @@ private Assessment updateAssessmentInternal(String appId, Assessment assessment,
198202
}
199203
AssessmentValidator validator = new AssessmentValidator(appId, organizationService);
200204
Validate.entityThrowingException(validator, assessment);
205+
Set<AssessmentPhase> allowedTargetPhases = ALLOWED_PHASE_TRANSITIONS.get(existing.getPhase());
206+
if (assessment.getPhase() != existing.getPhase() && !allowedTargetPhases.contains(assessment.getPhase())) {
207+
throw new BadRequestException("Assessment cannot transition from " +
208+
existing.getPhase().label() + " to " + assessment.getPhase().label() + ".");
209+
}
201210

202211
return dao.updateAssessment(appId, assessment);
203212
}
@@ -316,6 +325,7 @@ public Assessment publishAssessment(String appId, String ownerId, String newIden
316325
assessmentToPublish.setOriginGuid(null);
317326
assessmentToPublish.setOwnerId(sharedOwnerId);
318327
assessmentToPublish.setVersion(0L);
328+
assessmentToPublish.setPhase(PUBLISHED);
319329

320330
original.setOriginGuid(assessmentToPublish.getGuid());
321331

src/main/java/org/sagebionetworks/bridge/services/StudyService.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.util.HashSet;
2929
import java.util.List;
30+
import java.util.Optional;
3031
import java.util.Set;
3132
import java.util.function.Consumer;
3233
import java.util.stream.Collectors;
@@ -44,7 +45,11 @@
4445
import org.sagebionetworks.bridge.models.PagedResourceList;
4546
import org.sagebionetworks.bridge.models.VersionHolder;
4647
import org.sagebionetworks.bridge.models.activities.StudyActivityEventIdsMap;
48+
import org.sagebionetworks.bridge.models.assessments.Assessment;
49+
import org.sagebionetworks.bridge.models.assessments.AssessmentPhase;
50+
import org.sagebionetworks.bridge.models.schedules2.AssessmentReference;
4751
import org.sagebionetworks.bridge.models.schedules2.Schedule2;
52+
import org.sagebionetworks.bridge.models.schedules2.Session;
4853
import org.sagebionetworks.bridge.models.studies.Study;
4954
import org.sagebionetworks.bridge.models.studies.StudyPhase;
5055
import org.sagebionetworks.bridge.validators.StudyValidator;
@@ -71,6 +76,8 @@ public class StudyService {
7176
private DemographicService demographicService;
7277
@Autowired
7378
private AlertService alertService;
79+
@Autowired
80+
private AssessmentService assessmentService;
7481

7582
protected String getDefaultTimeZoneId() {
7683
return DateTimeZone.getDefault().getID();
@@ -456,8 +463,37 @@ private Study phaseTransition(String appId, String studyId, StudyPhase targetPha
456463
alertService.deleteAlertsForStudy(appId, studyId);
457464
}
458465

466+
// mark assessments as published when study moves into recruitment
467+
if (targetPhase == RECRUITMENT && study.getScheduleGuid() != null) {
468+
Set<AssessmentReference> assessmentRefs = getAssessmentGuidsFromSchedule(appId, studyId);
469+
for (AssessmentReference assessmentRef : assessmentRefs) {
470+
//Only update local assessments
471+
if (appId.equals(assessmentRef.getAppId())) {
472+
Assessment assessment = assessmentService.getAssessmentByGuid(assessmentRef.getAppId(), null, assessmentRef.getGuid());
473+
if (assessment.getPhase() != AssessmentPhase.PUBLISHED) {
474+
assessment.setPhase(AssessmentPhase.PUBLISHED);
475+
assessmentService.updateAssessment(appId, null, assessment);
476+
}
477+
}
478+
}
479+
}
480+
459481
return study;
460482
}
483+
484+
/**
485+
* Get a Set of all Assessment GUIDs used by a study's schedule.
486+
*/
487+
protected Set<AssessmentReference> getAssessmentGuidsFromSchedule(String appId, String studyId) {
488+
Set<AssessmentReference> assessmentRefs = new HashSet<>();
489+
Schedule2 schedule = scheduleService.getScheduleForStudy(appId, studyId).orElse(null);
490+
if (schedule != null) {
491+
for (Session session : schedule.getSessions()) {
492+
assessmentRefs.addAll(session.getAssessments());
493+
}
494+
}
495+
return assessmentRefs;
496+
}
461497

462498
/**
463499
* Retrieves the custom event IDs from a schedule. The returned event IDs will

src/main/java/org/sagebionetworks/bridge/validators/AssessmentValidator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import static org.sagebionetworks.bridge.validators.Validate.BRIDGE_EVENT_ID_PATTERN;
77
import static org.sagebionetworks.bridge.validators.Validate.CANNOT_BE_BLANK;
88
import static org.sagebionetworks.bridge.validators.Validate.CANNOT_BE_NEGATIVE;
9+
import static org.sagebionetworks.bridge.validators.Validate.CANNOT_BE_NULL;
910
import static org.sagebionetworks.bridge.validators.Validate.INVALID_TYPE;
1011
import static org.sagebionetworks.bridge.validators.ValidatorUtils.TEXT_SIZE;
1112
import static org.sagebionetworks.bridge.validators.ValidatorUtils.validateColorScheme;
@@ -50,6 +51,9 @@ public void validate(Object target, Errors errors) {
5051
errors.rejectValue("title", CANNOT_BE_BLANK);
5152
}
5253
validateStringLength(errors, 255, assessment.getTitle(), "title");
54+
if (assessment.getPhase() == null) {
55+
errors.rejectValue("phase", CANNOT_BE_NULL);
56+
}
5357
String osName = assessment.getOsName();
5458
if (isBlank(assessment.getOsName())) {
5559
errors.rejectValue("osName", CANNOT_BE_BLANK);

src/main/resources/db/changelog/changelog.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,3 +1098,7 @@ ALTER TABLE `AdherenceRecords`
10981098
ADD COLUMN `postProcessingAttributes` text COLLATE utf8_unicode_ci DEFAULT NULL,
10991099
ADD COLUMN `postProcessingCompletedOn` bigint(20) unsigned DEFAULT NULL,
11001100
ADD COLUMN `postProcessingStatus` varchar(255) DEFAULT NULL;
1101+
1102+
-- changeset bridge:81
1103+
ALTER TABLE `Assessments`
1104+
ADD COLUMN `phase` enum('DRAFT', 'REVIEW', 'PUBLISHED') DEFAULT 'DRAFT';

src/test/java/org/sagebionetworks/bridge/models/assessments/AssessmentTest.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void createFactoryMethod() {
8080
assessment.setMinAge(MIN_AGE);
8181
assessment.setMaxAge(MAX_AGE);
8282
assessment.setAdditionalMetadata(ADDITIONAL_METADATA);
83-
83+
assessment.setPhase(AssessmentPhase.DRAFT);
8484
Assessment dto = Assessment.create(assessment);
8585
assertAssessment(dto);
8686
}
@@ -101,7 +101,7 @@ public void serializeRountrip() throws Exception {
101101
Assessment dto = createAssessment();
102102

103103
JsonNode node = BridgeObjectMapper.get().valueToTree(dto);
104-
assertEquals(node.size(), 27);
104+
assertEquals(node.size(), 28);
105105
assertEquals(node.get("guid").textValue(), GUID);
106106
assertEquals(node.get("identifier").textValue(), IDENTIFIER);
107107
assertEquals(node.get("revision").intValue(), 5);
@@ -133,6 +133,7 @@ public void serializeRountrip() throws Exception {
133133
assertEquals(node.get("additionalMetadata").get("key1").textValue(), "value1");
134134
assertEquals(node.get("additionalMetadata").get("key2").textValue(), "value2");
135135
assertEquals(node.get("type").textValue(), "Assessment");
136+
assertEquals(node.get("phase").textValue(), "draft");
136137

137138
ArrayNode tags = (ArrayNode)node.get("tags");
138139
assertEquals(tags.size(), 2);
@@ -192,6 +193,7 @@ public static Assessment createAssessment() {
192193
dto.setMinAge(MIN_AGE);
193194
dto.setMaxAge(MAX_AGE);
194195
dto.setAdditionalMetadata(ADDITIONAL_METADATA);
196+
dto.setPhase(AssessmentPhase.DRAFT);
195197
return dto;
196198
}
197199

@@ -232,5 +234,6 @@ private void assertAssessment(Assessment assessment) {
232234
assertEquals(assessment.getMinAge(), MIN_AGE);
233235
assertEquals(assessment.getMaxAge(), MAX_AGE);
234236
assertEquals(assessment.getAdditionalMetadata(), ADDITIONAL_METADATA);
237+
assertEquals(assessment.getPhase(), AssessmentPhase.DRAFT);
235238
}
236239
}

src/test/java/org/sagebionetworks/bridge/models/assessments/HibernateAssessmentTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public static HibernateAssessment createAssessment() {
7676
assessment.setMinAge(MIN_AGE);
7777
assessment.setMaxAge(MAX_AGE);
7878
assessment.setAdditionalMetadata(ADDITIONAL_METADATA);
79+
assessment.setPhase(AssessmentPhase.DRAFT);
7980
return assessment;
8081
}
8182

@@ -110,5 +111,6 @@ private void assertAssessment(HibernateAssessment assessment) {
110111
assertEquals(assessment.getMinAge(), MIN_AGE);
111112
assertEquals(assessment.getMaxAge(), MAX_AGE);
112113
assertEquals(assessment.getAdditionalMetadata(), ADDITIONAL_METADATA);
114+
assertEquals(assessment.getPhase(), AssessmentPhase.DRAFT);
113115
}
114116
}

0 commit comments

Comments
 (0)