From a6110322d3a027561ca6a0018030e19d84997581 Mon Sep 17 00:00:00 2001 From: Mikhail Trofimov Date: Mon, 9 Jun 2025 11:33:54 +0300 Subject: [PATCH] Added calculating debt flags logic --- .../credit_tracker/facade/SignalFacade.java | 8 +- .../mapper/indic/FlagsMapper.java | 18 ++++ .../mapper/signal/SignalMapper.java | 2 +- .../credit_tracker/service/SignalService.java | 27 +++--- .../service/indic/FlagsService.java | 84 +++++++++++++++++++ .../mybatis/mapper/indic/FlagsMapper.xml | 32 +++++++ .../mybatis/mapper/signal/SignalMapper.xml | 4 +- 7 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 src/main/java/ru/nbch/credit_tracker/mapper/indic/FlagsMapper.java create mode 100644 src/main/java/ru/nbch/credit_tracker/service/indic/FlagsService.java create mode 100644 src/main/resources/mybatis/mapper/indic/FlagsMapper.xml diff --git a/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java b/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java index 0d50dbb..e79bbd3 100644 --- a/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java +++ b/src/main/java/ru/nbch/credit_tracker/facade/SignalFacade.java @@ -112,18 +112,20 @@ public class SignalFacade { } try { + // проверка авторизации if (!authorizationService.hasAuthorization(monitoringRequest.getUserId(), monitoringRequest.getPassword())) { signalService.rejectPackage(monitoringRequest); - return getBadResponse(SignalError.ERROR_005); + return getBadResponse(SignalError.ERROR_005); // TODO расширить с возвращением отсутствия продукта } + // проверка на уникальность пакета if (signalService.isPackageNotUnique(monitoringRequest)) { signalService.rejectPackage(monitoringRequest); return getBadResponse(SignalError.ERROR_007); } - Integer packageId = signalService.registerPackage(monitoringRequest); - signalService.registerSubjects(monitoringRequest, packageId); + signalService.registerPackage(monitoringRequest); + } catch (Exception e) { log.error(e.getMessage(), e); String errorPath = failureAnswerGenerator.generateFailureAnswer(SignalError.ERROR_100); diff --git a/src/main/java/ru/nbch/credit_tracker/mapper/indic/FlagsMapper.java b/src/main/java/ru/nbch/credit_tracker/mapper/indic/FlagsMapper.java new file mode 100644 index 0000000..3baaa97 --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/mapper/indic/FlagsMapper.java @@ -0,0 +1,18 @@ +package ru.nbch.credit_tracker.mapper.indic; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import ru.nbch.credit_tracker.service.indic.FlagsService; + +import java.time.LocalDate; +import java.util.List; + +@Mapper +public interface FlagsMapper { + + List findFlagsDebt5000(@Param("fid") Integer fid); + + boolean findFlag90ByPastDueArrear(@Param("fid") Integer fid, @Param("reportedDate") LocalDate reportedDate); + + boolean findFlag90ByRuPaymt(@Param("fid") Integer fid, @Param("reportedDate") LocalDate reportedDate); +} diff --git a/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java b/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java index 0e2b096..024af3c 100644 --- a/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java +++ b/src/main/java/ru/nbch/credit_tracker/mapper/signal/SignalMapper.java @@ -19,5 +19,5 @@ public interface SignalMapper { void insertPackage(@Param("request") MonitoringRequest request, @Param("creadedAt") LocalDateTime creadedAt, @Param("status") String status); - void registerSubjectsFid(@Param("id") String id, @Param("fid") Integer fid, @Param("packageId") Integer packageId); + void registerSubjectsFidAndDebts(@Param("id") String id, @Param("fid") Integer fid, @Param("flagDebt5000") Integer flagDebt5000, @Param("flag90") Integer flag90, @Param("packageId") Integer packageId); } diff --git a/src/main/java/ru/nbch/credit_tracker/service/SignalService.java b/src/main/java/ru/nbch/credit_tracker/service/SignalService.java index 99d5e4c..a1f955a 100644 --- a/src/main/java/ru/nbch/credit_tracker/service/SignalService.java +++ b/src/main/java/ru/nbch/credit_tracker/service/SignalService.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Service; import ru.nbch.credit_tracker.entities.monitoring_request.MonitoringRequest; import ru.nbch.credit_tracker.enums.Status; import ru.nbch.credit_tracker.mapper.signal.SignalMapper; +import ru.nbch.credit_tracker.service.indic.FlagsService; import ru.nbch.credit_tracker.service.indic.PhoneService; import java.time.LocalDateTime; @@ -14,32 +15,34 @@ public class SignalService { private final SignalMapper mapper; private final PhoneService phoneService; + private final FlagsService flagsService; - public SignalService(SignalMapper mapper, PhoneService phoneService) { + public SignalService(SignalMapper mapper, + PhoneService phoneService, + FlagsService flagsService) { this.mapper = mapper; this.phoneService = phoneService; + this.flagsService = flagsService; } public boolean isPackageNotUnique(MonitoringRequest request) { String userId = request.getUserId(); - return mapper.isPackageNotUnique(userId.substring(0, 6),request.getPackageName()); + return mapper.isPackageNotUnique(userId.substring(0, 6), request.getPackageName()); } - public Integer registerPackage(MonitoringRequest request) { + public void registerPackage(MonitoringRequest request) { Integer packageId = mapper.registerPackage(request, LocalDateTime.now(), Status.PROCESSING.name()); mapper.registerSubjects(request.getSubjects().getSubject(), packageId); - return packageId; + List fidsPhoneDataList = phoneService.findFidsPhoneData(request.getSubjects().getSubject()); + fidsPhoneDataList.forEach(phoneData -> { + FlagsService.FlagsFidData flagsData = flagsService.findFlags(phoneData.getFid()); + mapper.registerSubjectsFidAndDebts(phoneData.getId(), phoneData.getFid(), flagsData.getFlagDebt5000(), flagsData.getFlag90days(), packageId); + }); + } public void rejectPackage(MonitoringRequest request) { - mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name()); - } - - public void registerSubjects(MonitoringRequest request, Integer packageId) { - List fidsPhoneDataList = phoneService.findFidsPhoneData(request.getSubjects().getSubject()); - fidsPhoneDataList.forEach(phoneData -> { - mapper.registerSubjectsFid(phoneData.getId(), phoneData.getFid(), packageId); - }); + mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name()); } } diff --git a/src/main/java/ru/nbch/credit_tracker/service/indic/FlagsService.java b/src/main/java/ru/nbch/credit_tracker/service/indic/FlagsService.java new file mode 100644 index 0000000..1aab3de --- /dev/null +++ b/src/main/java/ru/nbch/credit_tracker/service/indic/FlagsService.java @@ -0,0 +1,84 @@ +package ru.nbch.credit_tracker.service.indic; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.stereotype.Service; +import ru.nbch.credit_tracker.mapper.indic.FlagsMapper; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +public class FlagsService { + + private final FlagsMapper mapper; + + public FlagsService(FlagsMapper mapper) { + this.mapper = mapper; + } + + public FlagsFidData findFlags(Integer fid) { + FlagsFidData flagsData = new FlagsFidData(); + flagsData.setFlagDebt5000(calcFlag5000(fid)); + flagsData.setFlag90days(calcFlag90Days(fid)); + return flagsData; + } + /** + * По FID из RU_PASTDUEARREAR выбираются все уникальные ACC_SERIAL_NUM с максимальной датой REPORTED_DT. + * Если по хотя бы одной такой записи AMT_PAST_DUE > 5000, то флаг устанавливается в 1. + * Если ни по одному счёту условие не выполняется или счетов вообще не найдено, флаг = 0. + */ + private Integer calcFlag5000(Integer fid) { + List dataList = mapper.findFlagsDebt5000(fid).stream() + .collect(Collectors.groupingBy( + Flag5000FidData::getAccSerialNum, + Collectors.maxBy(Comparator.comparing(Flag5000FidData::getReportedDate)) + )) + .values() + .stream() + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); + + if (!dataList.isEmpty() && dataList.stream().anyMatch(item -> item != null && item.getAmountPastDue().compareTo(BigDecimal.valueOf(5000)) > 0)) { + return 1; + } else { + return 0; + } + } + + /** + * Флаг = 1, если выполняется хотя бы одно из условий: + * В INDIC.RU_PASTDUEARREAR или RU_PAYMT у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев. + * Если ни по одной записи условия не выполняются или записей вообще не найдено, флаг = 0. + */ + private Integer calcFlag90Days(Integer fid) { + LocalDate yearAgo = LocalDate.now().minusYears(1); + if (mapper.findFlag90ByPastDueArrear(fid, yearAgo)) { + return 1; + } else if (mapper.findFlag90ByRuPaymt(fid, yearAgo)) { + return 1; + } + return 0; + } + + @Getter + @Setter + public static class FlagsFidData { + private Integer flagDebt5000; + private Integer flag90days; + } + + @Getter + @Setter + public static class Flag5000FidData { + private BigInteger accSerialNum; + private LocalDate reportedDate; + private BigDecimal amountPastDue; + } +} diff --git a/src/main/resources/mybatis/mapper/indic/FlagsMapper.xml b/src/main/resources/mybatis/mapper/indic/FlagsMapper.xml new file mode 100644 index 0000000..4764aa6 --- /dev/null +++ b/src/main/resources/mybatis/mapper/indic/FlagsMapper.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mybatis/mapper/signal/SignalMapper.xml b/src/main/resources/mybatis/mapper/signal/SignalMapper.xml index f3ac377..04e1ff0 100644 --- a/src/main/resources/mybatis/mapper/signal/SignalMapper.xml +++ b/src/main/resources/mybatis/mapper/signal/SignalMapper.xml @@ -30,9 +30,9 @@ - + UPDATE signals_phone_fid_map - SET fid = #{fid} + SET fid = #{fid}, flag_debt5000 = #{flagDebt5000}, flag_90_12 = #{flag90} WHERE package_id = #{packageId} AND subject_id = #{id}