Added calculating debt flags logic

This commit is contained in:
Mikhail Trofimov 2025-06-09 11:33:54 +03:00
parent 122c6d2419
commit a6110322d3
7 changed files with 157 additions and 18 deletions

View file

@ -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);

View file

@ -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<FlagsService.Flag5000FidData> 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);
}

View file

@ -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);
}

View file

@ -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<PhoneService.FidsPhoneData> 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<PhoneService.FidsPhoneData> fidsPhoneDataList = phoneService.findFidsPhoneData(request.getSubjects().getSubject());
fidsPhoneDataList.forEach(phoneData -> {
mapper.registerSubjectsFid(phoneData.getId(), phoneData.getFid(), packageId);
});
mapper.insertPackage(request, LocalDateTime.now(), Status.REJECTED.name());
}
}

View file

@ -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<Flag5000FidData> 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;
}
}

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ru.nbch.credit_tracker.mapper.indic.FlagsMapper">
<resultMap id="Flag5000FidDataResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$Flag5000FidData">
<result property="accSerialNum" column="ACC_SERIAL_NUM" />
<result property="reportedDate" column="REPORTED_DT" />
<result property="amountPastDue" column="AMT_PAST_DUE" />
</resultMap>
<select id="findFlagsDebt5000" resultMap="Flag5000FidDataResultMap">
SELECT ACC_SERIAL_NUM, AMT_PAST_DUE, REPORTED_DT
FROM RU_PASTDUEARREAR
WHERE FID = #{fid}
ORDER BY REPORTED_DT DESC
</select>
<select id="findFlag90ByPastDueArrear">
SELECT COUNT(*) > 0
FROM RU_PASTDUEARREAR
WHERE FID = #{fid} AND DAYS_PAST_DUE >= 90 AND REPORTED_DT >= #{reportedDate}
</select>
<select id="findFlag90ByRuPaymt">
SELECT COUNT(*) > 0
FROM RU_PAYMT
WHERE FID = #{fid} AND DAYS_PAST_DUE >= 90 AND REPORTED_DT >= #{reportedDate}
</select>
</mapper>

View file

@ -30,9 +30,9 @@
</foreach>
</insert>
<update id="registerSubjectsFid">
<update id="registerSubjectsFidAndDebts">
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}
</update>