Skip to content

Commit 91bc033

Browse files
committed
MX-362: Implement online person enrollment KYC for the Mifos Self Service Plugin
1 parent c29bc12 commit 91bc033

7 files changed

Lines changed: 135 additions & 6 deletions

File tree

src/main/java/org/apache/fineract/kyc/api/KycVerificationApiResource.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import jakarta.ws.rs.Consumes;
1313
import jakarta.ws.rs.GET;
1414
import jakarta.ws.rs.HeaderParam;
15+
import jakarta.ws.rs.NotFoundException;
1516
import jakarta.ws.rs.POST;
1617
import jakarta.ws.rs.Path;
1718
import jakarta.ws.rs.PathParam;
@@ -85,4 +86,18 @@ public ResponseEntity<List<KycVerification>> listByClient(
8586
}
8687
return ResponseEntity.ok(verifications);
8788
}
89+
90+
@GET
91+
@Path("/clients/{clientId}/verifications/{id}")
92+
@Produces({ MediaType.APPLICATION_JSON })
93+
@Operation(summary = "Get full KYC verification details by ID")
94+
public ResponseEntity<KycVerification> getVerificationById(
95+
@PathParam("id") @Parameter(description = "Verification ID") final Long id) {
96+
97+
// Full detail endpoint — returns the complete nested tree
98+
final KycVerification verification = kycVerificationService.findByIdWithDetails(id)
99+
.orElseThrow(() -> new NotFoundException("KYC verification not found with id: " + id));
100+
101+
return ResponseEntity.ok(verification);
102+
}
88103
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Copyright since 2026 Mifos Initiative
3+
*
4+
* <p>This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy
5+
* of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.apache.fineract.kyc.data;
8+
9+
import com.fasterxml.jackson.annotation.JsonInclude;
10+
import java.time.OffsetDateTime;
11+
12+
@JsonInclude(JsonInclude.Include.NON_NULL)
13+
public class KycVerificationSummaryData {
14+
15+
private Long id;
16+
private Long clientId;
17+
private String sessionId;
18+
private String workflowId;
19+
private Integer workflowVersion;
20+
private String webhookType;
21+
private String kycStatus;
22+
private Long kycTimestamp;
23+
private String decisionStatus;
24+
private OffsetDateTime decisionCreatedAt;
25+
private OffsetDateTime createdOnUtc;
26+
27+
public KycVerificationSummaryData() {}
28+
29+
public KycVerificationSummaryData(final Long id,
30+
final Long clientId,
31+
final String sessionId,
32+
final String workflowId,
33+
final Integer workflowVersion,
34+
final String webhookType,
35+
final String kycStatus,
36+
final Long kycTimestamp,
37+
final String decisionStatus,
38+
final OffsetDateTime decisionCreatedAt,
39+
final OffsetDateTime createdOnUtc) {
40+
this.id = id;
41+
this.clientId = clientId;
42+
this.sessionId = sessionId;
43+
this.workflowId = workflowId;
44+
this.workflowVersion = workflowVersion;
45+
this.webhookType = webhookType;
46+
this.kycStatus = kycStatus;
47+
this.kycTimestamp = kycTimestamp;
48+
this.decisionStatus = decisionStatus;
49+
this.decisionCreatedAt = decisionCreatedAt;
50+
this.createdOnUtc = createdOnUtc;
51+
}
52+
53+
// Getters
54+
public Long getId() { return id; }
55+
public Long getClientId() { return clientId; }
56+
public String getSessionId() { return sessionId; }
57+
public String getWorkflowId() { return workflowId; }
58+
public Integer getWorkflowVersion() { return workflowVersion; }
59+
public String getWebhookType() { return webhookType; }
60+
public String getKycStatus() { return kycStatus; }
61+
public Long getKycTimestamp() { return kycTimestamp; }
62+
public String getDecisionStatus() { return decisionStatus; }
63+
public OffsetDateTime getDecisionCreatedAt() { return decisionCreatedAt; }
64+
public OffsetDateTime getCreatedOnUtc() { return createdOnUtc; }
65+
}

