Added test variant of counting flags 500 and 90_days from RU_PASTDUEARREAR
This commit is contained in:
parent
021d7e8615
commit
c245790eb5
6 changed files with 281 additions and 188 deletions
|
|
@ -8,9 +8,9 @@ server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b
|
||||||
# datasources
|
# datasources
|
||||||
# indic
|
# indic
|
||||||
ct.indic-data-source-settings.driver=com.ibm.db2.jcc.DB2Driver
|
ct.indic-data-source-settings.driver=com.ibm.db2.jcc.DB2Driver
|
||||||
ct.indic-data-source-settings.url=${DB_URL_INDIC:jdbc:db2://10.230.227.101:2668/cprosd22:currentSchema=INDIC;}
|
ct.indic-data-source-settings.url=${DB_URL_INDIC:jdbc:db2://10.230.227.100:2668/cprosd22:currentSchema=INDIC;}
|
||||||
ct.indic-data-source-settings.username=${USERNAME_INDIC:tester}
|
ct.indic-data-source-settings.username=${USERNAME_INDIC:ros9appl}
|
||||||
ct.indic-data-source-settings.password=${PASSWORD_INDIC:tester}
|
ct.indic-data-source-settings.password=${PASSWORD_INDIC:R0s9Appl}
|
||||||
|
|
||||||
# signal
|
# signal
|
||||||
ct.signal-data-source-settings.driver=org.postgresql.Driver
|
ct.signal-data-source-settings.driver=org.postgresql.Driver
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,31 @@ package ru.nbch.credit_tracker;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import ru.nbch.credit_tracker.service.MonitoringService;
|
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
||||||
import ru.nbch.credit_tracker.service.UpdateProcessingPackagesService;
|
|
||||||
import ru.nbch.credit_tracker.service.UpdatingFlagsService;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class CreditTrackerApplication {
|
public class CreditTrackerApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ConfigurableApplicationContext ctx = SpringApplication.run(CreditTrackerApplication.class, args);
|
ConfigurableApplicationContext ctx = SpringApplication.run(CreditTrackerApplication.class, args);
|
||||||
UpdateProcessingPackagesService updateProcessingPackagesService = ctx.getBean(UpdateProcessingPackagesService.class);
|
List<Integer> fids = new ArrayList<>();
|
||||||
MonitoringService monitoringService = ctx.getBean(MonitoringService.class);
|
fids.add(11085548);
|
||||||
UpdatingFlagsService updatingFlagsService = ctx.getBean(UpdatingFlagsService.class);
|
fids.add(16442833);
|
||||||
updateProcessingPackagesService.run();
|
fids.add(109128766);
|
||||||
monitoringService.run();
|
fids.add(115150769);
|
||||||
updatingFlagsService.run();
|
fids.add(16442929);
|
||||||
|
fids.add(114429070);
|
||||||
|
fids.add(108696892);
|
||||||
|
ctx.getBean(FlagsService.class).test(fids);
|
||||||
|
// UpdateProcessingPackagesService updateProcessingPackagesService = ctx.getBean(UpdateProcessingPackagesService.class);
|
||||||
|
// MonitoringService monitoringService = ctx.getBean(MonitoringService.class);
|
||||||
|
// UpdatingFlagsService updatingFlagsService = ctx.getBean(UpdatingFlagsService.class);
|
||||||
|
// updateProcessingPackagesService.run();
|
||||||
|
// monitoringService.run();
|
||||||
|
// updatingFlagsService.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,7 @@ public interface FlagsMapper {
|
||||||
|
|
||||||
List<FlagsService.FlagFidData> findFlag90ByRuPaymt(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
List<FlagsService.FlagFidData> findFlag90ByRuPaymt(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
||||||
|
|
||||||
|
List<FlagsService.RuPastDuarearData> findRuPastDuarearData(@Param("fids") List<Integer> fids);
|
||||||
List<FlagsService.Debt5000Data> findFlagsDebt5000NewWithOrderBy(@Param("fids") List<Integer> fids);
|
|
||||||
|
|
||||||
|
|
||||||
List<FlagsService.Flag90DaysData> findFlag90ByPastDueArrearNewWithOrderBy(@Param("fids") List<Integer> fids);
|
|
||||||
|
|
||||||
|
|
||||||
List<FlagsService.Flag90DaysData> findFlag90ByRuPaymtNewWithOrderBy(@Param("fids") List<Integer> fids);
|
List<FlagsService.Flag90DaysData> findFlag90ByRuPaymtNewWithOrderBy(@Param("fids") List<Integer> fids);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package ru.nbch.credit_tracker.service.indic;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
@ -11,9 +12,7 @@ import ru.nbch.credit_tracker.mapper.indic.FlagsMapper;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class FlagsService {
|
public class FlagsService {
|
||||||
|
|
@ -25,6 +24,88 @@ public class FlagsService {
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void test(List<Integer> fids) {
|
||||||
|
Map<Integer, Integer> oldFlags5000 = calcFlag5000(fids);
|
||||||
|
Map<Integer, Integer> oldFlags90 = calcFlag90DaysByPastDueArrear(fids);
|
||||||
|
|
||||||
|
fids.sort(Comparator.naturalOrder());
|
||||||
|
|
||||||
|
Map<Integer, Integer> flag5000Map = new HashMap<>();
|
||||||
|
Map<Integer, Integer> flag90Days = new HashMap<>();
|
||||||
|
findFlags5000(fids, flag5000Map, flag90Days);
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, Integer> flag : flag5000Map.entrySet()) {
|
||||||
|
if(!flag.getValue().equals(oldFlags5000.get(flag.getKey()))) {
|
||||||
|
String error = "New: "+flag.getKey() + " = " + flag.getValue() + "\n" +"Old: " + flag.getKey() + " = " + oldFlags5000.get(flag.getKey());
|
||||||
|
throw new AssertionError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, Integer> flag : flag90Days.entrySet()) {
|
||||||
|
if(!flag.getValue().equals(oldFlags90.get(flag.getKey()))) {
|
||||||
|
String error = "New: "+flag.getKey() + " = " + flag.getValue() + "\n" +"Old: " + flag.getKey() + " = " + oldFlags90.get(flag.getKey());
|
||||||
|
throw new AssertionError(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findFlags5000(List<Integer> fids, Map<Integer, Integer> flag5000Map, Map<Integer, Integer> flag90Days) {
|
||||||
|
List<RuPastDuarearData> ruPastDuarearDataList = mapper.findRuPastDuarearData(fids);
|
||||||
|
ruPastDuarearDataList.sort(Comparator.comparing(FlagsService.RuPastDuarearData::getFid) // сортируем сначала по фиду
|
||||||
|
.thenComparing(FlagsService.RuPastDuarearData::getReportedDate, Comparator.reverseOrder())); // Затем сортируем по REPORTED_DT по убыванию
|
||||||
|
|
||||||
|
LocalDate yearAgo = LocalDate.parse("2024-09-09");
|
||||||
|
|
||||||
|
for (Integer fid : fids) {
|
||||||
|
Iterator<RuPastDuarearData> iterator = ruPastDuarearDataList.iterator();
|
||||||
|
BigInteger prevAccSerialNum = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
FlagsService.RuPastDuarearData data = iterator.next();
|
||||||
|
|
||||||
|
if (fid.equals(data.getFid())) {
|
||||||
|
if (flag5000Map.get(fid) == null) { // Первая запись в списке с макс REPORTED_DT. Нас интересует только она для флага 5000
|
||||||
|
if (prevAccSerialNum == null || !prevAccSerialNum.equals(data.getAccSerialNum())) {
|
||||||
|
if (data.getAmtPastDue() != null && data.getAmtPastDue().compareTo(BigDecimal.valueOf(5000)) >= 0) {
|
||||||
|
flag5000Map.put(fid, 1);
|
||||||
|
} else {
|
||||||
|
flag5000Map.put(fid, 0);
|
||||||
|
}
|
||||||
|
prevAccSerialNum = data.getAccSerialNum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag90Days.get(fid) != null && flag90Days.get(fid) == 1) {
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag90Days.get(fid) == null || flag90Days.get(fid) == 0) {
|
||||||
|
if (data.getDaysPastDue() != null) {
|
||||||
|
boolean has90daysFlag = data.getDaysPastDue().compareTo(BigInteger.valueOf(90)) >= 0 && !data.getReportedDate().isBefore(yearAgo);
|
||||||
|
if (has90daysFlag) {
|
||||||
|
flag90Days.put(fid, 1);
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
flag90Days.put(fid, 0);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag5000Map.get(fid) == null) {
|
||||||
|
flag5000Map.put(fid, 0);
|
||||||
|
}
|
||||||
|
if (flag90Days.get(fid) == null) {
|
||||||
|
flag90Days.put(fid, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Map<Integer, FlagsData> findFlags(List<Integer> fids) {
|
public Map<Integer, FlagsData> findFlags(List<Integer> fids) {
|
||||||
if (fids.isEmpty()) {
|
if (fids.isEmpty()) {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
|
|
@ -32,11 +113,8 @@ public class FlagsService {
|
||||||
List<Integer> distinctFids = fids.stream().distinct().toList();
|
List<Integer> distinctFids = fids.stream().distinct().toList();
|
||||||
log.debug("Fids count: {}", distinctFids.size());
|
log.debug("Fids count: {}", distinctFids.size());
|
||||||
Map<Integer, Integer> flags5000 = calcFlag5000(distinctFids);
|
Map<Integer, Integer> flags5000 = calcFlag5000(distinctFids);
|
||||||
calcFlag500Test(distinctFids);
|
|
||||||
Map<Integer, Integer> flags90DaysByPastDueArrear = calcFlag90DaysByPastDueArrear(distinctFids);
|
Map<Integer, Integer> flags90DaysByPastDueArrear = calcFlag90DaysByPastDueArrear(distinctFids);
|
||||||
calcFlag90DaysByPastDueArrearTest(distinctFids);
|
|
||||||
Map<Integer, Integer> flags90DaysByRuPaymt = calcFlag90DaysByRuPaymt(distinctFids);
|
Map<Integer, Integer> flags90DaysByRuPaymt = calcFlag90DaysByRuPaymt(distinctFids);
|
||||||
calcFlag90DaysByRuPaymtTest(distinctFids);
|
|
||||||
|
|
||||||
Map<Integer, FlagsData> result = new HashMap<>();
|
Map<Integer, FlagsData> result = new HashMap<>();
|
||||||
fids.forEach(fid -> {
|
fids.forEach(fid -> {
|
||||||
|
|
@ -71,12 +149,6 @@ public class FlagsService {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcFlag500Test(List<Integer> fids) {
|
|
||||||
log.debug("Start findFlagsDebt5000NewWithOrderBy");
|
|
||||||
mapper.findFlagsDebt5000NewWithOrderBy(fids);
|
|
||||||
log.debug("Complete findFlagsDebt5000NewWithOrderBy");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Флаг = 1, если выполняется хотя бы одно из условий:
|
* Флаг = 1, если выполняется хотя бы одно из условий:
|
||||||
* В INDIC.RU_PASTDUEARREAR или RU_PAYMT у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
* В INDIC.RU_PASTDUEARREAR или RU_PAYMT у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
||||||
|
|
@ -91,12 +163,6 @@ public class FlagsService {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcFlag90DaysByPastDueArrearTest(List<Integer> fids) {
|
|
||||||
log.debug("Start findFlag90ByPastDueArrearNewWithOrderBy");
|
|
||||||
mapper.findFlag90ByPastDueArrearNewWithOrderBy(fids);
|
|
||||||
log.debug("Complete findFlag90ByPastDueArrearNewWithOrderBy");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<Integer, Integer> calcFlag90DaysByRuPaymt(List<Integer> fids) {
|
private Map<Integer, Integer> calcFlag90DaysByRuPaymt(List<Integer> fids) {
|
||||||
log.debug("Start calculating flag 90 by ruPaymt");
|
log.debug("Start calculating flag 90 by ruPaymt");
|
||||||
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
||||||
|
|
@ -106,12 +172,6 @@ public class FlagsService {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcFlag90DaysByRuPaymtTest(List<Integer> fids) {
|
|
||||||
log.debug("Start findFlag90ByRuPaymtNewWithOrderBy");
|
|
||||||
mapper.findFlag90ByRuPaymtNewWithOrderBy(fids);
|
|
||||||
log.debug("Complete findFlag90ByRuPaymtNewWithOrderBy");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<Integer, Integer> makeFidFlagMapByRs(List<Integer> fids, List<FlagFidData> rows) {
|
private Map<Integer, Integer> makeFidFlagMapByRs(List<Integer> fids, List<FlagFidData> rows) {
|
||||||
Map<Integer, Integer> result = new HashMap<>();
|
Map<Integer, Integer> result = new HashMap<>();
|
||||||
for (Integer fid : fids) {
|
for (Integer fid : fids) {
|
||||||
|
|
@ -140,11 +200,14 @@ public class FlagsService {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public static class Debt5000Data {
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class RuPastDuarearData {
|
||||||
private Integer fid;
|
private Integer fid;
|
||||||
private BigInteger accSerialNum;
|
private BigInteger accSerialNum;
|
||||||
private LocalDate reportedDate;
|
private LocalDate reportedDate;
|
||||||
private BigDecimal amtPastDue;
|
private BigDecimal amtPastDue;
|
||||||
|
private BigInteger daysPastDue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,24 @@
|
||||||
<result property="flag" column="flag" />
|
<result property="flag" column="flag" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
|
<resultMap id="RuPastDuarearResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$RuPastDuarearData">
|
||||||
|
<result property="fid" column="fid" />
|
||||||
|
<result property="accSerialNum" column="ACC_SERIAL_NUM" />
|
||||||
|
<result property="reportedDate" column="REPORTED_DT" />
|
||||||
|
<result property="amtPastDue" column="AMT_PAST_DUE" />
|
||||||
|
<result property="daysPastDue" column="DAYS_PAST_DUE" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="findRuPastDuarearData" resultMap="RuPastDuarearResultMap">
|
||||||
|
SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE, DAYS_PAST_DUE
|
||||||
|
FROM RU_PASTDUEARREAR
|
||||||
|
WHERE FID IN
|
||||||
|
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
||||||
|
#{fid}
|
||||||
|
</foreach>
|
||||||
|
with UR
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="findFlagsDebt5000" resultMap="FlagsFidDataResultMap">
|
<select id="findFlagsDebt5000" resultMap="FlagsFidDataResultMap">
|
||||||
WITH latest AS (
|
WITH latest AS (
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -79,150 +97,4 @@
|
||||||
WITH UR
|
WITH UR
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="findFlagsDebt5000Old" resultMap="FlagsFidDataResultMap">
|
|
||||||
SELECT rp.FID as fid,
|
|
||||||
CASE
|
|
||||||
WHEN EXISTS (SELECT 1
|
|
||||||
FROM RU_PASTDUEARREAR rp2
|
|
||||||
WHERE rp2.FID = rp.FID
|
|
||||||
AND rp2.ACC_SERIAL_NUM = rp.ACC_SERIAL_NUM
|
|
||||||
AND rp2.REPORTED_DT = rp.MAX_REP_DATE
|
|
||||||
AND rp2.AMT_PAST_DUE > 5000) THEN 1
|
|
||||||
ELSE 0
|
|
||||||
END as flag
|
|
||||||
FROM (SELECT FID,
|
|
||||||
ACC_SERIAL_NUM,
|
|
||||||
MAX(REPORTED_DT) as MAX_REP_DATE
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
GROUP BY FID, ACC_SERIAL_NUM) rp
|
|
||||||
GROUP BY rp.FID, rp.ACC_SERIAL_NUM, rp.MAX_REP_DATE
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByPastDueArrearOld" resultMap="FlagsFidDataResultMap">
|
|
||||||
SELECT rp.FID as fid,
|
|
||||||
CASE
|
|
||||||
WHEN EXISTS (SELECT 1
|
|
||||||
FROM RU_PASTDUEARREAR rp2
|
|
||||||
WHERE rp2.FID = rp.FID
|
|
||||||
AND rp2.REPORTED_DT >= #{reportedDate}
|
|
||||||
AND rp2.DAYS_PAST_DUE > 90) THEN 1
|
|
||||||
ELSE 0
|
|
||||||
END as flag
|
|
||||||
FROM (SELECT FID,
|
|
||||||
DAYS_PAST_DUE
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
GROUP BY FID, DAYS_PAST_DUE) rp
|
|
||||||
GROUP BY rp.FID, rp.DAYS_PAST_DUE
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByRuPaymtOld" resultMap="FlagsFidDataResultMap">
|
|
||||||
SELECT rp.FID as fid,
|
|
||||||
CASE
|
|
||||||
WHEN EXISTS (SELECT 1
|
|
||||||
FROM RU_PAYMT rp2
|
|
||||||
WHERE rp2.FID = rp.FID
|
|
||||||
AND rp2.REPORTED_DT >= #{reportedDate}
|
|
||||||
AND rp2.DAYS_PAST_DUE > 90) THEN 1
|
|
||||||
ELSE 0
|
|
||||||
END as flag
|
|
||||||
FROM (SELECT FID,
|
|
||||||
DAYS_PAST_DUE
|
|
||||||
FROM RU_PAYMT
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
GROUP BY FID, DAYS_PAST_DUE) rp
|
|
||||||
GROUP BY rp.FID, rp.DAYS_PAST_DUE
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<resultMap id="Debt500ResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$Debt5000Data">
|
|
||||||
<result property="fid" column="fid" />
|
|
||||||
<result property="accSerialNum" column="ACC_SERIAL_NUM" />
|
|
||||||
<result property="reportedDate" column="REPORTED_DT" />
|
|
||||||
<result property="amtPastDue" column="AMT_PAST_DUE" />
|
|
||||||
</resultMap>
|
|
||||||
|
|
||||||
<select id="findFlagsDebt5000New" resultMap="Debt500ResultMap">
|
|
||||||
SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
with UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlagsDebt5000NewWithOrderBy" resultMap="Debt500ResultMap">
|
|
||||||
SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE fid IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
ORDER BY FID DESC
|
|
||||||
with UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<resultMap id="Flag90ByPastDueArrearResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$Flag90DaysData">
|
|
||||||
<result property="fid" column="fid" />
|
|
||||||
<result property="daysPastDue" column="DAYS_PAST_DUE" />
|
|
||||||
<result property="daysPastDue" column="REPORTED_DT" />
|
|
||||||
</resultMap>
|
|
||||||
|
|
||||||
<select id="findFlag90ByPastDueArrearNew" resultMap="Flag90ByPastDueArrearResultMap">
|
|
||||||
SELECT FID, DAYS_PAST_DUE
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
AND REPORTED_DT >= #{reportedDate}
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByPastDueArrearNewWithOrderBy">
|
|
||||||
SELECT FID, DAYS_PAST_DUE, REPORTED_DT
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
ORDER BY FID DESC
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByRuPaymtNew">
|
|
||||||
SELECT FID, DAYS_PAST_DUE
|
|
||||||
FROM RU_PAYMT
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
AND REPORTED_DT >= #{reportedDate}
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByRuPaymtNewWithOrderBy">
|
|
||||||
SELECT FID, DAYS_PAST_DUE, REPORTED_DT
|
|
||||||
FROM RU_PAYMT
|
|
||||||
WHERE FID IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
ORDER BY FID DESC
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
package ru.nbch.credit_tracker.service;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import ru.nbch.credit_tracker.mapper.indic.FlagsMapper;
|
||||||
|
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class FlagsServiceTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
FlagsMapper flagsMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
List<Integer> fids = new ArrayList<>(List.of(
|
||||||
|
1, // есть просрочка 5000, есть просрочка 90_days в RU_PASTDUEARREAR
|
||||||
|
2, // есть просрочка 5000, нет просрочки 90_days в RU_PASTDUEARREAR. Нет просрочки 90_days в RU_PAYMT
|
||||||
|
3, // есть просрочка 5000, нет просрочки 90_days в RU_PASTDUEARREAR. Есть просрочка 90_days в RU_PAYMT
|
||||||
|
4, // нет никаких просрочек
|
||||||
|
7, // нет просрочки 5000, есть просрочка 90_days в RU_PASTDUEARREAR
|
||||||
|
5, // есть просрочка 5000, есть просрочка 90_days в RU_PASTDUEARREAR
|
||||||
|
6, // нет просрочки 5000, нет просрочки 90_days в RU_PASTDUEARREAR. Есть просрочка 90_days в RU_PAYMT
|
||||||
|
8, // нету в RU_PASTDUEARREAR, есть в RU_PAYMT
|
||||||
|
9) // нету в RU_PASTDUEARREAR, нету в RU_PAYMT
|
||||||
|
);
|
||||||
|
|
||||||
|
fids.sort(Comparator.naturalOrder());
|
||||||
|
|
||||||
|
Map<Integer, Boolean> flag5000Map = new HashMap<>();
|
||||||
|
Map<Integer, Boolean> flag90Days = new HashMap<>();
|
||||||
|
findFlags5000(fids, flag5000Map, flag90Days);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, flag5000Map.size());
|
||||||
|
Assertions.assertEquals(true, flag5000Map.get(1));
|
||||||
|
Assertions.assertEquals(true, flag5000Map.get(2));
|
||||||
|
Assertions.assertEquals(true, flag5000Map.get(3));
|
||||||
|
Assertions.assertEquals(false, flag5000Map.get(4));
|
||||||
|
Assertions.assertEquals(true, flag5000Map.get(5));
|
||||||
|
Assertions.assertEquals(false, flag5000Map.get(6));
|
||||||
|
Assertions.assertEquals(false, flag5000Map.get(7));
|
||||||
|
Assertions.assertEquals(false, flag5000Map.get(8));
|
||||||
|
Assertions.assertEquals(false, flag5000Map.get(9));
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, flag90Days.size());
|
||||||
|
Assertions.assertEquals(true, flag90Days.get(1));
|
||||||
|
Assertions.assertEquals(false, flag90Days.get(2));
|
||||||
|
Assertions.assertEquals(false, flag90Days.get(3));
|
||||||
|
Assertions.assertEquals(false, flag90Days.get(4));
|
||||||
|
Assertions.assertEquals(true, flag90Days.get(5));
|
||||||
|
Assertions.assertEquals(false, flag90Days.get(6));
|
||||||
|
Assertions.assertEquals(true, flag90Days.get(7));
|
||||||
|
Assertions.assertEquals(false, flag90Days.get(8));
|
||||||
|
Assertions.assertEquals(false, flag90Days.get(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findFlags5000(List<Integer> fids, Map<Integer, Boolean> flag5000Map, Map<Integer, Boolean> flag90Days) {
|
||||||
|
ruPastDuarearDataList.sort(Comparator.comparing(FlagsService.RuPastDuarearData::getFid) // сортируем сначала по фиду
|
||||||
|
.thenComparing(FlagsService.RuPastDuarearData::getReportedDate, Comparator.reverseOrder())); // Затем сортируем по REPORTED_DT по убыванию
|
||||||
|
|
||||||
|
LocalDate yearAgo = LocalDate.parse("2024-09-09");
|
||||||
|
|
||||||
|
for (Integer fid : fids) {
|
||||||
|
Iterator<FlagsService.RuPastDuarearData> iterator = ruPastDuarearDataList.iterator();
|
||||||
|
BigInteger prevAccSerialNum = null;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
FlagsService.RuPastDuarearData data = iterator.next();
|
||||||
|
|
||||||
|
if (fid.equals(data.getFid())) {
|
||||||
|
if (flag5000Map.get(fid) == null) { // Первая запись в списке с макс REPORTED_DT. Нас интересует только она для флага 5000
|
||||||
|
if (prevAccSerialNum == null || !prevAccSerialNum.equals(data.getAccSerialNum())) {
|
||||||
|
if (data.getAmtPastDue() != null && data.getAmtPastDue().compareTo(BigDecimal.valueOf(5000)) >= 0) {
|
||||||
|
flag5000Map.put(fid, true);
|
||||||
|
} else {
|
||||||
|
flag5000Map.put(fid, false);
|
||||||
|
}
|
||||||
|
prevAccSerialNum = data.getAccSerialNum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag90Days.get(fid) != null && flag90Days.get(fid).equals(Boolean.TRUE)) {
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag90Days.get(fid) == null || flag90Days.get(fid).equals(Boolean.FALSE)) {
|
||||||
|
if (data.getDaysPastDue() != null) {
|
||||||
|
boolean has90daysFlag = data.getDaysPastDue().compareTo(BigInteger.valueOf(90)) >= 0 && !data.getReportedDate().isBefore(yearAgo);
|
||||||
|
if (has90daysFlag) {
|
||||||
|
flag90Days.put(fid, true);
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
flag90Days.put(fid, false);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag5000Map.get(fid) == null) {
|
||||||
|
flag5000Map.put(fid, false);
|
||||||
|
}
|
||||||
|
if (flag90Days.get(fid) == null) {
|
||||||
|
flag90Days.put(fid, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<FlagsService.RuPastDuarearData> ruPastDuarearDataList = new ArrayList<>(
|
||||||
|
List.of(
|
||||||
|
new FlagsService.RuPastDuarearData(1, BigInteger.valueOf(1), LocalDate.parse("2025-12-31"), BigDecimal.valueOf(36000.00), BigInteger.valueOf(159)), // просрочка 5000 и 90_days по этой записи
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), LocalDate.parse("2021-12-29"), BigDecimal.valueOf(3200.00), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), LocalDate.parse("2022-01-28"), BigDecimal.valueOf(6700.00), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), LocalDate.parse("2025-04-06"), BigDecimal.valueOf(5700.00), null), // просрочка 5000 по этой записи
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(3, BigInteger.valueOf(3), LocalDate.parse("2025-01-14"), BigDecimal.valueOf(300000000000.00), null),
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), LocalDate.parse("2021-11-29"), BigDecimal.valueOf(0.00), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(4, BigInteger.valueOf(4), LocalDate.parse("2025-12-06"), BigDecimal.valueOf(4000.00), null), // нет просрочек
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-04-01"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(182)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-05-01"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(212)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-05-31"), BigDecimal.valueOf(2000.31), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-07-01"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(273)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-07-31"), BigDecimal.valueOf(2000.31), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-08-04"), BigDecimal.valueOf(7000.31), BigInteger.valueOf(307)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2025-09-08"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(338)), // не макс reported_date для того же acc_serial_num, просрочка 90_days будет взята у этой записи
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(51), LocalDate.parse("2025-09-09"), BigDecimal.valueOf(7000.31), BigInteger.valueOf(368)), // Просрочка 5000 будет взята у этой записи. Уникальный acc_serial_num с макс reported_dt
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2021-11-04"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(399)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), LocalDate.parse("2022-01-04"), BigDecimal.valueOf(5000.31), BigInteger.valueOf(5)), // не макс reported_date для того же acc_serial_num
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(6, BigInteger.valueOf(6), LocalDate.parse("2025-09-09"), BigDecimal.valueOf(3000), null), // Нет просрочки 5000, нет просрочки 90_days (90_days будет в RU_PAYMT)
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(7, BigInteger.valueOf(7), LocalDate.parse("2025-09-09"), BigDecimal.valueOf(5500), BigInteger.valueOf(90)), // не макс reported_date для того же acc_serial_num. 90_days будет взята отсюда
|
||||||
|
new FlagsService.RuPastDuarearData(7, BigInteger.valueOf(7), LocalDate.parse("2025-09-10"), BigDecimal.valueOf(3000), null) // Нет просрочки 5000. Уникальный acc_serial_num с макс reported_dt
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue