Skip to content

Commit da30c3a

Browse files
Merge pull request #201 from CodeForPhilly/publish-screener-flow
feat: Publish Screener flow
2 parents bf5bebb + 6168edf commit da30c3a

29 files changed

+691
-547
lines changed

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

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.acme.persistence.EligibilityCheckRepository;
1515

1616
import java.util.List;
17-
import java.util.Map;
1817
import java.util.Optional;
1918

2019
@Path("/api")
@@ -34,7 +33,7 @@ public Response getAllBenefits(@Context SecurityIdentity identity) {
3433
return Response.status(Response.Status.UNAUTHORIZED).build();
3534
}
3635
Log.info("Fetching all eligibility checks. User: " + userId);
37-
List<Benefit> benefits = benefitRepository.getAllPublicBenefits();
36+
List<Benefit> benefits = benefitRepository.getAllBenefits();
3837

3938
return Response.ok(benefits, MediaType.APPLICATION_JSON).build();
4039
}
@@ -87,70 +86,4 @@ public Response getBenefitChecks(@Context SecurityIdentity identity,
8786

8887
return Response.ok(checks, MediaType.APPLICATION_JSON).build();
8988
}
90-
91-
92-
@PUT
93-
@Consumes(MediaType.APPLICATION_JSON)
94-
@Path("/benefit")
95-
public Response updateBenefit(@Context SecurityIdentity identity,
96-
Benefit newBenefit) {
97-
String userId = AuthUtils.getUserId(identity);
98-
//TODO: Add validations for user provided data
99-
100-
newBenefit.setOwnerId(userId);
101-
try {
102-
Optional<Benefit> benefitOpt = benefitRepository.getBenefit(newBenefit.getId());
103-
if (benefitOpt.isEmpty()){
104-
return Response.status(Response.Status.NOT_FOUND).build();
105-
}
106-
Benefit existingBenefit = benefitOpt.get();
107-
108-
if (!isUserAuthorizedToUpdateBenefit(userId, existingBenefit)){
109-
return Response.status(Response.Status.UNAUTHORIZED).build();
110-
}
111-
112-
113-
benefitRepository.updateBenefit(newBenefit);
114-
return Response.ok(newBenefit, MediaType.APPLICATION_JSON).build();
115-
116-
} catch (Exception e){
117-
Log.error(e);
118-
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
119-
.entity(Map.of("error", "Could not update benefit"))
120-
.build();
121-
}
122-
}
123-
124-
// Utility endpoint to create a public benefit
125-
@POST
126-
@Path("/benefit")
127-
public Response createBenefit(@Context SecurityIdentity identity,
128-
Benefit newBenefit) {
129-
String userId = AuthUtils.getUserId(identity);
130-
131-
//TODO: Add validations for user provided data
132-
133-
newBenefit.setOwnerId(userId);
134-
try {
135-
String benefitId = benefitRepository.saveNewBenefit(newBenefit);
136-
newBenefit.setId(benefitId);
137-
return Response.ok(newBenefit, MediaType.APPLICATION_JSON).build();
138-
} catch (Exception e){
139-
Log.error(e);
140-
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
141-
.entity(Map.of("error", "Could not save benefit"))
142-
.build();
143-
}
144-
}
145-
146-
private boolean isUserAuthorizedToUpdateBenefit(String userId, Benefit benefit) {
147-
String ownerId = benefit.getOwnerId();
148-
if (ownerId == null){
149-
return false;
150-
}
151-
if (userId.equals(ownerId)){
152-
return true;
153-
}
154-
return false;
155-
}
15689
}

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

