Skip to content

Commit f1e21e5

Browse files
Merge pull request #214 from CodeForPhilly/public_check_flows
Updates to list and fetch individual library benefits
2 parents e28db75 + bdd2d50 commit f1e21e5

File tree

12 files changed

+171
-96
lines changed

12 files changed

+171
-96
lines changed

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

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import jakarta.ws.rs.core.Response;
1010

1111
import org.acme.auth.AuthUtils;
12-
import org.acme.enums.OptionalBoolean;
12+
import org.acme.enums.EvaluationResult;
1313
import org.acme.model.domain.Benefit;
1414
import org.acme.model.domain.CheckConfig;
1515
import org.acme.model.domain.EligibilityCheck;
@@ -20,6 +20,7 @@
2020
import org.acme.persistence.ScreenerRepository;
2121
import org.acme.persistence.StorageService;
2222
import org.acme.service.DmnService;
23+
import org.acme.service.LibraryApiService;
2324

2425
import java.util.*;
2526

@@ -41,6 +42,9 @@ public class DecisionResource {
4142
@Inject
4243
DmnService dmnService;
4344

45+
@Inject
46+
LibraryApiService libraryApi;
47+
4448
@POST
4549
@Path("/published/{screenerId}/evaluate")
4650
@Consumes(MediaType.APPLICATION_JSON)
@@ -124,39 +128,46 @@ private Map<String, Object> evaluateBenefit(Benefit benefit, Map<String, Object>
124128
return result;
125129
} else {
126130
// Custom benefit, evaluate here in the web app api (as opposed to calling the library api for evaluation)
127-
List<OptionalBoolean> checkResultsList = new ArrayList<>();
131+
List<EvaluationResult> resultsList = new ArrayList<>();
128132
Map<String, Object> checkResults = new HashMap<>();
129133

130134
int checkNum = 0;
131135
for (CheckConfig checkConfig : benefit.getChecks()) {
132136
String dmnFilepath = storageService.getCheckDmnModelPath(checkConfig.getCheckId());
133-
OptionalBoolean result = dmnService.evaluateDmn(
134-
dmnFilepath, checkConfig.getCheckName(), inputData, checkConfig.getParameters()
135-
);
136-
checkResultsList.add(result);
137+
EvaluationResult evaluationResult;
138+
if (isLibraryCheck(checkConfig)){
139+
EligibilityCheck check = libraryApi.getById(checkConfig.getCheckId());
140+
String path = check.getPath();
141+
evaluationResult = libraryApi.evaluateCheck(checkConfig, path, inputData);
142+
} else {
143+
evaluationResult = dmnService.evaluateDmn(
144+
dmnFilepath, checkConfig.getCheckName(), inputData, checkConfig.getParameters()
145+
);
146+
}
147+
resultsList.add(evaluationResult);
137148

138149
String uniqueCheckKey = checkConfig.getCheckId() + checkNum;
139-
checkResults.put(uniqueCheckKey, Map.of("name", checkConfig.getCheckName(), "result", result));
150+
checkResults.put(uniqueCheckKey, Map.of("name", checkConfig.getCheckName(), "result", evaluationResult));
140151
checkNum += 1;
141152
}
142153

143154
// Determine overall Benefit result
144-
Boolean allChecksTrue = checkResultsList.stream().allMatch(result -> result == OptionalBoolean.TRUE);
145-
Boolean anyChecksFalse = checkResultsList.stream().anyMatch(result -> result == OptionalBoolean.FALSE);
155+
Boolean allChecksTrue = resultsList.stream().allMatch(evaluationResult -> evaluationResult == EvaluationResult.TRUE);
156+
Boolean anyChecksFalse = resultsList.stream().anyMatch(evaluationResult -> evaluationResult == EvaluationResult.FALSE);
146157

147-
OptionalBoolean benefitResult;
158+
EvaluationResult benefitEvaluationResult;
148159
if (allChecksTrue) {
149-
benefitResult = OptionalBoolean.TRUE;
160+
benefitEvaluationResult = EvaluationResult.TRUE;
150161
} else if (anyChecksFalse) {
151-
benefitResult = OptionalBoolean.FALSE;
162+
benefitEvaluationResult = EvaluationResult.FALSE;
152163
} else {
153-
benefitResult = OptionalBoolean.UNABLE_TO_DETERMINE;
164+
benefitEvaluationResult = EvaluationResult.UNABLE_TO_DETERMINE;
154165
}
155166

156167
return new HashMap<String, Object>(
157168
Map.of(
158169
"name", benefit.getName(),
159-
"result", benefitResult,
170+
"result", benefitEvaluationResult,
160171
"check_results", checkResults
161172
)
162173
);
@@ -192,10 +203,10 @@ public Response evaluateCheck(
192203
try {
193204
String dmnFilepath = storageService.getCheckDmnModelPath(check.getId());
194205

195-
OptionalBoolean result = dmnService.evaluateDmn(
206+
EvaluationResult evaluationResult = dmnService.evaluateDmn(
196207
dmnFilepath, request.checkConfig.getCheckName(), request.inputData, request.checkConfig.getParameters()
197208
);
198-
return Response.ok().entity(Map.of("result", result)).build();
209+
return Response.ok().entity(Map.of("result", evaluationResult)).build();
199210
} catch (Exception e) {
200211
Log.error("Error: " + e.getMessage());
201212
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
@@ -218,4 +229,9 @@ private boolean isUserAuthorizedToAccessScreenerByScreener(String userId, Screen
218229
}
219230
return false;
220231
}
232+
233+
private boolean isLibraryCheck(CheckConfig checkConfig){
234+
Character libraryCheckPrefix = 'L';
235+
return libraryCheckPrefix.equals(checkConfig.getCheckId().charAt(0));
236+
}
221237
}

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import jakarta.inject.Inject;
44
import jakarta.ws.rs.*;
55
import jakarta.ws.rs.core.MediaType;
6+
import jakarta.ws.rs.core.Response;
67
import org.acme.model.domain.EligibilityCheck;
7-
import org.acme.service.LibraryApiMetadataService;
8+
import org.acme.service.LibraryApiService;
89

910
import java.util.List;
1011

@@ -13,7 +14,7 @@
1314
public class LibraryCheckResource {
1415

1516
@Inject
16-
LibraryApiMetadataService libraryApiMetadataService; // Inject the singleton bean
17+
LibraryApiService libraryApiMetadataService; // Inject the singleton bean
1718

1819
@GET
1920
@Path("/library-checks")
@@ -23,5 +24,18 @@ public List<EligibilityCheck> getLibraryChecks(@QueryParam("module") String modu
2324
}
2425
return libraryApiMetadataService.getAll();
2526
}
27+
28+
@GET
29+
@Path("/library-checks/{checkId}")
30+
public Response getLibraryCheck(@PathParam("checkId") String checkId) {
31+
if ( checkId != null) {
32+
EligibilityCheck check = libraryApiMetadataService.getById(checkId);
33+
if (check == null){
34+
return Response.status(Response.Status.NOT_FOUND).build();
35+
}
36+
return Response.ok().entity(check).build();
37+
}
38+
return Response.status(Response.Status.NOT_FOUND).build();
39+
}
2640
}
2741

builder-api/src/main/java/org/acme/enums/OptionalBoolean.java renamed to builder-api/src/main/java/org/acme/enums/EvaluationResult.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package org.acme.enums;
22

3-
public enum OptionalBoolean {
3+
public enum EvaluationResult {
44
TRUE("TRUE"),
55
FALSE("FALSE"),
66
UNABLE_TO_DETERMINE("UNABLE_TO_DETERMINE");
77

88
public final String label;
99

10-
private OptionalBoolean(String label) {
10+
private EvaluationResult(String label) {
1111
this.label = label;
1212
}
1313
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public class EligibilityCheck {
2121
private String ownerId;
2222
@JsonProperty("isPublic")
2323
private Boolean isPublic;
24+
// API endpoint for evaluating library checks
25+
private String path;
2426

2527
public String getId() {
2628
return this.id;
@@ -117,4 +119,12 @@ public JsonNode getSituation() {
117119
public void setSituation(JsonNode situation) {
118120
this.situation = situation;
119121
}
122+
123+
public String getPath() {
124+
return path;
125+
}
126+
127+
public void setPath(String path) {
128+
this.path = path;
129+
}
120130
}

builder-api/src/main/java/org/acme/service/DmnService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package org.acme.service;
2-
import org.acme.enums.OptionalBoolean;
2+
import org.acme.enums.EvaluationResult;
33

44
import java.util.List;
55
import java.util.Map;
@@ -11,7 +11,7 @@ public List<String> validateDmnXml(
1111
String modelId,
1212
String requiredBooleanDecisionName
1313
) throws Exception;
14-
public OptionalBoolean evaluateDmn(
14+
public EvaluationResult evaluateDmn(
1515
String dmnFilePath,
1616
String dmnModelName,
1717
Map<String, Object> inputs,

builder-api/src/main/java/org/acme/service/KieDmnService.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import io.quarkus.logging.Log;
44
import jakarta.enterprise.context.ApplicationScoped;
55
import jakarta.inject.Inject;
6-
import org.acme.enums.OptionalBoolean;
6+
import org.acme.enums.EvaluationResult;
77
import org.acme.persistence.StorageService;
88
import org.kie.api.KieServices;
99
import org.kie.api.builder.*;
@@ -133,7 +133,7 @@ private DmnCompilationResult compileDmnModel(String dmnXml, Map<String, String>
133133
return new DmnCompilationResult(kieModuleBytes, new ArrayList<String>());
134134
}
135135

136-
public OptionalBoolean evaluateDmn(
136+
public EvaluationResult evaluateDmn(
137137
String dmnFilePath,
138138
String dmnModelName,
139139
Map<String, Object> inputs,
@@ -189,13 +189,13 @@ public OptionalBoolean evaluateDmn(
189189
DMNDecisionResult decisionResult = decisionResults.get(0);
190190
Object result = decisionResult.getResult();
191191
if (result == null) {
192-
return OptionalBoolean.UNABLE_TO_DETERMINE;
192+
return EvaluationResult.UNABLE_TO_DETERMINE;
193193
}
194194
else if (result instanceof Boolean && (Boolean) result) {
195-
return OptionalBoolean.TRUE;
195+
return EvaluationResult.TRUE;
196196
}
197197
else if (result instanceof Boolean && !(Boolean) result) {
198-
return OptionalBoolean.FALSE;
198+
return EvaluationResult.FALSE;
199199
}
200200
throw new RuntimeException("Unexpected decision result type: " + result.getClass().getName());
201201
}

builder-api/src/main/java/org/acme/service/LibraryApiMetadataService.java renamed to builder-api/src/main/java/org/acme/service/LibraryApiService.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import jakarta.annotation.PostConstruct;
77
import jakarta.enterprise.context.ApplicationScoped;
88
import jakarta.inject.Inject;
9+
import org.acme.enums.EvaluationResult;
10+
import org.acme.model.domain.CheckConfig;
911
import org.acme.model.domain.EligibilityCheck;
1012
import org.acme.persistence.StorageService;
1113
import org.acme.persistence.FirestoreUtils;
@@ -16,7 +18,7 @@
1618

1719

1820
@ApplicationScoped
19-
public class LibraryApiMetadataService {
21+
public class LibraryApiService {
2022
@Inject
2123
private StorageService storageService;
2224

@@ -58,5 +60,19 @@ public List<EligibilityCheck> getByModule(String module) {
5860
.filter(e -> module.equals(e.getModule()))
5961
.toList();
6062
}
63+
64+
public EligibilityCheck getById(String id) {
65+
List<EligibilityCheck> matches = checks.stream()
66+
.filter(e -> id.equals(e.getId()))
67+
.toList();
68+
if (matches.isEmpty()) {
69+
return null;
70+
}
71+
return matches.getFirst();
72+
}
73+
74+
public EvaluationResult evaluateCheck(CheckConfig checkConfig, String path, Map<String, Object> inputs){
75+
return EvaluationResult.TRUE;
76+
}
6177
}
6278

builder-frontend/src/api/check.ts

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { EligibilityCheck, OptionalBoolean } from "@/types";
55
const apiUrl = import.meta.env.VITE_API_URL;
66

77
export const fetchPublicChecks = async (): Promise<EligibilityCheck[]> => {
8-
const url = apiUrl + "/checks";
8+
const url = apiUrl + "/library-checks";
99
try {
1010
const response = await authFetch(url, {
1111
method: "GET",
@@ -28,31 +28,11 @@ export const fetchPublicChecks = async (): Promise<EligibilityCheck[]> => {
2828
export const fetchCheck = async (
2929
checkId: string
3030
): Promise<EligibilityCheck> => {
31-
const url = apiUrl + `/checks/${checkId}`;
32-
try {
33-
const response = await authFetch(url, {
34-
method: "GET",
35-
headers: {
36-
Accept: "application/json",
37-
},
38-
});
39-
40-
if (!response.ok) {
41-
throw new Error(`Fetch failed with status: ${response.status}`);
42-
}
43-
const data = await response.json();
44-
console.log("Fetched check:", data);
45-
return data;
46-
} catch (error) {
47-
console.error("Error fetching check:", error);
48-
throw error; // rethrow so you can handle it in your component if needed
31+
let url = apiUrl + `/custom-checks/${checkId}`;
32+
if (checkId.charAt(0) === "L") {
33+
url = apiUrl + `/library-checks/${checkId}`;
4934
}
50-
};
5135

52-
export const fetchCustomCheck = async (
53-
checkId: string
54-
): Promise<EligibilityCheck> => {
55-
const url = apiUrl + `/custom-checks/${checkId}`;
5636
try {
5737
const response = await authFetch(url, {
5838
method: "GET",
@@ -140,7 +120,10 @@ export const saveCheckDmn = async (checkId: string, dmnModel: string) => {
140120
}
141121
};
142122

143-
export const validateCheckDmn = async (checkId: string, dmnModel: string): Promise<string[]> => {
123+
export const validateCheckDmn = async (
124+
checkId: string,
125+
dmnModel: string
126+
): Promise<string[]> => {
144127
const url = apiUrl + "/validate-check-dmn";
145128
try {
146129
const response = await authFetch(url, {
@@ -189,7 +172,11 @@ export const fetchUserDefinedChecks = async (
189172
}
190173
};
191174

192-
export const evaluateWorkingCheck = async (checkId: string, checkConfig: any, inputData: Record<string, any>): Promise<OptionalBoolean> => {
175+
export const evaluateWorkingCheck = async (
176+
checkId: string,
177+
checkConfig: any,
178+
inputData: Record<string, any>
179+
): Promise<OptionalBoolean> => {
193180
const url = apiUrl + `/decision/working-check?checkId=${checkId}`;
194181
try {
195182
const response = await authFetch(url, {
@@ -210,9 +197,11 @@ export const evaluateWorkingCheck = async (checkId: string, checkConfig: any, in
210197
console.error("Error testing check:", error);
211198
throw error; // rethrow so you can handle it in your component if needed
212199
}
213-
}
200+
};
214201

215-
export const getRelatedPublishedChecks = async (checkId: string): Promise<EligibilityCheck[]> => {
202+
export const getRelatedPublishedChecks = async (
203+
checkId: string
204+
): Promise<EligibilityCheck[]> => {
216205
const url = apiUrl + `/custom-checks/${checkId}/published-check-versions`;
217206
try {
218207
const response = await authFetch(url, {
@@ -231,9 +220,11 @@ export const getRelatedPublishedChecks = async (checkId: string): Promise<Eligib
231220
console.error("Error fetching related published checks:", error);
232221
throw error; // rethrow so you can handle it in your component if needed
233222
}
234-
}
223+
};
235224

236-
export const publishCheck = async (checkId: string): Promise<OptionalBoolean> => {
225+
export const publishCheck = async (
226+
checkId: string
227+
): Promise<OptionalBoolean> => {
237228
const url = apiUrl + `/publish-check/${checkId}`;
238229
try {
239230
const response = await authFetch(url, {

0 commit comments

Comments
 (0)