Skip to content

Commit 2515229

Browse files
Merge pull request #204 from CodeForPhilly/check-testing-and-publishing
2 parents 2b423e8 + 3a359a3 commit 2515229

File tree

20 files changed

+972
-111
lines changed

20 files changed

+972
-111
lines changed

builder-api/src/main/java/org/acme/controller/DecisionResource.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
import org.acme.enums.OptionalBoolean;
1313
import org.acme.model.domain.Benefit;
1414
import org.acme.model.domain.CheckConfig;
15+
import org.acme.model.domain.EligibilityCheck;
1516
import org.acme.model.domain.Screener;
17+
import org.acme.model.dto.EvaluateCheckRequest;
1618
import org.acme.persistence.EligibilityCheckRepository;
1719
import org.acme.persistence.PublishedScreenerRepository;
1820
import org.acme.persistence.ScreenerRepository;
@@ -116,7 +118,6 @@ public Response evaluateScreener(
116118
}
117119

118120
private Map<String, Object> evaluateBenefit(Benefit benefit, Map<String, Object> inputData) throws Exception {
119-
120121
if (benefit.getPublic()){
121122
// Public benefit, call the Library API to evaluate
122123
Map<String, Object> result = new HashMap<>();
@@ -159,6 +160,46 @@ private Map<String, Object> evaluateBenefit(Benefit benefit, Map<String, Object>
159160
}
160161
}
161162

163+
@POST
164+
@Path("/decision/working-check")
165+
@Consumes(MediaType.APPLICATION_JSON)
166+
@Produces(MediaType.APPLICATION_JSON)
167+
public Response evaluateCheck(
168+
@Context SecurityIdentity identity,
169+
@QueryParam("checkId") String checkId,
170+
EvaluateCheckRequest request
171+
) throws Exception {
172+
String userId = AuthUtils.getUserId(identity);
173+
174+
if (checkId == null || checkId.isBlank()){
175+
return Response.status(Response.Status.BAD_REQUEST)
176+
.entity("Error: Missing required query parameter: checkId")
177+
.build();
178+
}
179+
180+
// Get EligibilityCheck
181+
Optional<EligibilityCheck> checkOpt = eligibilityCheckRepository.getWorkingCustomCheck(userId, checkId);
182+
if (checkOpt.isEmpty()) {
183+
return Response.status(Response.Status.NOT_FOUND)
184+
.entity("Error: Check not found")
185+
.build();
186+
}
187+
EligibilityCheck check = checkOpt.get();
188+
189+
try {
190+
String dmnFilepath = storageService.getCheckDmnModelPath(check.getId());
191+
String dmnModelName = check.getId();
192+
193+
OptionalBoolean result = dmnService.evaluateSimpleDmn(
194+
dmnFilepath, dmnModelName, request.inputData, request.checkConfig.getParameters()
195+
);
196+
return Response.ok().entity(Map.of("result", result)).build();
197+
} catch (Exception e) {
198+
Log.error("Error: " + e.getMessage());
199+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
200+
}
201+
}
202+
162203
private boolean isUserAuthorizedToAccessScreenerByScreenerId(String userId, String screenerId) {
163204
Optional<Screener> screenerOpt = screenerRepository.getWorkingScreenerMetaDataOnly(screenerId);
164205
if (screenerOpt.isEmpty()){

builder-api/src/main/java/org/acme/controller/EligibilityCheckResource.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,14 @@ public Response publishCustomCheck(@Context SecurityIdentity identity, @PathPara
262262
return Response.status(Response.Status.UNAUTHORIZED).build();
263263
}
264264

265+
// Retrieve DMN Path before incrementing version
266+
Optional<String> workingDmnOpt = storageService.getStringFromStorage(storageService.getCheckDmnModelPath(check.getId()));
267+
if (!workingDmnOpt.isPresent()) {
268+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
269+
.entity(Map.of("error", "could not find DMN file for working Check"))
270+
.build();
271+
}
272+
265273
// Update workingCheck so that the incremented version number is saved
266274
check.setVersion(check.getVersion() + 1);
267275
try {
@@ -278,10 +286,11 @@ public Response publishCustomCheck(@Context SecurityIdentity identity, @PathPara
278286
String publishedCheckId = eligibilityCheckRepository.saveNewPublishedCustomCheck(check);
279287

280288
// save published check DMN to storage
281-
Optional<String> workingDmnOpt = storageService.getStringFromStorage(storageService.getCheckDmnModelPath(check.getId()));
282289
if (workingDmnOpt.isPresent()){
283290
String workingDmn = workingDmnOpt.get();
284291
storageService.writeStringToStorage(storageService.getCheckDmnModelPath(publishedCheckId), workingDmn, "application/xml");
292+
} else {
293+
Log.warn("Could not find working DMN model for check " + check.getId() + ", published check created without DMN model");
285294
}
286295
} catch (Exception e){
287296
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
@@ -291,4 +300,34 @@ public Response publishCustomCheck(@Context SecurityIdentity identity, @PathPara
291300

292301
return Response.ok(check, MediaType.APPLICATION_JSON).build();
293302
}
303+
304+
/* Endpoint for returning all Published Check Versions related to a given Working Eligibility Check */
305+
@GET
306+
@Path("/custom-checks/{checkId}/published-check-versions")
307+
public Response getPublishedVersionsOfWorkingCheck(@Context SecurityIdentity identity, @PathParam("checkId") String checkId){
308+
String userId = AuthUtils.getUserId(identity);
309+
Optional<EligibilityCheck> checkOpt = eligibilityCheckRepository.getWorkingCustomCheck(userId, checkId);
310+
if (checkOpt.isEmpty()){
311+
return Response.status(Response.Status.NOT_FOUND).build();
312+
}
313+
314+
EligibilityCheck check = checkOpt.get();
315+
316+
// Authorization
317+
if (!userId.equals(check.getOwnerId())){
318+
return Response.status(Response.Status.UNAUTHORIZED).build();
319+
}
320+
321+
// Update workingCheck so that the incremented version number is saved
322+
check.setVersion(check.getVersion() + 1);
323+
try {
324+
List<EligibilityCheck> publishedChecks = eligibilityCheckRepository.getPublishedCheckVersions(check);
325+
326+
return Response.ok(publishedChecks, MediaType.APPLICATION_JSON).build();
327+
} catch (Exception e){
328+
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
329+
.entity(Map.of("error", "could not update working Check, published check version was not created"))
330+
.build();
331+
}
332+
}
294333
}

builder-api/src/main/java/org/acme/model/domain/EligibilityCheck.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import com.fasterxml.jackson.annotation.JsonProperty;
5-
import org.acme.constants.CheckStatus;
65

76
import java.util.List;
87

@@ -108,6 +107,4 @@ public Boolean getPublic() {
108107
public void setPublic(Boolean aPublic) {
109108
isPublic = aPublic;
110109
}
111-
112-
113110
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.acme.model.dto;
2+
3+
import java.util.Map;
4+
5+
import org.acme.model.domain.CheckConfig;
6+
7+
public class EvaluateCheckRequest {
8+
public CheckConfig checkConfig;
9+
public Map<String, Object> inputData;
10+
}

builder-api/src/main/java/org/acme/persistence/EligibilityCheckRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public interface EligibilityCheckRepository {
1616

1717
List<EligibilityCheck> getWorkingCustomChecks(String userId);
1818

19+
List<EligibilityCheck> getPublishedCheckVersions(EligibilityCheck workingCustomCheck);
20+
1921
List<EligibilityCheck> getPublishedCustomChecks(String userId);
2022

2123
Optional<EligibilityCheck> getWorkingCustomCheck(String userId, String checkId);

builder-api/src/main/java/org/acme/persistence/FirestoreUtils.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,32 @@ public static List<Map<String, Object>> getFirestoreDocsByField(String collectio
5050
return data;
5151
})
5252
.toList();
53+
}catch(Exception e){
54+
Log.error("Error fetching documents from firestore: ", e);
55+
return new ArrayList<>();
56+
}
57+
}
5358

59+
public static List<Map<String, Object>> getFirestoreDocsByFields(String collection, Map<String, String> fieldValues) {
60+
System.out.println("Fetching documents from collection: " + collection + " with field values: " + fieldValues);
61+
System.out.println("Using Firestore instance: " + db.listCollections());
62+
try {
63+
Query query = db.collection(collection);
64+
for (Map.Entry<String, String> entry : fieldValues.entrySet()) {
65+
// Add a whereEqualTo clause for each field-value pair
66+
query = query.whereEqualTo(entry.getKey(), entry.getValue());
67+
}
68+
ApiFuture<QuerySnapshot> querySnapshot = query.get();
69+
List<QueryDocumentSnapshot> documents;
70+
documents = querySnapshot.get().getDocuments();
71+
72+
return documents.stream()
73+
.map(doc -> {
74+
Map<String, Object> data = doc.getData();
75+
data.put("id", doc.getId());
76+
return data;
77+
})
78+
.toList();
5479
}catch(Exception e){
5580
Log.error("Error fetching documents from firestore: ", e);
5681
return new ArrayList<>();

builder-api/src/main/java/org/acme/persistence/impl/EligibilityCheckRepositoryImpl.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.annotation.JsonInclude;
44
import com.fasterxml.jackson.databind.ObjectMapper;
55

6+
import io.quarkus.logging.Log;
67
import jakarta.enterprise.context.ApplicationScoped;
78
import jakarta.inject.Inject;
89

@@ -72,7 +73,6 @@ public List<EligibilityCheck> getWorkingCustomChecks(String userId){
7273
List<Map<String, Object>> checkMaps = FirestoreUtils.getFirestoreDocsByField(CollectionNames.WORKING_CUSTOM_CHECK_COLLECTION, FieldNames.OWNER_ID, userId);
7374
ObjectMapper mapper = new ObjectMapper();
7475
return checkMaps.stream().map(checkMap -> mapper.convertValue(checkMap, EligibilityCheck.class)).toList();
75-
7676
}
7777

7878
public List<EligibilityCheck> getPublishedCustomChecks(String userId){
@@ -81,6 +81,24 @@ public List<EligibilityCheck> getPublishedCustomChecks(String userId){
8181
return checkMaps.stream().map(checkMap -> mapper.convertValue(checkMap, EligibilityCheck.class)).toList();
8282
}
8383

84+
public List<EligibilityCheck> getPublishedCheckVersions(EligibilityCheck workingCustomCheck){
85+
Map<String, String> fieldValues = Map.of(
86+
"ownerId", workingCustomCheck.getOwnerId(),
87+
"module", workingCustomCheck.getModule(),
88+
"name", workingCustomCheck.getName()
89+
);
90+
91+
/* Get all related Published Checks for a Working Check */
92+
List<Map<String, Object>> checkMaps = (
93+
FirestoreUtils.getFirestoreDocsByFields(
94+
CollectionNames.PUBLISHED_CUSTOM_CHECK_COLLECTION,
95+
fieldValues
96+
)
97+
);
98+
ObjectMapper mapper = new ObjectMapper();
99+
return checkMaps.stream().map(checkMap -> mapper.convertValue(checkMap, EligibilityCheck.class)).toList();
100+
}
101+
84102
public Optional<EligibilityCheck> getWorkingCustomCheck(String userId, String checkId){
85103
return getCustomCheck(userId, checkId, false);
86104
}
@@ -116,21 +134,22 @@ public String saveNewWorkingCustomCheck(EligibilityCheck check) throws Exception
116134
return FirestoreUtils.persistDocumentWithId(CollectionNames.WORKING_CUSTOM_CHECK_COLLECTION, checkId, data);
117135
}
118136

119-
public void updateWorkingCustomCheck(EligibilityCheck check) throws Exception{
137+
public void updateWorkingCustomCheck(EligibilityCheck check) throws Exception {
120138
ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
121139
Map<String, Object> data = mapper.convertValue(check, Map.class);
122140
FirestoreUtils.updateDocument(CollectionNames.WORKING_CUSTOM_CHECK_COLLECTION, data, check.getId());
123141
}
124142

125-
public String saveNewPublishedCustomCheck(EligibilityCheck check) throws Exception{
126-
check.setId(getPublishedId(check));
143+
public String saveNewPublishedCustomCheck(EligibilityCheck check) throws Exception {
127144
ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
128145
Map<String, Object> data = mapper.convertValue(check, Map.class);
146+
data.put("id", getPublishedId(check));
147+
data.put("datePublished", System.currentTimeMillis());
148+
129149
String checkDocId = getPublishedId(check);
130150
return FirestoreUtils.persistDocumentWithId(CollectionNames.PUBLISHED_CUSTOM_CHECK_COLLECTION, checkDocId, data);
131151
}
132152

133-
134153
public void updatePublishedCustomCheck(EligibilityCheck check) throws Exception{
135154
ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
136155
Map<String, Object> data = mapper.convertValue(check, Map.class);
@@ -149,7 +168,11 @@ public String getWorkingId(EligibilityCheck check) {
149168
return CheckStatus.WORKING.getCode() + "-" + check.getOwnerId() + "-" + check.getModule() + "-" + check.getName();
150169
}
151170

171+
public String getPublishedPrefix(EligibilityCheck check) {
172+
return CheckStatus.PUBLISHED.getCode() + "-" + check.getOwnerId() + "-" + check.getModule() + "-" + check.getName();
173+
}
174+
152175
public String getPublishedId(EligibilityCheck check) {
153-
return CheckStatus.PUBLISHED.getCode() + "-" + check.getOwnerId() + "-" + check.getModule() + "-" + check.getName() + "-" + check.getVersion().toString();
176+
return getPublishedPrefix(check) + "-" + check.getVersion().toString();
154177
}
155178
}

0 commit comments

Comments
 (0)