Lines changed: 79 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
import org.acme.auth.AuthUtils;
1212
import org.acme.enums.OptionalBoolean;
1313
import org.acme.model.domain.Benefit;
14+
import org.acme.model.domain.CheckConfig;
1415
import org.acme.model.domain.EligibilityCheck;
1516
import org.acme.model.domain.Screener;
16-
import org.acme.persistence.BenefitRepository;
1717
import org.acme.persistence.EligibilityCheckRepository;
18+
import org.acme.persistence.PublishedScreenerRepository;
1819
import org.acme.persistence.ScreenerRepository;
1920
import org.acme.persistence.StorageService;
2021
import org.acme.service.DmnService;
@@ -23,53 +24,48 @@
2324

2425
@Path("/api")
2526
public class DecisionResource {
26-
27+
2728
@Inject
28-
ScreenerRepository screenerRepository;
29+
EligibilityCheckRepository eligibilityCheckRepository;
2930

3031
@Inject
31-
StorageService storageService;
32+
ScreenerRepository screenerRepository;
3233

3334
@Inject
34-
DmnService dmnService;
35+
PublishedScreenerRepository publishedScreenerRepository;
3536

3637
@Inject
37-
EligibilityCheckRepository eligibilityCheckRepository;
38+
StorageService storageService;
3839

3940
@Inject
40-
BenefitRepository benefitRepository;
41+
DmnService dmnService;
4142

4243
@POST
43-
@Path("/decision/v2")
44+
@Path("/published/{screenerId}/evaluate")
4445
@Consumes(MediaType.APPLICATION_JSON)
4546
@Produces(MediaType.APPLICATION_JSON)
46-
public Response evaluateScreener(
47-
@Context SecurityIdentity identity,
48-
@QueryParam("screenerId") String screenerId,
47+
public Response evaluatePublishedScreener(
48+
@PathParam("screenerId") String screenerId,
4949
Map<String, Object> inputData
5050
) throws Exception {
51-
// Authorize user and get benefit
52-
String userId = AuthUtils.getUserId(identity);
53-
if (screenerId.isEmpty() || !isUserAuthorizedToAccessScreenerByScreenerId(userId, screenerId)){
54-
return Response.status(Response.Status.UNAUTHORIZED).build();
55-
}
56-
57-
Optional<Screener> screenerOpt = screenerRepository.getWorkingScreener(screenerId);
51+
Optional<Screener> screenerOpt = publishedScreenerRepository.getScreener(screenerId);
5852
if (screenerOpt.isEmpty()){
53+
Log.info("Screener not found: " + screenerId);
5954
return Response.status(Response.Status.NOT_FOUND).build();
6055
}
6156
Screener screener = screenerOpt.get();
6257

63-
List<Benefit> benefits = benefitRepository.getBenefitsInScreener(screener);
58+
List<Benefit> benefits = publishedScreenerRepository.getBenefitsInScreener(screener);
6459
if (benefits.isEmpty()){
60+
Log.info("Benefits not found: " + screenerId);
6561
return Response.status(Response.Status.NOT_FOUND).build();
6662
}
6763

6864
try {
6965
Map<String, Object> screenerResults = new HashMap<String, Object>();
7066
for (Benefit benefit : benefits) {
7167
// Evaluate benefit
72-
Map<String, Object> benefitResults = evaluateBenefitDmn(benefit, inputData);
68+
Map<String, Object> benefitResults = evaluateBenefit(benefit, inputData);
7369
screenerResults.put(benefit.getId(), benefitResults);
7470
}
7571
return Response.ok().entity(screenerResults).build();
@@ -80,53 +76,46 @@ public Response evaluateScreener(
8076
}
8177

8278
@POST
83-
@Path("/decision/v2/benefit")
79+
@Path("/decision/v2")
8480
@Consumes(MediaType.APPLICATION_JSON)
8581
@Produces(MediaType.APPLICATION_JSON)
86-
public Response evaluateBenefit(
82+
public Response evaluateScreener(
8783
@Context SecurityIdentity identity,
8884
@QueryParam("screenerId") String screenerId,
89-
@QueryParam("benefitId") String benefitId,
9085
Map<String, Object> inputData
9186
) throws Exception {
92-
if (benefitId == null || benefitId.isBlank()){
93-
return Response.status(Response.Status.BAD_REQUEST)
94-
.entity("Error: Missing required query parameter: benefitId")
95-
.build();
96-
}
97-
if (inputData == null || inputData.isEmpty()){
98-
return Response.status(Response.Status.BAD_REQUEST)
99-
.entity("Error: Missing decision inputs")
100-
.build();
101-
}
102-
10387
// Authorize user and get benefit
10488
String userId = AuthUtils.getUserId(identity);
105-
Optional<Benefit> benefitOpt = Optional.empty();
106-
if (!screenerId.isEmpty()){
107-
if (!isUserAuthorizedToAccessScreenerByScreenerId(userId, screenerId)){
108-
return Response.status(Response.Status.UNAUTHORIZED).build();
109-
}
110-
benefitOpt = benefitRepository.getCustomBenefit(screenerId, benefitId);
111-
} else {
112-
benefitOpt = benefitRepository.getBenefit(benefitId);
89+
if (screenerId.isEmpty() || !isUserAuthorizedToAccessScreenerByScreenerId(userId, screenerId)){
90+
return Response.status(Response.Status.UNAUTHORIZED).build();
91+
}
92+
93+
Optional<Screener> screenerOpt = screenerRepository.getWorkingScreener(screenerId);
94+
if (screenerOpt.isEmpty()){
95+
return Response.status(Response.Status.NOT_FOUND).build();
11396
}
114-
if (benefitOpt.isEmpty()){
97+
Screener screener = screenerOpt.get();
98+
99+
List<Benefit> benefits = screenerRepository.getBenefitsInScreener(screener);
100+
if (benefits.isEmpty()){
115101
return Response.status(Response.Status.NOT_FOUND).build();
116102
}
117103

118-
Benefit benefit = benefitOpt.get();
119104
try {
120-
// Evaluate benefit
121-
Map<String, Object> results = evaluateBenefitDmn(benefit, inputData);
122-
return Response.ok().entity(results).build();
105+
Map<String, Object> screenerResults = new HashMap<String, Object>();
106+
for (Benefit benefit : benefits) {
107+
// Evaluate benefit
108+
Map<String, Object> benefitResults = evaluateBenefit(benefit, inputData);
109+
screenerResults.put(benefit.getId(), benefitResults);
110+
}
111+
return Response.ok().entity(screenerResults).build();
123112
} catch (Exception e) {
124113
Log.error("Error: " + e.getMessage());
125114
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
126115
}
127116
}
128117

129-
private Map<String, Object> evaluateBenefitDmn(Benefit benefit, Map<String, Object> inputData) throws Exception {
118+
private Map<String, Object> evaluateBenefit(Benefit benefit, Map<String, Object> inputData) throws Exception {
130119
List<EligibilityCheck> checks = eligibilityCheckRepository.getChecksInBenefit(benefit);
131120

132121
if (benefit.getPublic()){
@@ -138,50 +127,48 @@ private Map<String, Object> evaluateBenefitDmn(Benefit benefit, Map<String, Obje
138127
List<OptionalBoolean> checkResultsList = new ArrayList<>();
139128
Map<String, Object> checkResults = new HashMap<>();
140129

141-
Map<String, Object> result = new HashMap<>();
142-
return result;
143-
//TODO: update implementation here
144-
// for (EligibilityCheck check : checks) {
145-
// Optional<CheckConfig> matchingCheckConfig = benefit.getChecks().stream().filter(
146-
// checkConfig -> checkConfig.getCheckId().equals(check.getId())
147-
// ).findFirst();
148-
// if (matchingCheckConfig.isEmpty()) {
149-
// throw new Exception("Could not find CheckConfig for check " + check.getId());
150-
// }
151-
//
152-
// String dmnFilepath = storageService.getCheckDmnModelPath(
153-
// check.getModule(), check.getId(), check.getVersion()
154-
// );
155-
// String dmnModelName = check.getId();
156-
//
157-
// OptionalBoolean result = dmnService.evaluateSimpleDmn(
158-
// dmnFilepath, dmnModelName, inputData, matchingCheckConfig.get().getParameters()
159-
// );
160-
// checkResultsList.add(result);
161-
// checkResults.put(check.getId(), Map.of("name", check.getName(), "result", result));
162-
// }
163-
//
164-
// // Determine overall Benefit result
165-
// Boolean allChecksTrue = checkResultsList.stream().allMatch(result -> result == OptionalBoolean.TRUE);
166-
// Boolean anyChecksFalse = checkResultsList.stream().anyMatch(result -> result == OptionalBoolean.FALSE);
167-
// Log.info("All True: " + allChecksTrue + " Any False: " + anyChecksFalse);
168-
//
169-
// OptionalBoolean benefitResult;
170-
// if (allChecksTrue) {
171-
// benefitResult = OptionalBoolean.TRUE;
172-
// } else if (anyChecksFalse) {
173-
// benefitResult = OptionalBoolean.FALSE;
174-
// } else {
175-
// benefitResult = OptionalBoolean.UNABLE_TO_DETERMINE;
176-
// }
177-
//
178-
// return new HashMap<String, Object>(
179-
// Map.of(
180-
// "name", benefit.getName(),
181-
// "result", benefitResult,
182-
// "check_results", checkResults
183-
// )
184-
// );
130+
// TODO: update implementation here
131+
for (EligibilityCheck check : checks) {
132+
Optional<CheckConfig> matchingCheckConfig = benefit.getChecks().stream().filter(
133+
checkConfig -> checkConfig.getCheckId().equals(check.getId())
134+
).findFirst();
135+
if (matchingCheckConfig.isEmpty()) {
136+
throw new Exception("Could not find CheckConfig for check " + check.getId());
137+
}
138+
139+
String dmnFilepath = storageService.getCheckDmnModelPath(
140+
check.getOwnerId(), check.getId()
141+
);
142+
String dmnModelName = check.getId();
143+
144+
OptionalBoolean result = dmnService.evaluateSimpleDmn(
145+
dmnFilepath, dmnModelName, inputData, matchingCheckConfig.get().getParameters()
146+
);
147+
checkResultsList.add(result);
148+
checkResults.put(check.getId(), Map.of("name", check.getName(), "result", result));
149+
}
150+
151+
// Determine overall Benefit result
152+
Boolean allChecksTrue = checkResultsList.stream().allMatch(result -> result == OptionalBoolean.TRUE);
153+
Boolean anyChecksFalse = checkResultsList.stream().anyMatch(result -> result == OptionalBoolean.FALSE);
154+
Log.info("All True: " + allChecksTrue + " Any False: " + anyChecksFalse);
155+
156+
OptionalBoolean benefitResult;
157+
if (allChecksTrue) {
158+
benefitResult = OptionalBoolean.TRUE;
159+
} else if (anyChecksFalse) {
160+
benefitResult = OptionalBoolean.FALSE;
161+
} else {
162+
benefitResult = OptionalBoolean.UNABLE_TO_DETERMINE;
163+
}
164+
165+
return new HashMap<String, Object>(
166+
Map.of(
167+
"name", benefit.getName(),
168+
"result", benefitResult,
169+
"check_results", checkResults
170+
)
171+
);
185172
}
186173
}
187174

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public Response createPublicCheck(@Context SecurityIdentity identity,
7070
EligibilityCheck newCheck) {
7171
String userId = AuthUtils.getUserId(identity);
7272

73-
//TODO: Add validations for user provided data
73+
// TODO: Add validations for user provided data
7474
newCheck.setOwnerId(userId);
7575
newCheck.setPublic(true);
7676
newCheck.setVersion(1);

0 commit comments

Comments
 (0)