Compare commits
10 commits
021d7e8615
...
af824c7d07
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af824c7d07 | ||
|
|
7a4695281e | ||
|
|
e07b203686 | ||
|
|
8c8ee75292 | ||
|
|
4f55c0df42 | ||
|
|
e70f07b04b | ||
|
|
45ca5f4440 | ||
|
|
d1064b6b9f | ||
|
|
b42e4f70df | ||
|
|
c245790eb5 |
18 changed files with 1105 additions and 355 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
|
||||||
|
|
|
||||||
5
pom.xml
5
pom.xml
|
|
@ -126,6 +126,11 @@
|
||||||
<version>3.0.4</version>
|
<version>3.0.4</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-junit-jupiter</artifactId>
|
<artifactId>mockito-junit-jupiter</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
@ -47,5 +48,10 @@ public class IndicDataSourceConfig extends DatabaseConfig {
|
||||||
sqlSessionFactoryBean.setTypeHandlersPackage("ru.nbch.credit_tracker.config.datasource.handlers");
|
sqlSessionFactoryBean.setTypeHandlersPackage("ru.nbch.credit_tracker.config.datasource.handlers");
|
||||||
return sqlSessionFactoryBean.getObject();
|
return sqlSessionFactoryBean.getObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "jdbcTemplateIndic")
|
||||||
|
public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(@Qualifier("indicDataSource") DataSource dataSource) {
|
||||||
|
return new NamedParameterJdbcTemplate(dataSource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,8 @@ import java.util.List;
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface FlagsMapper {
|
public interface FlagsMapper {
|
||||||
|
|
||||||
List<FlagsService.FlagFidData> findFlagsDebt5000(@Param("fids") List<Integer> fids);
|
List<FlagsService.RuPastDuarearData> findRuPastDuarearData(@Param("fids") List<Integer> fids);
|
||||||
|
|
||||||
List<FlagsService.FlagFidData> findFlag90ByPastDueArrear(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
List<FlagsService.RuPaymtData> findRuPaymtData(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
||||||
|
|
||||||
List<FlagsService.FlagFidData> findFlag90ByRuPaymt(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ public interface PhoneFidMapMapper {
|
||||||
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Integer packageId, @Param("offset") int offset, @Param("limit") int limit);
|
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Integer packageId, @Param("offset") int offset, @Param("limit") int limit);
|
||||||
|
|
||||||
void updatePhoneFidMaps(@Param("subjects") List<PhoneFidMap> subjects);
|
void updatePhoneFidMaps(@Param("subjects") List<PhoneFidMap> subjects);
|
||||||
void updatePhoneFid(@Param("subject") PhoneFidMap subject);
|
|
||||||
|
|
||||||
void updatePhoneFidMapsErrors(@Param("subjects") List<PhoneFidMap> subjects);
|
void updatePhoneFidMapsErrors(@Param("subjects") List<PhoneFidMap> subjects);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,8 @@
|
||||||
package ru.nbch.credit_tracker.service;
|
package ru.nbch.credit_tracker.service;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.entities.dto.Hit;
|
import ru.nbch.credit_tracker.entities.dto.Hit;
|
||||||
|
|
@ -36,6 +22,21 @@ import ru.nbch.credit_tracker.service.xml.stax.MonitoringSignalResponseStaxXmlWr
|
||||||
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
|
import ru.nbch.credit_tracker.service.xml.stax.StaxXmlProcessor;
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сервис периодического опроса официального сервиса сигналов на наличие новых отчетов по пакетам находящимся в статусе ON_MONITORING
|
* Сервис периодического опроса официального сервиса сигналов на наличие новых отчетов по пакетам находящимся в статусе ON_MONITORING
|
||||||
*/
|
*/
|
||||||
|
|
@ -59,9 +60,9 @@ public class MonitoringService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
// ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("monitoring-"));
|
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("monitoring-"));
|
||||||
// long period = config.getMonitoringInterval() != null ? config.getMonitoringInterval() : 15;
|
long period = config.getMonitoringInterval() != null ? config.getMonitoringInterval() : 15;
|
||||||
// scheduler.scheduleAtFixedRate(this::monitor, 0, period, TimeUnit.MINUTES);
|
scheduler.scheduleAtFixedRate(this::monitor, 0, period, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void monitor() {
|
private void monitor() {
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@ import ru.nbch.credit_tracker.entities.external_request.signals.Signals;
|
||||||
import ru.nbch.credit_tracker.entities.external_response.monitoring_report_error.MonitoringReportErrors;
|
import ru.nbch.credit_tracker.entities.external_response.monitoring_report_error.MonitoringReportErrors;
|
||||||
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.MonitoringRequest;
|
import ru.nbch.credit_tracker.entities.user_request.monitoring_request.MonitoringRequest;
|
||||||
import ru.nbch.credit_tracker.enums.Status;
|
import ru.nbch.credit_tracker.enums.Status;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
|
||||||
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
||||||
|
import ru.nbch.credit_tracker.service.indic.FlagsService2;
|
||||||
import ru.nbch.credit_tracker.service.indic.PersonService;
|
import ru.nbch.credit_tracker.service.indic.PersonService;
|
||||||
import ru.nbch.credit_tracker.service.indic.PhoneService;
|
import ru.nbch.credit_tracker.service.indic.PhoneService2;
|
||||||
import ru.nbch.credit_tracker.service.signal.HitsService;
|
import ru.nbch.credit_tracker.service.signal.HitsService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PhoneFidMapService;
|
import ru.nbch.credit_tracker.service.signal.PhoneFidMapService;
|
||||||
import ru.nbch.credit_tracker.service.signal.UserPackageService;
|
import ru.nbch.credit_tracker.service.signal.UserPackageService;
|
||||||
|
|
@ -44,9 +44,8 @@ public class SignalService {
|
||||||
private final HitsService hitsService;
|
private final HitsService hitsService;
|
||||||
private final UserPackageService userPackageService;
|
private final UserPackageService userPackageService;
|
||||||
private final PhoneFidMapService phoneFidMapService;
|
private final PhoneFidMapService phoneFidMapService;
|
||||||
private final PhoneFidMapMapper phoneFidMapMapper;
|
private final PhoneService2 phoneService;
|
||||||
private final PhoneService phoneService;
|
private final FlagsService2 flagsService;
|
||||||
private final FlagsService flagsService;
|
|
||||||
private final PersonService personService;
|
private final PersonService personService;
|
||||||
private final StaxXmlProcessor staxXmlProcessor;
|
private final StaxXmlProcessor staxXmlProcessor;
|
||||||
|
|
||||||
|
|
@ -56,16 +55,14 @@ public class SignalService {
|
||||||
HitsService hitsService,
|
HitsService hitsService,
|
||||||
UserPackageService userPackageService,
|
UserPackageService userPackageService,
|
||||||
PhoneFidMapService phoneFidMapService,
|
PhoneFidMapService phoneFidMapService,
|
||||||
PhoneFidMapMapper mapper,
|
PhoneService2 phoneService,
|
||||||
PhoneService phoneService,
|
FlagsService2 flagsService,
|
||||||
FlagsService flagsService,
|
|
||||||
PersonService personService,
|
PersonService personService,
|
||||||
StaxXmlProcessor staxXmlProcessor) {
|
StaxXmlProcessor staxXmlProcessor) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.hitsService = hitsService;
|
this.hitsService = hitsService;
|
||||||
this.userPackageService = userPackageService;
|
this.userPackageService = userPackageService;
|
||||||
this.phoneFidMapService = phoneFidMapService;
|
this.phoneFidMapService = phoneFidMapService;
|
||||||
this.phoneFidMapMapper = mapper;
|
|
||||||
this.phoneService = phoneService;
|
this.phoneService = phoneService;
|
||||||
this.flagsService = flagsService;
|
this.flagsService = flagsService;
|
||||||
this.personService = personService;
|
this.personService = personService;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,12 @@ package ru.nbch.credit_tracker.service;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.nbch.credit_tracker.entities.dto.UserPackage;
|
||||||
import ru.nbch.credit_tracker.enums.Status;
|
import ru.nbch.credit_tracker.enums.Status;
|
||||||
import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сервис для завершения обработки пакетов находящихся в статусе PROCESSING
|
* Сервис для завершения обработки пакетов находящихся в статусе PROCESSING
|
||||||
* Запускается при старте приложения и отрабатывает 1 раз
|
* Запускается при старте приложения и отрабатывает 1 раз
|
||||||
|
|
@ -26,13 +29,13 @@ public class UpdateProcessingPackagesService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
// log.info("Start updating processing packages");
|
log.info("Start updating processing packages");
|
||||||
// List<UserPackage> packages = signalService.findPackagesOnProcessing();
|
List<UserPackage> packages = signalService.findPackagesOnProcessing();
|
||||||
// for (UserPackage userPackage : packages) {
|
for (UserPackage userPackage : packages) {
|
||||||
// log.info("Updating flags for Package {}", userPackage.getPackageName());
|
log.info("Updating flags for Package {}", userPackage.getPackageName());
|
||||||
// process(userPackage.getId(), userPackage.getPackageName());
|
process(userPackage.getId(), userPackage.getPackageName());
|
||||||
// }
|
}
|
||||||
// log.info("Finish updating processing packages");
|
log.info("Finish updating processing packages");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void process(Integer packageId, String packageName) {
|
private void process(Integer packageId, String packageName) {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
package ru.nbch.credit_tracker.service;
|
package ru.nbch.credit_tracker.service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.temporal.ChronoUnit;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
|
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
|
||||||
|
|
@ -12,6 +9,14 @@ import ru.nbch.credit_tracker.entities.dto.UserPackage;
|
||||||
import ru.nbch.credit_tracker.enums.Status;
|
import ru.nbch.credit_tracker.enums.Status;
|
||||||
import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сервис периодического обновления фидов и флагов просрочек по пакетам находящимся в статусе ON_MONITORING
|
* Сервис периодического обновления фидов и флагов просрочек по пакетам находящимся в статусе ON_MONITORING
|
||||||
* По обновленным пакетам формируется новый запрос постановки на мониторинг в официальный сервис сигналов
|
* По обновленным пакетам формируется новый запрос постановки на мониторинг в официальный сервис сигналов
|
||||||
|
|
@ -38,8 +43,8 @@ public class UpdatingFlagsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
// ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("updating-flags-"));
|
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new CustomizableThreadFactory("updating-flags-"));
|
||||||
// scheduler.scheduleAtFixedRate(this::update, 0, updateFlagsInterval, TimeUnit.DAYS);
|
scheduler.scheduleAtFixedRate(this::update, 0, updateFlagsInterval, TimeUnit.DAYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
@ -29,14 +28,17 @@ public class FlagsService {
|
||||||
if (fids.isEmpty()) {
|
if (fids.isEmpty()) {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
List<Integer> distinctFids = fids.stream().distinct().toList();
|
List<Integer> distinctFids = fids.stream()
|
||||||
|
.distinct()
|
||||||
|
.sorted(Comparator.naturalOrder())
|
||||||
|
.toList();
|
||||||
|
|
||||||
log.debug("Fids count: {}", distinctFids.size());
|
log.debug("Fids count: {}", distinctFids.size());
|
||||||
Map<Integer, Integer> flags5000 = calcFlag5000(distinctFids);
|
Map<Integer, Integer> flags5000 = new HashMap<>();
|
||||||
calcFlag500Test(distinctFids);
|
Map<Integer, Integer> flags90DaysByPastDueArrear = new HashMap<>();
|
||||||
Map<Integer, Integer> flags90DaysByPastDueArrear = calcFlag90DaysByPastDueArrear(distinctFids);
|
Map<Integer, Integer> flags90DaysByRuPaymt = new HashMap<>();
|
||||||
calcFlag90DaysByPastDueArrearTest(distinctFids);
|
findFlagsRuPastDueArrear(distinctFids, flags5000, flags90DaysByPastDueArrear);
|
||||||
Map<Integer, Integer> flags90DaysByRuPaymt = calcFlag90DaysByRuPaymt(distinctFids);
|
findFlagsRuPaymt(distinctFids, flags90DaysByRuPaymt);
|
||||||
calcFlag90DaysByRuPaymtTest(distinctFids);
|
|
||||||
|
|
||||||
Map<Integer, FlagsData> result = new HashMap<>();
|
Map<Integer, FlagsData> result = new HashMap<>();
|
||||||
fids.forEach(fid -> {
|
fids.forEach(fid -> {
|
||||||
|
|
@ -46,7 +48,7 @@ public class FlagsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer flag90days = flags90DaysByPastDueArrear.get(fid);
|
Integer flag90days = flags90DaysByPastDueArrear.get(fid);
|
||||||
if (flag90days == null) {
|
if (flag90days == null || flag90days == 0) {
|
||||||
flag90days = flags90DaysByRuPaymt.get(fid);
|
flag90days = flags90DaysByRuPaymt.get(fid);
|
||||||
if (flag90days == null) {
|
if (flag90days == null) {
|
||||||
flag90days = 0;
|
flag90days = 0;
|
||||||
|
|
@ -59,68 +61,118 @@ public class FlagsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Выбирает данные из RU_PASTDUEARREAR и ищет по ним флаги просрочек
|
||||||
* По FID из RU_PASTDUEARREAR выбираются все уникальные ACC_SERIAL_NUM с максимальной датой REPORTED_DT.
|
* По FID из RU_PASTDUEARREAR выбираются все уникальные ACC_SERIAL_NUM с максимальной датой REPORTED_DT.
|
||||||
* Если по хотя бы одной такой записи AMT_PAST_DUE > 5000, то флаг устанавливается в 1.
|
* Если по хотя бы одной такой записи AMT_PAST_DUE > 5000, то flag500 устанавливается в 1.
|
||||||
* Если ни по одному счёту условие не выполняется или счетов вообще не найдено, флаг = 0.
|
* Если ни по одному счёту условие не выполняется или счетов вообще не найдено, флаг = 0.
|
||||||
|
*
|
||||||
|
* flag90Days = 1, если выполняется хотя бы одно из условий:
|
||||||
|
* В INDIC.RU_PASTDUEARREAR у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
||||||
|
* Если ни по одной записи условия не выполняются или записей вообще не найдено, флаг = 0.
|
||||||
|
* @param fids - отсортирован по возрастанию фидов
|
||||||
|
* @param flag5000Map - рещультирующая мапа флагов просрочек debt5000
|
||||||
|
* @param flag90Days - рещультирующая мапа флагов просрочек 90_days
|
||||||
*/
|
*/
|
||||||
private Map<Integer, Integer> calcFlag5000(List<Integer> fids) {
|
private void findFlagsRuPastDueArrear(List<Integer> fids, Map<Integer, Integer> flag5000Map, Map<Integer, Integer> flag90Days) {
|
||||||
log.debug("Start calculating flag 5000");
|
log.debug("Start calculating flag 5000 and 90 days by RU_PASTDUEARREAR");
|
||||||
List<FlagFidData> rows = mapper.findFlagsDebt5000(fids);
|
List<RuPastDuarearData> ruPastDuarearDataList = mapper.findRuPastDuarearData(fids);
|
||||||
Map<Integer, Integer> res = makeFidFlagMapByRs(fids, rows);
|
|
||||||
log.debug("Complete calculating flag 5000");
|
ruPastDuarearDataList.sort(Comparator.comparing(FlagsService.RuPastDuarearData::getFid) // сортируем сначала по фиду
|
||||||
return res;
|
.thenComparing(FlagsService.RuPastDuarearData::getReportedDate, Comparator.reverseOrder())); // Затем сортируем по REPORTED_DT по убыванию
|
||||||
|
|
||||||
|
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
prevAccSerialNum = data.getAccSerialNum();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcFlag500Test(List<Integer> fids) {
|
Integer flag90 = flag90Days.get(fid);
|
||||||
log.debug("Start findFlagsDebt5000NewWithOrderBy");
|
if (flag90 != null && flag90 == 1) {
|
||||||
mapper.findFlagsDebt5000NewWithOrderBy(fids);
|
iterator.remove();
|
||||||
log.debug("Complete findFlagsDebt5000NewWithOrderBy");
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag90 == null || flag90 == 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// если мы так и не нашли флаги для этих фидов - выставляем их в 0
|
||||||
|
flag5000Map.putIfAbsent(fid, 0);
|
||||||
|
flag90Days.putIfAbsent(fid, 0);
|
||||||
|
}
|
||||||
|
log.debug("Complete calculating flag 5000 and 90 days by RU_PASTDUEARREAR");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Флаг = 1, если выполняется хотя бы одно из условий:
|
* Выбирает данные из RU_PAYMT и ищет по ним флаги просрочек 90Days
|
||||||
* В INDIC.RU_PASTDUEARREAR или RU_PAYMT у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
*
|
||||||
|
* flag90Days = 1, если выполняется хотя бы одно из условий:
|
||||||
|
* В INDIC.RU_PAYMT у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
||||||
* Если ни по одной записи условия не выполняются или записей вообще не найдено, флаг = 0.
|
* Если ни по одной записи условия не выполняются или записей вообще не найдено, флаг = 0.
|
||||||
|
* @param fids - отсортирован по возрастанию фидов
|
||||||
|
* @param flag90Days - рещультирующая мапа флагов просрочек 90_days
|
||||||
*/
|
*/
|
||||||
private Map<Integer, Integer> calcFlag90DaysByPastDueArrear(List<Integer> fids) {
|
private void findFlagsRuPaymt(List<Integer> fids, Map<Integer, Integer> flag90Days) {
|
||||||
log.debug("Start calculating flag 90 by PastDueArrear");
|
log.debug("Start calculating flag 90 days by RU_PAPAYMT");
|
||||||
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
||||||
List<FlagFidData> rows = mapper.findFlag90ByPastDueArrear(fids, yearAgo);
|
List<RuPaymtData> ruPaymtDataList = mapper.findRuPaymtData(fids, yearAgo);
|
||||||
Map<Integer, Integer> res = makeFidFlagMapByRs(fids, rows);
|
ruPaymtDataList.sort(Comparator.comparing(RuPaymtData::getFid, Comparator.naturalOrder()));
|
||||||
log.debug("Complete calculating flag 90 by PastDueArrear");
|
|
||||||
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) {
|
|
||||||
log.debug("Start calculating flag 90 by ruPaymt");
|
|
||||||
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
|
||||||
List<FlagFidData> rows = mapper.findFlag90ByRuPaymt(fids, yearAgo);
|
|
||||||
Map<Integer, Integer> res = makeFidFlagMapByRs(fids, rows);
|
|
||||||
log.debug("Complete calculating flag 90 by ruPaymt");
|
|
||||||
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) {
|
|
||||||
Map<Integer, Integer> result = new HashMap<>();
|
|
||||||
for (Integer fid : fids) {
|
for (Integer fid : fids) {
|
||||||
result.put(fid, 0);
|
Iterator<RuPaymtData> iterator = ruPaymtDataList.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
RuPaymtData data = iterator.next();
|
||||||
|
if (fid.equals(data.getFid())) {
|
||||||
|
Integer flag90 = flag90Days.get(fid);
|
||||||
|
if (flag90 != null && flag90 == 1) {
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (FlagFidData row : rows) {
|
|
||||||
result.put(row.getFid(), row.getFlag() != null ? row.getFlag() : 0);
|
if (flag90 == null || flag90 == 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();
|
||||||
}
|
}
|
||||||
return result;
|
} else {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flag90Days.putIfAbsent(fid, 0);
|
||||||
|
}
|
||||||
|
log.debug("Complete calculating flag 90 days by RU_PAPAYMT");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|
@ -133,23 +185,21 @@ public class FlagsService {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public static class FlagFidData {
|
@AllArgsConstructor
|
||||||
private Integer fid;
|
@NoArgsConstructor
|
||||||
private Integer flag;
|
public static class RuPastDuarearData {
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public static class Debt5000Data {
|
|
||||||
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
|
||||||
@Setter
|
@Setter
|
||||||
public static class Flag90DaysData {
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class RuPaymtData {
|
||||||
private Integer fid;
|
private Integer fid;
|
||||||
private BigInteger daysPastDue;
|
private BigInteger daysPastDue;
|
||||||
private LocalDate reportedDate;
|
private LocalDate reportedDate;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
package ru.nbch.credit_tracker.service.indic;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class FlagsService2 {
|
||||||
|
|
||||||
|
private static final String SELECT_RU_PASDUEARREAR_DATA =
|
||||||
|
"SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE, DAYS_PAST_DUE " +
|
||||||
|
"FROM RU_PASTDUEARREAR " +
|
||||||
|
"WHERE FID IN (:fids) " +
|
||||||
|
"ORDER BY FID, REPORTED_DT DESC " +
|
||||||
|
"WITH UR";
|
||||||
|
|
||||||
|
private static final String SELECT_RU_PAYMT_DATA =
|
||||||
|
"SELECT FID, DAYS_PAST_DUE, REPORTED_DT " +
|
||||||
|
"FROM RU_PAYMT " +
|
||||||
|
"WHERE FID IN (:fids) " +
|
||||||
|
"AND REPORTED_DT >= :reportedDate " +
|
||||||
|
"WITH UR";
|
||||||
|
|
||||||
|
private final NamedParameterJdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
public FlagsService2(@Qualifier("jdbcTemplateIndic") NamedParameterJdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Integer, FlagsService.FlagsData> findFlags(List<Integer> fids) {
|
||||||
|
if (fids.isEmpty()) {
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
List<Integer> distinctFids = fids.stream()
|
||||||
|
.distinct()
|
||||||
|
.sorted(Comparator.naturalOrder())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
log.debug("Fids count: {}", distinctFids.size());
|
||||||
|
Map<Integer, Integer> flags5000 = new HashMap<>();
|
||||||
|
Map<Integer, Integer> flags90DaysByPastDueArrear = new HashMap<>();
|
||||||
|
Map<Integer, Integer> flags90DaysByRuPaymt = new HashMap<>();
|
||||||
|
findFlagsRuPastDueArrear(distinctFids, flags5000, flags90DaysByPastDueArrear);
|
||||||
|
findFlagsRuPaymt(distinctFids, flags90DaysByRuPaymt);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> result = new HashMap<>();
|
||||||
|
fids.forEach(fid -> {
|
||||||
|
Integer flagDebt5000 = flags5000.get(fid);
|
||||||
|
if (flagDebt5000 == null) {
|
||||||
|
flagDebt5000 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer flag90days = flags90DaysByPastDueArrear.get(fid);
|
||||||
|
if (flag90days == null || flag90days == 0) {
|
||||||
|
flag90days = flags90DaysByRuPaymt.get(fid);
|
||||||
|
if (flag90days == null) {
|
||||||
|
flag90days = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.put(fid, new FlagsService.FlagsData(flagDebt5000, flag90days));
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выбирает данные из RU_PASTDUEARREAR и ищет по ним флаги просрочек
|
||||||
|
* По FID из RU_PASTDUEARREAR выбираются все уникальные ACC_SERIAL_NUM с максимальной датой REPORTED_DT.
|
||||||
|
* Если по хотя бы одной такой записи AMT_PAST_DUE > 5000, то flag500 устанавливается в 1.
|
||||||
|
* Если ни по одному счёту условие не выполняется или счетов вообще не найдено, флаг = 0.
|
||||||
|
* <p>
|
||||||
|
* flag90Days = 1, если выполняется хотя бы одно из условий:
|
||||||
|
* В INDIC.RU_PASTDUEARREAR у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
||||||
|
* Если ни по одной записи условия не выполняются или записей вообще не найдено, флаг = 0.
|
||||||
|
*
|
||||||
|
* @param fids - отсортирован по возрастанию фидов
|
||||||
|
* @param flag5000Map - рещультирующая мапа флагов просрочек debt5000
|
||||||
|
* @param flag90Days - рещультирующая мапа флагов просрочек 90_days
|
||||||
|
*/
|
||||||
|
private void findFlagsRuPastDueArrear(List<Integer> fids, Map<Integer, Integer> flag5000Map, Map<Integer, Integer> flag90Days) {
|
||||||
|
log.debug("Start calculating flag 5000 and 90 days by RU_PASTDUEARREAR");
|
||||||
|
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||||
|
params.addValue("fids", fids);
|
||||||
|
|
||||||
|
jdbcTemplate.query(SELECT_RU_PASDUEARREAR_DATA, params, (ResultSet rs) -> {
|
||||||
|
Integer currentFid = null;
|
||||||
|
BigInteger prevAccSerialNum = null;
|
||||||
|
boolean processed5000ForCurrentId = false;
|
||||||
|
boolean processed90DaysForCurrentId = false;
|
||||||
|
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
Integer fid = rs.getInt("FID");
|
||||||
|
|
||||||
|
// Переход к новому fid. Сброс состояния
|
||||||
|
if (!fid.equals(currentFid)) {
|
||||||
|
currentFid = fid;
|
||||||
|
prevAccSerialNum = null;
|
||||||
|
processed5000ForCurrentId = false;
|
||||||
|
processed90DaysForCurrentId = false;
|
||||||
|
|
||||||
|
// Инициализируем значения по умолчанию
|
||||||
|
flag5000Map.putIfAbsent(fid, 0);
|
||||||
|
flag90Days.putIfAbsent(fid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если для текущего FID уже обработали оба флага, пропускаем остальные записи
|
||||||
|
if (processed5000ForCurrentId && processed90DaysForCurrentId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработка флага 5000
|
||||||
|
if (!processed5000ForCurrentId && flag5000Map.get(fid) == 0) {
|
||||||
|
BigInteger currentAccSerialNum = getBigInteger(rs, "ACC_SERIAL_NUM");
|
||||||
|
BigDecimal amtPastDue = getBigDecimal(rs, "AMT_PAST_DUE");
|
||||||
|
|
||||||
|
if (prevAccSerialNum == null || !prevAccSerialNum.equals(currentAccSerialNum)) {
|
||||||
|
if (amtPastDue != null && amtPastDue.compareTo(BigDecimal.valueOf(5000)) >= 0) {
|
||||||
|
flag5000Map.put(fid, 1);
|
||||||
|
processed5000ForCurrentId = true;
|
||||||
|
}
|
||||||
|
prevAccSerialNum = currentAccSerialNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработка флага 90 дней
|
||||||
|
if (!processed90DaysForCurrentId) {
|
||||||
|
Integer currentFlag90 = flag90Days.get(fid);
|
||||||
|
|
||||||
|
if (currentFlag90 != null && currentFlag90 == 1) {
|
||||||
|
processed90DaysForCurrentId = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentFlag90 == null || currentFlag90 == 0) {
|
||||||
|
BigInteger days = getBigInteger(rs, "DAYS_PAST_DUE");
|
||||||
|
LocalDate reportedDate = rs.getObject("REPORTED_DT", LocalDate.class);
|
||||||
|
|
||||||
|
if (days != null) {
|
||||||
|
boolean has90daysFlag = days.compareTo(BigInteger.valueOf(90)) >= 0
|
||||||
|
&& reportedDate != null && !reportedDate.isBefore(yearAgo);
|
||||||
|
|
||||||
|
if (has90daysFlag) {
|
||||||
|
flag90Days.put(fid, 1);
|
||||||
|
processed90DaysForCurrentId = true;
|
||||||
|
} else {
|
||||||
|
flag90Days.put(fid, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flag90Days.put(fid, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
log.debug("Complete calculating flag 5000 and 90 days by RU_PASTDUEARREAR");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Выбирает данные из RU_PAYMT и ищет по ним флаги просрочек 90Days
|
||||||
|
* <p>
|
||||||
|
* flag90Days = 1, если выполняется хотя бы одно из условий:
|
||||||
|
* В INDIC.RU_PAYMT у данного FID есть запись с DAYS_PAST_DUE ≥ 90 и REPORTED_DT >= текущая дата – 12 месяцев.
|
||||||
|
* Если ни по одной записи условия не выполняются или записей вообще не найдено, флаг = 0.
|
||||||
|
*
|
||||||
|
* @param fids - отсортирован по возрастанию фидов
|
||||||
|
* @param flag90Days - рещультирующая мапа флагов просрочек 90_days
|
||||||
|
*/
|
||||||
|
private void findFlagsRuPaymt(List<Integer> fids, Map<Integer, Integer> flag90Days) {
|
||||||
|
log.debug("Start calculating flag 90 days by RU_PAPAYMT");
|
||||||
|
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
||||||
|
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||||
|
params.addValue("fids", fids);
|
||||||
|
params.addValue("reportedDate", yearAgo);
|
||||||
|
jdbcTemplate.query(SELECT_RU_PAYMT_DATA, params, rs -> {
|
||||||
|
Integer currentFid = null;
|
||||||
|
boolean processed90DaysForCurrentId = false;
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
Integer fid = rs.getInt("FID");
|
||||||
|
|
||||||
|
// Переход к новому fid. Сброс состояния
|
||||||
|
if (!fid.equals(currentFid)) {
|
||||||
|
currentFid = fid;
|
||||||
|
processed90DaysForCurrentId = false;
|
||||||
|
|
||||||
|
// Инициализируем значения по умолчанию
|
||||||
|
flag90Days.putIfAbsent(fid, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработка флага 90 дней
|
||||||
|
if (!processed90DaysForCurrentId) {
|
||||||
|
Integer currentFlag90 = flag90Days.get(fid);
|
||||||
|
|
||||||
|
if (currentFlag90 != null && currentFlag90 == 1) {
|
||||||
|
processed90DaysForCurrentId = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentFlag90 == null || currentFlag90 == 0) {
|
||||||
|
BigInteger days = getBigInteger(rs, "DAYS_PAST_DUE");
|
||||||
|
LocalDate date = rs.getObject("REPORTED_DT", LocalDate.class);
|
||||||
|
|
||||||
|
if (days != null) {
|
||||||
|
boolean has90daysFlag = days.compareTo(BigInteger.valueOf(90)) >= 0
|
||||||
|
&& date != null && !date.isBefore(yearAgo);
|
||||||
|
|
||||||
|
if (has90daysFlag) {
|
||||||
|
flag90Days.put(fid, 1);
|
||||||
|
processed90DaysForCurrentId = true;
|
||||||
|
} else {
|
||||||
|
flag90Days.put(fid, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flag90Days.put(fid, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
log.debug("Complete calculating flag 90 days by RU_PAPAYMT");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BigInteger getBigInteger(ResultSet rs, String columnName) {
|
||||||
|
try {
|
||||||
|
String value = rs.getString(columnName);
|
||||||
|
return value != null ? new BigInteger(value) : null;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getBigDecimal(ResultSet rs, String columnName) {
|
||||||
|
try {
|
||||||
|
return rs.getBigDecimal(columnName);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,6 @@ import ru.nbch.credit_tracker.mapper.indic.PhoneMapper;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
|
@ -25,13 +24,8 @@ public class PhoneService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ищет фиды по номерам телефона
|
* Ищет фиды по номерам телефона
|
||||||
* @return Map: key - номер телефона; value - fid
|
* @return Map: key - fid; value - {@link PhoneFidMap}
|
||||||
*/
|
*/
|
||||||
public Map<String, Integer> findFidsPhoneData(List<PhoneFidMap> subjects) {
|
|
||||||
List<String> phones = subjects.stream().map(subject -> "9" + subject.getPhone()).toList();
|
|
||||||
return convertFidsDataToMap(mapper.findFids(phones));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Integer, PhoneFidMap> defineFidByPhone(List<PhoneFidMap> subjects) {
|
public Map<Integer, PhoneFidMap> defineFidByPhone(List<PhoneFidMap> subjects) {
|
||||||
Map<Integer, PhoneFidMap> phoneFidMap = new HashMap<>();
|
Map<Integer, PhoneFidMap> phoneFidMap = new HashMap<>();
|
||||||
List<String> phones = subjects.stream().
|
List<String> phones = subjects.stream().
|
||||||
|
|
@ -65,23 +59,6 @@ public class PhoneService {
|
||||||
return phoneFidMap;
|
return phoneFidMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Integer> convertFidsDataToMap(List<FidsData> fidsData) {
|
|
||||||
if (fidsData == null || fidsData.isEmpty()) {
|
|
||||||
return new HashMap<>();
|
|
||||||
}
|
|
||||||
return fidsData.stream()
|
|
||||||
.collect(Collectors.groupingBy(
|
|
||||||
FidsData::getPhone,
|
|
||||||
Collectors.collectingAndThen(
|
|
||||||
Collectors.maxBy(
|
|
||||||
Comparator.comparing(FidsData::getFileSinceDate)
|
|
||||||
.thenComparing(FidsData::getFid)
|
|
||||||
),
|
|
||||||
data -> data.map(FidsData::getFid).orElse(null)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package ru.nbch.credit_tracker.service.indic;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class PhoneService2 {
|
||||||
|
|
||||||
|
private static final String SELCT_FIDS = """
|
||||||
|
SELECT
|
||||||
|
pn.number,
|
||||||
|
pn.fid,
|
||||||
|
pn.file_since_dt
|
||||||
|
FROM PHONE_NORM pn
|
||||||
|
JOIN (SELECT DISTINCT fid FROM NAME) nf
|
||||||
|
ON nf.fid = pn.fid
|
||||||
|
WHERE number in (:phones)
|
||||||
|
ORDER BY
|
||||||
|
pn.number ASC,
|
||||||
|
pn.file_since_dt DESC,
|
||||||
|
pn.fid DESC
|
||||||
|
WITH UR
|
||||||
|
""";
|
||||||
|
|
||||||
|
private final NamedParameterJdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
public PhoneService2(@Qualifier("jdbcTemplateIndic") NamedParameterJdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ищет фиды по номерам телефона
|
||||||
|
*
|
||||||
|
* @return Map: key - fid; value - {@link PhoneFidMap}
|
||||||
|
*/
|
||||||
|
public Map<Integer, PhoneFidMap> defineFidByPhone(List<PhoneFidMap> subjects) {
|
||||||
|
Map<Integer, PhoneFidMap> phoneFidMap = new HashMap<>();
|
||||||
|
|
||||||
|
List<String> phones = subjects.stream().
|
||||||
|
map(subject -> "9" + subject.getPhone())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
subjects.sort(
|
||||||
|
Comparator.comparing(
|
||||||
|
PhoneFidMap::getPhone,
|
||||||
|
Comparator.naturalOrder()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
MapSqlParameterSource params = new MapSqlParameterSource();
|
||||||
|
params.addValue("phones", phones);
|
||||||
|
|
||||||
|
List<FidsData> phonesByFid = jdbcTemplate.query(SELCT_FIDS, params, (rs, rowNum) ->
|
||||||
|
new FidsData(rs.getInt("fid"), rs.getString("number"), rs.getObject("file_since_dt", LocalDate.class))
|
||||||
|
);
|
||||||
|
|
||||||
|
log.debug("Start merging fids");
|
||||||
|
for (PhoneFidMap phoneFid : subjects) {
|
||||||
|
Iterator<FidsData> iterator = phonesByFid.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
FidsData fidsData = iterator.next();
|
||||||
|
if (fidsData.getPhone().equals(9 + phoneFid.getPhone())) {
|
||||||
|
//fixme доступ по ссылке, страшно, придумать что-то еще
|
||||||
|
phoneFidMap.put(fidsData.getFid(), phoneFid);
|
||||||
|
iterator.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("End merging fids");
|
||||||
|
|
||||||
|
return phoneFidMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class FidsData {
|
||||||
|
private Integer fid;
|
||||||
|
private String phone;
|
||||||
|
private LocalDate fileSinceDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,224 +5,39 @@
|
||||||
|
|
||||||
<mapper namespace="ru.nbch.credit_tracker.mapper.indic.FlagsMapper">
|
<mapper namespace="ru.nbch.credit_tracker.mapper.indic.FlagsMapper">
|
||||||
|
|
||||||
<resultMap id="FlagsFidDataResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$FlagFidData">
|
<resultMap id="RuPastDuarearResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$RuPastDuarearData">
|
||||||
<result property="fid" column="fid" />
|
|
||||||
<result property="flag" column="flag" />
|
|
||||||
</resultMap>
|
|
||||||
|
|
||||||
<select id="findFlagsDebt5000" resultMap="FlagsFidDataResultMap">
|
|
||||||
WITH latest AS (
|
|
||||||
SELECT
|
|
||||||
fid,
|
|
||||||
acc_serial_num,
|
|
||||||
amt_past_due,
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY fid, acc_serial_num ORDER BY reported_dt DESC) AS rn
|
|
||||||
FROM RU_PASTDUEARREAR
|
|
||||||
WHERE fid IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
fid,
|
|
||||||
CASE WHEN SUM(CASE WHEN amt_past_due > 5000 THEN 1 ELSE 0 END) > 0
|
|
||||||
THEN 1 ELSE 0
|
|
||||||
END AS flag
|
|
||||||
FROM latest WHERE rn = 1
|
|
||||||
GROUP BY fid
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByPastDueArrear" resultMap="FlagsFidDataResultMap">
|
|
||||||
WITH latest AS (
|
|
||||||
SELECT
|
|
||||||
r.fid,
|
|
||||||
r.days_past_due,
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY r.fid ORDER BY r.reported_dt DESC) AS rn
|
|
||||||
FROM RU_PASTDUEARREAR r
|
|
||||||
WHERE r.fid IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
AND r.reported_dt >= #{reportedDate}
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
fid,
|
|
||||||
CASE WHEN MAX(CASE WHEN days_past_due > 90 THEN 1 ELSE 0 END) = 1
|
|
||||||
THEN 1 ELSE 0
|
|
||||||
END AS flag
|
|
||||||
FROM latest WHERE rn = 1
|
|
||||||
GROUP BY fid
|
|
||||||
WITH UR
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="findFlag90ByRuPaymt" resultMap="FlagsFidDataResultMap">
|
|
||||||
WITH latest AS (
|
|
||||||
SELECT
|
|
||||||
r.fid,
|
|
||||||
r.days_past_due,
|
|
||||||
ROW_NUMBER() OVER (PARTITION BY r.fid ORDER BY r.reported_dt DESC) AS rn
|
|
||||||
FROM RU_PAYMT r
|
|
||||||
WHERE r.fid IN
|
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
|
||||||
#{fid}
|
|
||||||
</foreach>
|
|
||||||
AND r.reported_dt >= #{reportedDate}
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
fid,
|
|
||||||
CASE WHEN MAX(CASE WHEN days_past_due > 90 THEN 1 ELSE 0 END) = 1
|
|
||||||
THEN 1 ELSE 0
|
|
||||||
END AS flag
|
|
||||||
FROM latest WHERE rn = 1
|
|
||||||
GROUP BY fid
|
|
||||||
WITH UR
|
|
||||||
</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="fid" column="fid" />
|
||||||
<result property="accSerialNum" column="ACC_SERIAL_NUM" />
|
<result property="accSerialNum" column="ACC_SERIAL_NUM" />
|
||||||
<result property="reportedDate" column="REPORTED_DT" />
|
<result property="reportedDate" column="REPORTED_DT" />
|
||||||
<result property="amtPastDue" column="AMT_PAST_DUE" />
|
<result property="amtPastDue" column="AMT_PAST_DUE" />
|
||||||
|
<result property="daysPastDue" column="DAYS_PAST_DUE" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<select id="findFlagsDebt5000New" resultMap="Debt500ResultMap">
|
<resultMap id="RuPaymtResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$RuPaymtData">
|
||||||
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="fid" column="fid" />
|
||||||
<result property="daysPastDue" column="DAYS_PAST_DUE" />
|
<result property="daysPastDue" column="DAYS_PAST_DUE" />
|
||||||
<result property="daysPastDue" column="REPORTED_DT" />
|
<result property="reportedDate" column="REPORTED_DT" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<select id="findFlag90ByPastDueArrearNew" resultMap="Flag90ByPastDueArrearResultMap">
|
<select id="findRuPastDuarearData" resultMap="RuPastDuarearResultMap">
|
||||||
SELECT FID, DAYS_PAST_DUE
|
SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE, DAYS_PAST_DUE
|
||||||
FROM RU_PASTDUEARREAR
|
FROM RU_PASTDUEARREAR
|
||||||
WHERE FID IN
|
WHERE FID IN
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
||||||
#{fid}
|
#{fid}
|
||||||
</foreach>
|
</foreach>
|
||||||
AND REPORTED_DT >= #{reportedDate}
|
with UR
|
||||||
WITH UR
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="findFlag90ByPastDueArrearNewWithOrderBy">
|
<select id="findRuPaymtData" resultMap="RuPaymtResultMap">
|
||||||
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
|
SELECT FID, DAYS_PAST_DUE, REPORTED_DT
|
||||||
FROM RU_PAYMT
|
FROM RU_PAYMT
|
||||||
WHERE FID IN
|
WHERE FID IN
|
||||||
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
<foreach item="fid" collection="fids" open="(" separator="," close=")">
|
||||||
#{fid}
|
#{fid}
|
||||||
</foreach>
|
</foreach>
|
||||||
ORDER BY FID DESC
|
AND REPORTED_DT >= #{reportedDate}
|
||||||
WITH UR
|
with UR
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -42,17 +42,6 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updatePhoneFid" parameterType="ru.nbch.credit_tracker.entities.dto.PhoneFidMap">
|
|
||||||
UPDATE signals_phone_fid_map
|
|
||||||
SET
|
|
||||||
fid = #{subject.fid},
|
|
||||||
flag_debt5000 = #{subject.flagDebt5000},
|
|
||||||
flag_90_12 = #{subject.flag90days},
|
|
||||||
calculated_at = #{subject.calculatedAt},
|
|
||||||
error_text = #{subject.errorText}
|
|
||||||
WHERE id = #{subject.id}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="updatePhoneFidMapsErrors" parameterType="java.util.List">
|
<update id="updatePhoneFidMapsErrors" parameterType="java.util.List">
|
||||||
<foreach collection="subjects" item="subject" separator=";">
|
<foreach collection="subjects" item="subject" separator=";">
|
||||||
UPDATE signals_phone_fid_map
|
UPDATE signals_phone_fid_map
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,280 @@
|
||||||
|
package ru.nbch.credit_tracker.service;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
|
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
||||||
|
import ru.nbch.credit_tracker.service.indic.FlagsService2;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class FlagsService2Test {
|
||||||
|
|
||||||
|
private static final LocalDate INITIAL_DATE = LocalDate.parse("2025-09-25");
|
||||||
|
|
||||||
|
private static final String RU_PASTDUEAREAR_CREATE = """
|
||||||
|
create table RU_PASTDUEARREAR
|
||||||
|
(
|
||||||
|
FID INTEGER not null,
|
||||||
|
SERIAL_NUM BIGINT not null primary key,
|
||||||
|
ACC_SERIAL_NUM BIGINT not null,
|
||||||
|
REPORTED_DT DATE not null,
|
||||||
|
AMT_PAST_DUE DECIMAL(17, 2),
|
||||||
|
DAYS_PAST_DUE BIGINT
|
||||||
|
);
|
||||||
|
""";
|
||||||
|
|
||||||
|
private static final String RU_PASTDUEAREAR_DROP = """
|
||||||
|
DROP TABLE IF EXISTS RU_PASTDUEARREAR;
|
||||||
|
""";
|
||||||
|
|
||||||
|
private static final String RU_PAYMT_DROP = """
|
||||||
|
DROP TABLE IF EXISTS RU_PAYMT;
|
||||||
|
""";
|
||||||
|
|
||||||
|
private static final String RU_PAYMT_CREATE = """
|
||||||
|
create table RU_PAYMT
|
||||||
|
(
|
||||||
|
FID INTEGER not null,
|
||||||
|
SERIAL_NUM BIGINT not null primary key,
|
||||||
|
DAYS_PAST_DUE INTEGER,
|
||||||
|
REPORTED_DT DATE not null
|
||||||
|
);
|
||||||
|
""";
|
||||||
|
|
||||||
|
private static final String FILL_RU_PASTDUEARREAR = String.format("""
|
||||||
|
INSERT INTO RU_PASTDUEARREAR VALUES
|
||||||
|
(1, 1, 1, '%s', 36000.00, 159), -- просрочка 5000 и 90_days по этой записи
|
||||||
|
(2, 2, 2, '%s', 3200.00, null), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(2, 3, 2, '%s', 6700.00, null), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(2, 4, 2, '%s', 5700.00, null), -- просрочка 5000 по этой записи
|
||||||
|
(3, 5, 3, '%s', 300000000000.00, null),
|
||||||
|
(2, 6, 2, '%s', 0.00, null), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(4, 7, 4, '%s', 4000.00, null), -- нет просрочек
|
||||||
|
(5, 8, 5, '%s', 2000.31, 182), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 9, 5, '%s', 2000.31, 212), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 10, 5, '%s', 2000.31, null), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 11, 5, '%s', 2000.31, 273), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 12, 5, '%s', 2000.31, null), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 13, 5, '%s', 7000.31, 307), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 14, 5, '%s', 2000.31, 338), -- не макс reported_date для того же acc_serial_num, просрочка 90_days будет взята у этой записи
|
||||||
|
(5, 15, 5, '%s', 7000.31, 368), -- Просрочка 5000 будет взята у этой записи. Уникальный acc_serial_num с макс reported_dt
|
||||||
|
(5, 16, 5, '%s', 2000.31, 399), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(5, 17, 5, '%s', 5000.31, 5), -- не макс reported_date для того же acc_serial_num
|
||||||
|
(6, 18, 6, '%s', 3000, null), -- Нет просрочки 5000, нет просрочки 90_days (90_days будет в RU_PAYMT)
|
||||||
|
(7, 19, 7, '%s', 5500, 90), -- не макс reported_date для того же acc_serial_num. 90_days будет взята отсюда
|
||||||
|
(7, 20, 7, '%s', 3000, null) -- Нет просрочки 5000. Уникальный acc_serial_num с макс reported_dt
|
||||||
|
""",
|
||||||
|
calcLocalDateFromInitialDate("2025-05-31"),
|
||||||
|
calcLocalDateFromInitialDate("2021-12-29"),
|
||||||
|
calcLocalDateFromInitialDate("2022-01-28"),
|
||||||
|
calcLocalDateFromInitialDate("2025-04-06"),
|
||||||
|
calcLocalDateFromInitialDate("2025-01-14"),
|
||||||
|
calcLocalDateFromInitialDate("2021-11-29"),
|
||||||
|
calcLocalDateFromInitialDate("2025-12-06"),
|
||||||
|
calcLocalDateFromInitialDate("2021-04-01"),
|
||||||
|
calcLocalDateFromInitialDate("2021-05-01"),
|
||||||
|
calcLocalDateFromInitialDate("2021-05-31"),
|
||||||
|
calcLocalDateFromInitialDate("2021-07-01"),
|
||||||
|
calcLocalDateFromInitialDate("2021-07-31"),
|
||||||
|
calcLocalDateFromInitialDate("2021-08-04"),
|
||||||
|
calcLocalDateFromInitialDate("2025-09-08"),
|
||||||
|
calcLocalDateFromInitialDate("2025-09-09"),
|
||||||
|
calcLocalDateFromInitialDate("2021-11-04"),
|
||||||
|
calcLocalDateFromInitialDate("2022-01-04"),
|
||||||
|
calcLocalDateFromInitialDate("2025-09-09"),
|
||||||
|
calcLocalDateFromInitialDate("2025-09-09"),
|
||||||
|
calcLocalDateFromInitialDate("2025-09-10"));
|
||||||
|
|
||||||
|
private static final String FILL_RU_PAYMT = String.format("""
|
||||||
|
INSERT INTO RU_PAYMT VALUES
|
||||||
|
(1, 1, null, '%s'),
|
||||||
|
(2, 2, 30, '%s'),
|
||||||
|
(3, 3, null, '%s'),
|
||||||
|
(3, 4, 100, '%s'),
|
||||||
|
(4, 5, 10, '%s'),
|
||||||
|
(5, 6, 10, '%s'),
|
||||||
|
(6, 7, 90, '%s'),
|
||||||
|
(6, 8, 80, '%s'),
|
||||||
|
(7, 9, null, '%s'),
|
||||||
|
(8, 10, null, '%s'),
|
||||||
|
(8, 11, 83, '%s'),
|
||||||
|
(8, 12, 91, '%s'),
|
||||||
|
(9, 13, 100, '%s')
|
||||||
|
""",
|
||||||
|
calcLocalDateFromInitialDate("2024-11-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-11-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-11-10"),
|
||||||
|
calcLocalDateFromInitialDate("2024-11-15"),
|
||||||
|
calcLocalDateFromInitialDate("2024-11-15"),
|
||||||
|
calcLocalDateFromInitialDate("2023-11-15"),
|
||||||
|
calcLocalDateFromInitialDate("2024-11-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-10-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-10-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-10-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-10-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-10-09"),
|
||||||
|
calcLocalDateFromInitialDate("2024-10-09"));
|
||||||
|
|
||||||
|
|
||||||
|
private DataSource dataSource;
|
||||||
|
private NamedParameterJdbcTemplate jdbcTemplate;
|
||||||
|
private FlagsService2 flagsService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
dataSource = DataSourceBuilder.create()
|
||||||
|
.url("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=DB2;DATABASE_TO_LOWER=TRUE")
|
||||||
|
.driverClassName("org.h2.Driver")
|
||||||
|
.username("sa")
|
||||||
|
.password("")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||||
|
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(RU_PASTDUEAREAR_DROP);
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(RU_PAYMT_DROP);
|
||||||
|
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(RU_PASTDUEAREAR_CREATE);
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(RU_PAYMT_CREATE);
|
||||||
|
|
||||||
|
flagsService = new FlagsService2(jdbcTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testfindFlags() {
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(FILL_RU_PASTDUEARREAR);
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(FILL_RU_PAYMT);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> resultMap = flagsService.findFlags(fids);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, resultMap.size());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(2).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlagDebt5000());
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(6).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(7).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(8).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(9).getFlag90days());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testfindFlagsWithoutRuPaymt() {
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(FILL_RU_PASTDUEARREAR);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> resultMap = flagsService.findFlags(fids);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, resultMap.size());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(2).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlagDebt5000());
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(3).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(7).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlag90days());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testfindFlagsWithoutRuPastduearreae() {
|
||||||
|
jdbcTemplate.getJdbcTemplate().execute(FILL_RU_PAYMT);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> resultMap = flagsService.findFlags(fids);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, resultMap.size());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(1).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(3).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(5).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlagDebt5000());
|
||||||
|
|
||||||
|
Assertions.assertEquals(0, resultMap.get(1).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(5).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(6).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(8).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(9).getFlag90days());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate calcLocalDateFromInitialDate(String date) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
long daysPassed = ChronoUnit.DAYS.between(INITIAL_DATE, now);
|
||||||
|
return LocalDate.parse(date).plusDays(daysPassed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,218 @@
|
||||||
|
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.Mockito;
|
||||||
|
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.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class FlagsServiceTest {
|
||||||
|
|
||||||
|
private static final LocalDate INITIAL_DATE = LocalDate.parse("2025-09-25");
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
FlagsMapper flagsMapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testfindFlags() {
|
||||||
|
FlagsService flagsService = new FlagsService(flagsMapper);
|
||||||
|
|
||||||
|
when(flagsMapper.findRuPastDuarearData(Mockito.anyList())).thenReturn(ruPastDuarearDataList);
|
||||||
|
when(flagsMapper.findRuPaymtData(Mockito.anyList(), Mockito.any())).thenReturn(ruPaymtDataList);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> resultMap = flagsService.findFlags(fids);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, resultMap.size());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(2).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlagDebt5000());
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(6).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(7).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(8).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(9).getFlag90days());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testfindFlagsWithoutRuPaymt() {
|
||||||
|
FlagsService flagsService = new FlagsService(flagsMapper);
|
||||||
|
|
||||||
|
when(flagsMapper.findRuPastDuarearData(Mockito.anyList())).thenReturn(ruPastDuarearDataList);
|
||||||
|
when(flagsMapper.findRuPaymtData(Mockito.anyList(), Mockito.any())).thenReturn(new ArrayList<>());
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> resultMap = flagsService.findFlags(fids);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, resultMap.size());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(2).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlagDebt5000());
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, resultMap.get(1).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(3).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(5).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(7).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlag90days());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testfindFlagsWithoutRuPastduearreae() {
|
||||||
|
FlagsService flagsService = new FlagsService(flagsMapper);
|
||||||
|
|
||||||
|
when(flagsMapper.findRuPastDuarearData(Mockito.anyList())).thenReturn(new ArrayList<>());
|
||||||
|
when(flagsMapper.findRuPaymtData(Mockito.anyList(), Mockito.any())).thenReturn(ruPaymtDataList);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<Integer, FlagsService.FlagsData> resultMap = flagsService.findFlags(fids);
|
||||||
|
|
||||||
|
Assertions.assertEquals(9, resultMap.size());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(1).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(3).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(5).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(6).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(8).getFlagDebt5000());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(9).getFlagDebt5000());
|
||||||
|
|
||||||
|
Assertions.assertEquals(0, resultMap.get(1).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(2).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(3).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(4).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(5).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(6).getFlag90days());
|
||||||
|
Assertions.assertEquals(0, resultMap.get(7).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(8).getFlag90days());
|
||||||
|
Assertions.assertEquals(1, resultMap.get(9).getFlag90days());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final List<FlagsService.RuPastDuarearData> ruPastDuarearDataList = new ArrayList<>(
|
||||||
|
List.of(
|
||||||
|
new FlagsService.RuPastDuarearData(1, BigInteger.valueOf(1), calcLocalDateFromInitialDate("2025-05-31"), BigDecimal.valueOf(36000.00), BigInteger.valueOf(159)), // просрочка 5000 и 90_days по этой записи
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), calcLocalDateFromInitialDate("2021-12-29"), BigDecimal.valueOf(3200.00), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), calcLocalDateFromInitialDate("2022-01-28"), BigDecimal.valueOf(6700.00), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), calcLocalDateFromInitialDate("2025-04-06"), BigDecimal.valueOf(5700.00), null), // просрочка 5000 по этой записи
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(3, BigInteger.valueOf(3), calcLocalDateFromInitialDate("2025-01-14"), BigDecimal.valueOf(300000000000.00), null),
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(2, BigInteger.valueOf(2), calcLocalDateFromInitialDate("2021-11-29"), BigDecimal.valueOf(0.00), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(4, BigInteger.valueOf(4), calcLocalDateFromInitialDate("2025-12-06"), BigDecimal.valueOf(4000.00), null), // нет просрочек
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-04-01"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(182)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-05-01"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(212)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-05-31"), BigDecimal.valueOf(2000.31), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-07-01"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(273)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-07-31"), BigDecimal.valueOf(2000.31), null), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-08-04"), BigDecimal.valueOf(7000.31), BigInteger.valueOf(307)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2025-09-08"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(338)), // не макс reported_date для того же acc_serial_num, просрочка 90_days будет взята у этой записи
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(51), calcLocalDateFromInitialDate("2025-09-09"), BigDecimal.valueOf(7000.31), BigInteger.valueOf(368)), // Просрочка 5000 будет взята у этой записи. Уникальный acc_serial_num с макс reported_dt
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2021-11-04"), BigDecimal.valueOf(2000.31), BigInteger.valueOf(399)), // не макс reported_date для того же acc_serial_num
|
||||||
|
new FlagsService.RuPastDuarearData(5, BigInteger.valueOf(5), calcLocalDateFromInitialDate("2022-01-04"), BigDecimal.valueOf(5000.31), BigInteger.valueOf(5)), // не макс reported_date для того же acc_serial_num
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(6, BigInteger.valueOf(6), calcLocalDateFromInitialDate("2025-09-09"), BigDecimal.valueOf(3000), null), // Нет просрочки 5000, нет просрочки 90_days (90_days будет в RU_PAYMT)
|
||||||
|
|
||||||
|
new FlagsService.RuPastDuarearData(7, BigInteger.valueOf(7), calcLocalDateFromInitialDate("2025-09-09"), BigDecimal.valueOf(5500), BigInteger.valueOf(90)), // не макс reported_date для того же acc_serial_num. 90_days будет взята отсюда
|
||||||
|
new FlagsService.RuPastDuarearData(7, BigInteger.valueOf(7), calcLocalDateFromInitialDate("2025-09-10"), BigDecimal.valueOf(3000), null) // Нет просрочки 5000. Уникальный acc_serial_num с макс reported_dt
|
||||||
|
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
private final List<FlagsService.RuPaymtData> ruPaymtDataList = new ArrayList<>(
|
||||||
|
List.of(
|
||||||
|
new FlagsService.RuPaymtData(1, null, calcLocalDateFromInitialDate("2024-11-09")),
|
||||||
|
new FlagsService.RuPaymtData(2, BigInteger.valueOf(30), calcLocalDateFromInitialDate("2024-11-09")),
|
||||||
|
new FlagsService.RuPaymtData(3, null, calcLocalDateFromInitialDate("2024-11-10")),
|
||||||
|
new FlagsService.RuPaymtData(3, BigInteger.valueOf(100), calcLocalDateFromInitialDate("2024-11-15")),
|
||||||
|
new FlagsService.RuPaymtData(4, BigInteger.valueOf(10), calcLocalDateFromInitialDate("2024-11-15")),
|
||||||
|
new FlagsService.RuPaymtData(5, BigInteger.valueOf(10), calcLocalDateFromInitialDate("2023-11-15")),
|
||||||
|
new FlagsService.RuPaymtData(6, BigInteger.valueOf(90), calcLocalDateFromInitialDate("2024-11-09")),
|
||||||
|
new FlagsService.RuPaymtData(6, BigInteger.valueOf(80), calcLocalDateFromInitialDate("2024-10-09")),
|
||||||
|
new FlagsService.RuPaymtData(7, null, calcLocalDateFromInitialDate("2024-10-09")),
|
||||||
|
new FlagsService.RuPaymtData(8, null, calcLocalDateFromInitialDate("2024-10-09")),
|
||||||
|
new FlagsService.RuPaymtData(8, BigInteger.valueOf(83), calcLocalDateFromInitialDate("2024-10-09")),
|
||||||
|
new FlagsService.RuPaymtData(8, BigInteger.valueOf(91), calcLocalDateFromInitialDate("2024-10-09")),
|
||||||
|
new FlagsService.RuPaymtData(9, BigInteger.valueOf(100), calcLocalDateFromInitialDate("2024-10-09"))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
private LocalDate calcLocalDateFromInitialDate(String date) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
long daysPassed = ChronoUnit.DAYS.between(INITIAL_DATE, now);
|
||||||
|
return LocalDate.parse(date).plusDays(daysPassed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
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 org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||||
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
|
import ru.nbch.credit_tracker.entities.dto.PhoneFidMap;
|
||||||
|
import ru.nbch.credit_tracker.service.indic.PhoneService2;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class PhoneService2Test {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
NamedParameterJdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defineFidByPhoneTest() {
|
||||||
|
PhoneService2 phoneService = new PhoneService2(jdbcTemplate);
|
||||||
|
|
||||||
|
fidsDataWithEqualSinceDt.sort(byDbOrder);
|
||||||
|
when(jdbcTemplate.query(anyString(), any(MapSqlParameterSource.class), any(RowMapper.class))).thenReturn(fidsDataWithEqualSinceDt);
|
||||||
|
|
||||||
|
List<PhoneFidMap> phoneFidMap = new ArrayList<>();
|
||||||
|
phoneFidMap.add(PhoneFidMap.builder().phone("1111").build());
|
||||||
|
phoneFidMap.add(PhoneFidMap.builder().phone("1112").build());
|
||||||
|
phoneFidMap.add(PhoneFidMap.builder().phone("1113").build());
|
||||||
|
phoneFidMap.add(PhoneFidMap.builder().phone("1114").build());
|
||||||
|
|
||||||
|
Map<Integer, PhoneFidMap> res = phoneService.defineFidByPhone(phoneFidMap);
|
||||||
|
Assertions.assertEquals(3, res.size());
|
||||||
|
Assertions.assertEquals("1111", res.get(124).getPhone());
|
||||||
|
Assertions.assertEquals("1112", res.get(125).getPhone());
|
||||||
|
Assertions.assertEquals("1114", res.get(126).getPhone());
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<PhoneService2.FidsData> fidsDataWithEqualSinceDt = new ArrayList<>(
|
||||||
|
List.of(
|
||||||
|
new PhoneService2.FidsData(123, "91111", LocalDate.of(2025, 9, 10)),
|
||||||
|
new PhoneService2.FidsData(124, "91111", LocalDate.of(2025, 9, 10)),
|
||||||
|
new PhoneService2.FidsData(125, "91112", LocalDate.of(2024, 10, 10)),
|
||||||
|
new PhoneService2.FidsData(126, "91114", LocalDate.of(2024, 10, 11))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Comparator<PhoneService2.FidsData> byDbOrder =
|
||||||
|
Comparator.comparing(PhoneService2.FidsData::getPhone, Comparator.nullsFirst(Comparator.naturalOrder())) // pn.number ASC
|
||||||
|
.thenComparing(PhoneService2.FidsData::getFileSinceDate, Comparator.nullsLast(Comparator.reverseOrder())) // file_since_dt DESC
|
||||||
|
.thenComparing(PhoneService2.FidsData::getFid, Comparator.reverseOrder());
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue