From 02541eed6c6ff8cb8d69fa5b39a88223ce61a5d9 Mon Sep 17 00:00:00 2001 From: Nitesh Yadav Date: Thu, 30 Jul 2026 10:33:33 +0530 Subject: [PATCH] feat(sanctions): expose the loaded list's data-currency date on every screening result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screening only ever told a caller whether a name matched and when the check ran — not which dated snapshot of the UN Security Council list it ran against. Added SanctionsEntryRepository.findListLastLoadedOn() (MAX(createdDate) over active entries) and threaded it through SanctionsScreeningResult as listDataAsOf, so the frontend can show "List Data As Of: " alongside "Screened On". --- .../domain/SanctionsEntryRepository.java | 9 +++++++++ .../sanctions/data/SanctionsScreeningResult.java | 15 ++++++++++----- .../service/SanctionsScreeningServiceImpl.java | 8 +++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/sanctions/domain/SanctionsEntryRepository.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/sanctions/domain/SanctionsEntryRepository.java index 0dbe5c012..22a7a11f6 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/sanctions/domain/SanctionsEntryRepository.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/sanctions/domain/SanctionsEntryRepository.java @@ -18,7 +18,9 @@ */ package org.apache.fineract.portfolio.sanctions.domain; +import java.time.OffsetDateTime; import java.util.List; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -40,4 +42,11 @@ public interface SanctionsEntryRepository extends JpaRepository findListLastLoadedOn(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/data/SanctionsScreeningResult.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/data/SanctionsScreeningResult.java index 3da421b0c..ac33a4ad9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/data/SanctionsScreeningResult.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/data/SanctionsScreeningResult.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.sanctions.data; +import java.time.OffsetDateTime; import java.util.List; /** @@ -32,10 +33,11 @@ public final class SanctionsScreeningResult { private final String message; private final int matchCount; private final List matches; + private final OffsetDateTime listDataAsOf; private SanctionsScreeningResult(final Long screeningLogId, final String screenedName, final boolean matchFound, final String status, final String message, final int matchCount, - final List matches) { + final List matches, final OffsetDateTime listDataAsOf) { this.screeningLogId = screeningLogId; this.screenedName = screenedName; this.matchFound = matchFound; @@ -43,20 +45,22 @@ public final class SanctionsScreeningResult { this.message = message; this.matchCount = matchCount; this.matches = matches; + this.listDataAsOf = listDataAsOf; } public static SanctionsScreeningResult matched(final Long screeningLogId, final String screenedName, - final List matches) { + final List matches, final OffsetDateTime listDataAsOf) { return new SanctionsScreeningResult(screeningLogId, screenedName, true, "FLAGGED", "Potential match found in UN Security Council consolidated sanctions list. " + "Manual review required before proceeding.", - matches.size(), matches); + matches.size(), matches, listDataAsOf); } - public static SanctionsScreeningResult clear(final Long screeningLogId, final String screenedName) { + public static SanctionsScreeningResult clear(final Long screeningLogId, final String screenedName, + final OffsetDateTime listDataAsOf) { return new SanctionsScreeningResult(screeningLogId, screenedName, false, "CLEAR", "No match found in UN Security Council consolidated sanctions list.", - 0, List.of()); + 0, List.of(), listDataAsOf); } public Long getScreeningLogId() { return screeningLogId; } @@ -66,4 +70,5 @@ public final class SanctionsScreeningResult { public String getMessage() { return message; } public int getMatchCount() { return matchCount; } public List getMatches() { return matches; } + public OffsetDateTime getListDataAsOf() { return listDataAsOf; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/service/SanctionsScreeningServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/service/SanctionsScreeningServiceImpl.java index 111e7003e..5fd41625d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/service/SanctionsScreeningServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/sanctions/service/SanctionsScreeningServiceImpl.java @@ -18,6 +18,7 @@ */ package org.apache.fineract.portfolio.sanctions.service; +import java.time.OffsetDateTime; import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; @@ -54,18 +55,19 @@ public class SanctionsScreeningServiceImpl implements SanctionsScreeningService final Long clientId, final String ipAddress) { if (name == null || name.isBlank()) { final Long logId = saveLog(name, "CLEAR", 0, null, null, source, clientId, ipAddress); - return SanctionsScreeningResult.clear(logId, name); + return SanctionsScreeningResult.clear(logId, name, sanctionsEntryRepository.findListLastLoadedOn().orElse(null)); } final String trimmedName = name.trim(); LOG.info("Screening name against sanctions list: {}", trimmedName); + final OffsetDateTime listDataAsOf = sanctionsEntryRepository.findListLastLoadedOn().orElse(null); final List matches = sanctionsEntryRepository.searchByNameOrAlias(trimmedName); if (matches.isEmpty()) { LOG.info("No sanctions match found for: {}", trimmedName); final Long logId = saveLog(trimmedName, "CLEAR", 0, null, null, source, clientId, ipAddress); - return SanctionsScreeningResult.clear(logId, trimmedName); + return SanctionsScreeningResult.clear(logId, trimmedName, listDataAsOf); } LOG.warn("Sanctions match found for '{}': {} potential match(es)", trimmedName, matches.size()); @@ -84,7 +86,7 @@ public class SanctionsScreeningServiceImpl implements SanctionsScreeningService final Long logId = saveLog(trimmedName, "FLAGGED", matches.size(), matchedEntryIds, matchedNames, source, clientId, ipAddress); - return SanctionsScreeningResult.matched(logId, trimmedName, matchDataList); + return SanctionsScreeningResult.matched(logId, trimmedName, matchDataList, listDataAsOf); } @Override