Skip to content

Commit c472f79

Browse files
committed
Decode pdf from base64 and add controller endpoint to display report
1 parent 294190d commit c472f79

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

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

Lines changed: 17 additions & 5 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;
@@ -66,15 +66,27 @@ private Mono<Void> sendRequest(String base64, DocumentDataV1 document, Aggregato
6666
.header("token", token)
6767
.bodyValue(body)
6868
.retrieve()
69-
.bodyToMono(String.class)
69+
.bodyToMono(AryaBsaResponse.class)
7070
.flatMap(resp -> saveResult(resp, aggregator))
7171
.doOnError(err -> log.error("Arya BSA request failed", err))
7272
.then(updateAggregatorStatus(aggregator));
7373
}
7474

75-
private Mono<BankStatementAnalysisResult> saveResult(String resp, Aggregator aggregator) {
76-
BankStatementAnalysisResult result = new BankStatementAnalysisResult(null, aggregator.getLoanId(), Json.of(resp));
77-
return resultRepository.save(result);
75+
private Mono<BankStatementAnalysisResult> saveResult(AryaBsaResponse resp, Aggregator aggregator) {
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);
7890
}
7991

8092
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/controller/AnalysisResultUIController.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
import com.fasterxml.jackson.databind.node.ObjectNode;
66
import io.r2dbc.postgresql.codec.Json;
77
import lombok.AllArgsConstructor;
8+
import org.mifos.loanrisk.document.storage.ObjectStorageClient;
89
import org.mifos.loanrisk.external.bsa.domain.BankStatementAnalysisResult;
910
import org.mifos.loanrisk.external.bsa.repository.BankStatementAnalysisResultRepository;
1011
import org.mifos.loanrisk.external.cb.domain.CreditBureauResult;
1112
import org.mifos.loanrisk.external.cb.repository.CreditBureauResultRepository;
13+
import org.springframework.http.HttpHeaders;
1214
import org.springframework.http.MediaType;
15+
import org.springframework.http.ResponseEntity;
1316
import org.springframework.web.bind.annotation.GetMapping;
1417
import org.springframework.web.bind.annotation.PathVariable;
1518
import org.springframework.web.bind.annotation.RestController;
@@ -25,6 +28,7 @@ public class AnalysisResultUIController {
2528
private final BankStatementAnalysisResultRepository bsaRepository;
2629
private final CreditBureauResultRepository cbRepository;
2730
private final ObjectMapper objectMapper;
31+
private final ObjectStorageClient storageClient;
2832

2933
@GetMapping(value = "/bsa", produces = MediaType.TEXT_HTML_VALUE)
3034
public Mono<String> getAllBsaResults() {
@@ -42,6 +46,30 @@ public Mono<String> getBsaResultsByLoan(@PathVariable("loanId") Long loanId) {
4246
.map(this::asHtml);
4347
}
4448

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+
4573
@GetMapping(value = "/cb", produces = MediaType.TEXT_HTML_VALUE)
4674
public Mono<String> getAllCbResults() {
4775
return cbRepository.findAll()

0 commit comments

Comments
 (0)