Skip to content

Commit 78093e0

Browse files
authored
Merge pull request #35 from JebronLames32/UIcontroller
Add UI controller to display results of BSA and credit report
2 parents 8e676a2 + c472f79 commit 78093e0

File tree

5 files changed

+142
-10
lines changed

5 files changed

+142
-10
lines changed

src/main/java/org/mifos/loanrisk/external/bsa/arya/AryaBankStatementAnalysisService.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import java.util.Base64;
44
import java.util.UUID;
5-
import com.fasterxml.jackson.core.JsonProcessingException;
65
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.fasterxml.jackson.databind.node.ObjectNode;
77
import io.r2dbc.postgresql.codec.Json;
88
import lombok.RequiredArgsConstructor;
99
import lombok.extern.slf4j.Slf4j;
@@ -73,13 +73,20 @@ private Mono<Void> sendRequest(String base64, DocumentDataV1 document, Aggregato
7373
}
7474

7575
private Mono<BankStatementAnalysisResult> saveResult(AryaBsaResponse resp, Aggregator aggregator) {
76-
try {
77-
String json = mapper.writeValueAsString(resp);
78-
BankStatementAnalysisResult result = new BankStatementAnalysisResult(null, aggregator.getLoanId(), Json.of(json));
79-
return resultRepository.save(result);
80-
} catch (JsonProcessingException e) {
81-
return Mono.error(e);
82-
}
76+
String reportKey = "bsa/report-" + resp.reqId() + ".pdf";
77+
byte[] pdf = Base64.getDecoder().decode(resp.data());
78+
return storageClient.put(pdf, reportKey)
79+
.then(Mono.fromCallable(() -> {
80+
ObjectNode node = mapper.createObjectNode();
81+
node.put("req_id", resp.reqId());
82+
node.put("success", resp.success());
83+
if (resp.errorMessage() != null) {
84+
node.put("error_message", resp.errorMessage());
85+
}
86+
node.put("reportKey", reportKey);
87+
return new BankStatementAnalysisResult(null, aggregator.getLoanId(), Json.of(node.toString()));
88+
}))
89+
.flatMap(resultRepository::save);
8390
}
8491