src/main/java/org/apache/fineract/kyc/domain/KycAmlScreening.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ public class KycAmlScreening {
7272
@Column(name = "last_modified_on_utc", nullable = false)
7373
private OffsetDateTime lastModifiedOnUtc;
7474

75-
@JsonIgnore
7675
@OneToMany(mappedBy = "amlScreening", cascade = CascadeType.ALL,
7776
fetch = FetchType.LAZY, orphanRemoval = true)
7877
private List<KycAmlHit> hits = new ArrayList<>();

src/main/java/org/apache/fineract/kyc/domain/KycDecision.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,18 @@ public class KycDecision {
6060
@Column(name = "last_modified_on_utc", nullable = false)
6161
private OffsetDateTime lastModifiedOnUtc;
6262

63-
@JsonIgnore
6463
@OneToMany(mappedBy = "kycDecision", cascade = CascadeType.ALL,
6564
fetch = FetchType.LAZY, orphanRemoval = true)
6665
private List<KycDecisionFeature> features = new ArrayList<>();
6766

68-
@JsonIgnore
6967
@OneToMany(mappedBy = "kycDecision", cascade = CascadeType.ALL,
7068
fetch = FetchType.LAZY, orphanRemoval = true)
7169
private List<KycFaceMatch> faceMatches = new ArrayList<>();
7270

73-
@JsonIgnore
7471
@OneToMany(mappedBy = "kycDecision", cascade = CascadeType.ALL,
7572
fetch = FetchType.LAZY, orphanRemoval = true)
7673
private List<KycIdVerification> idVerifications = new ArrayList<>();
7774

78-
@JsonIgnore
7975
@OneToMany(mappedBy = "kycDecision", cascade = CascadeType.ALL,
8076
fetch = FetchType.LAZY, orphanRemoval = true)
8177
private List<KycAmlScreening> amlScreenings = new ArrayList<>();

src/main/java/org/apache/fineract/kyc/domain/KycVerification.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@
1313
@Table(name = "m_client_kyc_verification")
1414
public class KycVerification {
1515

16+
/**
17+
* @return the createdOnUtc
18+
*/
19+
public OffsetDateTime getCreatedOnUtc() {
20+
return createdOnUtc;
21+
}
22+
23+
/**
24+
* @param createdOnUtc the createdOnUtc to set
25+
*/
26+
public void setCreatedOnUtc(OffsetDateTime createdOnUtc) {
27+
this.createdOnUtc = createdOnUtc;
28+
}
29+
1630
@Id
1731
@GeneratedValue(strategy = GenerationType.IDENTITY)
1832
private Long id;
@@ -86,7 +100,7 @@ public static KycVerification create(final Long clientId,
86100
v.createdBy = createdBy;
87101
v.lastModifiedBy = createdBy;
88102
final OffsetDateTime now = OffsetDateTime.now();
89-
v.createdOnUtc = now;
103+
v.setCreatedOnUtc(now);
90104
v.lastModifiedOnUtc = now;
91105
return v;
92106
}

src/main/java/org/apache/fineract/kyc/service/KycVerificationService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import java.util.List;
1111
import java.util.Optional;
12+
import org.apache.fineract.kyc.data.KycVerificationSummaryData;
1213
import org.apache.fineract.kyc.data.KycWebhookPayload;
1314
import org.apache.fineract.kyc.domain.KycVerification;
1415

@@ -30,4 +31,8 @@ public interface KycVerificationService {
3031
List<KycVerification> findByClientId(Long clientId);
3132

3233
List<KycVerification> findByClientIdAndStatus(Long clientId, Optional<String> status);
34+
35+
List<KycVerificationSummaryData> findSummaryByClientId(Long clientId);
36+
37+
List<KycVerificationSummaryData> findSummaryByClientIdAndStatus(Long clientId, Optional<String> status);
3338
}

src/main/java/org/apache/fineract/kyc/service/KycVerificationServiceImpl.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.time.format.DateTimeFormatter;
1717
import java.util.List;
1818
import java.util.Optional;
19+
import org.apache.fineract.kyc.data.KycVerificationSummaryData;
1920
import org.apache.fineract.kyc.data.KycWebhookPayload;
2021
import org.apache.fineract.kyc.data.KycWebhookPayload.AmlScreening;
2122
import org.apache.fineract.kyc.data.KycWebhookPayload.Decision;
@@ -245,4 +246,38 @@ private String serializeToJson(final Object obj) {
245246
return obj.toString();
246247
}
247248
}
249+
250+
@Override
251+
@Transactional(readOnly = true)
252+
public List<KycVerificationSummaryData> findSummaryByClientId(final Long clientId) {
253+
return kycVerificationRepository.findByClientIdOrderByCreatedOnUtcDesc(clientId)
254+
.stream()
255+
.map(this::toSummaryData)
256+
.toList();
257+
}
258+
259+
@Override
260+
@Transactional(readOnly = true)
261+
public List<KycVerificationSummaryData> findSummaryByClientIdAndStatus(final Long clientId, final Optional<String> status) {
262+
return kycVerificationRepository.findByClientIdAndKycStatus(clientId, status)
263+
.stream()
264+
.map(this::toSummaryData)
265+
.toList();
266+
}
267+
268+
private KycVerificationSummaryData toSummaryData(final KycVerification v) {
269+
return new KycVerificationSummaryData(
270+
v.getId(),
271+
v.getClientId(),
272+
v.getSessionId(),
273+
v.getWorkflowId(),
274+
v.getWorkflowVersion(),
275+
v.getWebhookType(),
276+
v.getKycStatus(),
277+
v.getKycTimestamp(),
278+
v.getDecision() != null ? v.getDecision().getDecisionStatus() : null,
279+
v.getDecision() != null ? v.getDecision().getDecisionCreatedAt() : null,
280+
v.getCreatedOnUtc()
281+
);
282+
}
248283
}

0 commit comments

Comments
 (0)