8592
private Mono<Void> updateAggregatorStatus(Aggregator aggregator) {
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.mifos.loanrisk.external.bsa.arya;
22

33
import com.fasterxml.jackson.annotation.JsonProperty;
4-
import java.util.Map;
54

65
/**
76
* DTO for Arya's bank statement analysis response.
@@ -10,6 +9,6 @@ public record AryaBsaResponse(
109
@JsonProperty("req_id") String reqId,
1110
@JsonProperty("success") Boolean success,
1211
@JsonProperty("error_message") String errorMessage,
13-
@JsonProperty("data") Map<String, Object> data) {
12+
@JsonProperty("data") String data) {
1413
}
1514

src/main/java/org/mifos/loanrisk/external/bsa/repository/BankStatementAnalysisResultRepository.java

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

33
import org.mifos.loanrisk.external.bsa.domain.BankStatementAnalysisResult;
44
import org.springframework.data.r2dbc.repository.R2dbcRepository;
5+
import reactor.core.publisher.Flux;
56

67
public interface BankStatementAnalysisResultRepository extends R2dbcRepository<BankStatementAnalysisResult, Long> {
8+
9+
Flux<BankStatementAnalysisResult> findAllByLoanId(Long loanId);
710
}

src/main/java/org/mifos/loanrisk/external/cb/repository/CreditBureauResultRepository.java

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

33
import org.mifos.loanrisk.external.cb.domain.CreditBureauResult;
44
import org.springframework.data.r2dbc.repository.R2dbcRepository;
5+
import reactor.core.publisher.Flux;
56

67
public interface CreditBureauResultRepository extends R2dbcRepository<CreditBureauResult, Long> {
8+
9+
Flux<CreditBureauResult> findAllByLoanId(Long loanId);
710
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package org.mifos.loanrisk.external.controller;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import com.fasterxml.jackson.databind.node.ObjectNode;
6+
import io.r2dbc.postgresql.codec.Json;
7+
import lombok.AllArgsConstructor;
8+
import org.mifos.loanrisk.document.storage.ObjectStorageClient;
9+
import org.mifos.loanrisk.external.bsa.domain.BankStatementAnalysisResult;
10+
import org.mifos.loanrisk.external.bsa.repository.BankStatementAnalysisResultRepository;
11+
import org.mifos.loanrisk.external.cb.domain.CreditBureauResult;
12+
import org.mifos.loanrisk.external.cb.repository.CreditBureauResultRepository;
13+
import org.springframework.http.HttpHeaders;
14+
import org.springframework.http.MediaType;
15+
import org.springframework.http.ResponseEntity;
16+
import org.springframework.web.bind.annotation.GetMapping;
17+
import org.springframework.web.bind.annotation.PathVariable;
18+
import org.springframework.web.bind.annotation.RestController;
19+
import reactor.core.publisher.Mono;
20+
21+
import java.util.List;
22+
import java.util.stream.Collectors;
23+
24+
@RestController
25+
@AllArgsConstructor
26+
public class AnalysisResultUIController {
27+
28+
private final BankStatementAnalysisResultRepository bsaRepository;
29+
private final CreditBureauResultRepository cbRepository;
30+
private final ObjectMapper objectMapper;
31+
private final ObjectStorageClient storageClient;
32+
33+
@GetMapping(value = "/bsa", produces = MediaType.TEXT_HTML_VALUE)
34+
public Mono<String> getAllBsaResults() {
35+
return bsaRepository.findAll()
36+
.map(this::toPrettyJson)
37+
.collectList()
38+
.map(this::asHtml);
39+
}
40+
41+
@GetMapping(value = "/bsa/loan/{loanId}", produces = MediaType.TEXT_HTML_VALUE)
42+
public Mono<String> getBsaResultsByLoan(@PathVariable("loanId") Long loanId) {
43+
return bsaRepository.findAllByLoanId(loanId)
44+
.map(this::toPrettyJson)
45+
.collectList()
46+
.map(this::asHtml);
47+
}
48+
49+
@GetMapping(value = "/bsa/report/{id}", produces = MediaType.APPLICATION_PDF_VALUE)
50+
public Mono<ResponseEntity<byte[]>> getBsaReport(@PathVariable("id") Long id) {
51+
return bsaRepository.findById(id)
52+
.flatMap(result -> {
53+
if (result.getAttributes() == null) {
54+
return Mono.empty();
55+
}
56+
try {
57+
String reportKey = objectMapper.readTree(result.getAttributes().asString())
58+
.path("reportKey").asText(null);
59+
if (reportKey == null || reportKey.isBlank()) {
60+
return Mono.empty();
61+
}
62+
return storageClient.get(reportKey)
63+
.map(data -> ResponseEntity.ok()
64+
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"bsa-report-" + id + ".pdf\"")
65+
.contentType(MediaType.APPLICATION_PDF)
66+
.body(data));
67+
} catch (JsonProcessingException e) {
68+
return Mono.error(e);
69+
}
70+
});
71+
}
72+
73+
@GetMapping(value = "/cb", produces = MediaType.TEXT_HTML_VALUE)
74+
public Mono<String> getAllCbResults() {
75+
return cbRepository.findAll()
76+
.map(this::toPrettyJson)
77+
.collectList()
78+
.map(this::asHtml);
79+
}
80+
81+
@GetMapping(value = "/cb/loan/{loanId}", produces = MediaType.TEXT_HTML_VALUE)
82+
public Mono<String> getCbResultsByLoan(@PathVariable("loanId") Long loanId) {
83+
return cbRepository.findAllByLoanId(loanId)
84+
.map(this::toPrettyJson)
85+
.collectList()
86+
.map(this::asHtml);
87+
}
88+
89+
private String toPrettyJson(BankStatementAnalysisResult result) {
90+
return formatResult(result.getId(), result.getLoanId(), result.getAttributes());
91+
}
92+
93+
private String toPrettyJson(CreditBureauResult result) {
94+
return formatResult(result.getId(), result.getLoanId(), result.getAttributes());
95+
}
96+
97+
private String formatResult(Long id, Long loanId, Json attributes) {
98+
ObjectNode node = objectMapper.createObjectNode();
99+
node.put("id", id);
100+
node.put("loanId", loanId);
101+
if (attributes != null) {
102+
try {
103+
node.set("attributes", objectMapper.readTree(attributes.asString()));
104+
} catch (JsonProcessingException e) {
105+
node.put("attributes", attributes.asString());
106+
}
107+
}
108+
try {
109+
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
110+
} catch (JsonProcessingException e) {
111+
return "{}";
112+
}
113+
}
114+
115+
private String asHtml(List<String> jsons) {
116+
String joined = jsons.stream().collect(Collectors.joining("\n\n"));
117+
return "<html><body><pre>" + joined + "</pre></body></html>";
118+
}
119+
}
120+

0 commit comments

Comments
 (0)