- изменена БД: добавлены новые поля, флаги вынесены в отдельную таблицу.
This commit is contained in:
parent
4cfdd75dd9
commit
89f6d58f98
17 changed files with 241 additions and 215 deletions
20
src/main/java/ru/nbch/credit_tracker/config/AppConfig.java
Normal file
20
src/main/java/ru/nbch/credit_tracker/config/AppConfig.java
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
package ru.nbch.credit_tracker.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class AppConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ObjectMapper entityToJsonMapper() {
|
||||||
|
return new ObjectMapper()
|
||||||
|
.registerModule(new JavaTimeModule())
|
||||||
|
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
||||||
|
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,9 @@ import java.util.function.Supplier;
|
||||||
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 ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.PartFilePayload;
|
import ru.nbch.credit_tracker.model.impl.PartFilePayload;
|
||||||
import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload;
|
import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.service.indic.FlagsService2;
|
|
||||||
import ru.nbch.credit_tracker.service.task.impl.FlagsEnricher;
|
|
||||||
import ru.nbch.credit_tracker.service.task.impl.KickPipeLineImpl;
|
import ru.nbch.credit_tracker.service.task.impl.KickPipeLineImpl;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.XmlMergeCoordinator;
|
import ru.nbch.credit_tracker.service.task.impl.XmlMergeCoordinator;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
||||||
|
|
@ -28,9 +25,4 @@ public class PipelineStarterConfig {
|
||||||
public Supplier<IPipeLineTerminator<PartFilePayload, SignalXmlFilePayload>> pipelineTerminatorFactory(CreditTrackerSettings creditTrackerSettings) {
|
public Supplier<IPipeLineTerminator<PartFilePayload, SignalXmlFilePayload>> pipelineTerminatorFactory(CreditTrackerSettings creditTrackerSettings) {
|
||||||
return () -> new XmlMergeCoordinator(creditTrackerSettings);
|
return () -> new XmlMergeCoordinator(creditTrackerSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Supplier<FlagsEnricher> flagEnricherFactory(FlagsService2 flagsService, PhoneFidMapMapper mapper) {
|
|
||||||
return () -> new FlagsEnricher(flagsService, mapper);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package ru.nbch.credit_tracker.entities.app;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class FlagDetail {
|
||||||
|
private Long id;
|
||||||
|
private Long mapId;
|
||||||
|
private Long packageId;
|
||||||
|
private String subjectId;
|
||||||
|
private String phone;
|
||||||
|
private Integer fid;
|
||||||
|
private Integer flagDebt5000;
|
||||||
|
private Integer flag90days;
|
||||||
|
private LocalDateTime calculatedAt;
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ import ru.nbch.credit_tracker.entities.indic.PaymentsFlag;
|
||||||
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface FlagsMapper {
|
public interface IndicFlagsMapper {
|
||||||
List<FlagsService.RuPastDuarearData> findRuPastDuarearData(@Param("fids") List<Integer> fids);
|
List<FlagsService.RuPastDuarearData> findRuPastDuarearData(@Param("fids") List<Integer> fids);
|
||||||
|
|
||||||
List<FlagsService.RuPaymtData> findRuPaymtData(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
List<FlagsService.RuPaymtData> findRuPaymtData(@Param("fids") List<Integer> fids, @Param("reportedDate") LocalDate reportedDate);
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ru.nbch.credit_tracker.mapper.signal;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface FlagDetailMapper {
|
||||||
|
void registerCalcFlags(@Param("json") String json);
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ public interface PhoneFidMapMapper {
|
||||||
|
|
||||||
void registerSubjects(@Param("subjects") List<Subject> subjects, @Param("packageId") Long packageId);
|
void registerSubjects(@Param("subjects") List<Subject> subjects, @Param("packageId") Long packageId);
|
||||||
void register(@Param("phoneFidMap") List<PhoneFidMap> phoneFidMap);
|
void register(@Param("phoneFidMap") List<PhoneFidMap> phoneFidMap);
|
||||||
void registerJson(@Param("json") String json);
|
List<Long> registerJson(@Param("json") String json);
|
||||||
void registerWithId(@Param("phoneFidMap") List<PhoneFidMap> phoneFidMap);
|
void registerWithId(@Param("phoneFidMap") List<PhoneFidMap> phoneFidMap);
|
||||||
|
|
||||||
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Long packageId, @Param("offset") int offset, @Param("limit") int limit);
|
List<PhoneFidMap> findFullPhoneFidMap(@Param("packageId") Long packageId, @Param("offset") int offset, @Param("limit") int limit);
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import lombok.Setter;
|
||||||
@Builder
|
@Builder
|
||||||
public class SubjectProfile {
|
public class SubjectProfile {
|
||||||
private String identifier;
|
private String identifier;
|
||||||
|
private Long mapId;
|
||||||
private String phone;
|
private String phone;
|
||||||
private Integer fid;
|
private Integer fid;
|
||||||
private NameData nameData;
|
private NameData nameData;
|
||||||
private IdData idData;
|
private IdData idData;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.nbch.credit_tracker.mapper.indic.FlagsMapper;
|
import ru.nbch.credit_tracker.mapper.indic.IndicFlagsMapper;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
@ -24,7 +24,7 @@ import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
public class FlagsService {
|
public class FlagsService {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(FlagsService.class);
|
private static final Logger log = LoggerFactory.getLogger(FlagsService.class);
|
||||||
private final FlagsMapper mapper;
|
private final IndicFlagsMapper mapper;
|
||||||
|
|
||||||
private static final String SELECT_RU_PASDUEARREAR_DATA =
|
private static final String SELECT_RU_PASDUEARREAR_DATA =
|
||||||
"SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE, DAYS_PAST_DUE " +
|
"SELECT FID, ACC_SERIAL_NUM, REPORTED_DT, AMT_PAST_DUE, DAYS_PAST_DUE " +
|
||||||
|
|
@ -42,7 +42,7 @@ public class FlagsService {
|
||||||
|
|
||||||
private final NamedParameterJdbcTemplate jdbcTemplate;
|
private final NamedParameterJdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
public FlagsService(FlagsMapper mapper,
|
public FlagsService(IndicFlagsMapper mapper,
|
||||||
@Qualifier("jdbcTemplateIndic") NamedParameterJdbcTemplate jdbcTemplate) {
|
@Qualifier("jdbcTemplateIndic") NamedParameterJdbcTemplate jdbcTemplate) {
|
||||||
this.mapper = mapper;
|
this.mapper = mapper;
|
||||||
this.jdbcTemplate = jdbcTemplate;
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,32 @@
|
||||||
package ru.nbch.credit_tracker.service.indic;
|
package ru.nbch.credit_tracker.service.indic;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
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.app.FlagDetail;
|
||||||
import ru.nbch.credit_tracker.entities.indic.PaymentsFlag;
|
import ru.nbch.credit_tracker.entities.indic.PaymentsFlag;
|
||||||
import ru.nbch.credit_tracker.mapper.indic.FlagsMapper;
|
import ru.nbch.credit_tracker.mapper.indic.IndicFlagsMapper;
|
||||||
|
import ru.nbch.credit_tracker.mapper.signal.FlagDetailMapper;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class FlagsService2 {
|
public class FlagsService2 {
|
||||||
private final FlagsMapper flagsMapper;
|
private final IndicFlagsMapper flagsMapper;
|
||||||
|
private final FlagDetailMapper flagDetailMapper;
|
||||||
|
private final ObjectMapper entityToJsonMapper;
|
||||||
|
|
||||||
public FlagsService2(FlagsMapper flagsMapper) {
|
public FlagsService2(IndicFlagsMapper flagsMapper,
|
||||||
|
FlagDetailMapper flagDetailMapper,
|
||||||
|
ObjectMapper entityToJsonMapper) {
|
||||||
this.flagsMapper = flagsMapper;
|
this.flagsMapper = flagsMapper;
|
||||||
|
this.flagDetailMapper = flagDetailMapper;
|
||||||
|
this.entityToJsonMapper = entityToJsonMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, Integer> findFlagsDebt5000(List<Integer> fids) {
|
public Map<Integer, Integer> findFlagsDebt5000(List<Integer> fids) {
|
||||||
|
|
@ -33,5 +44,25 @@ public class FlagsService2 {
|
||||||
.collect(Collectors.toMap(PaymentsFlag::getFid, PaymentsFlag::getFlag));
|
.collect(Collectors.toMap(PaymentsFlag::getFid, PaymentsFlag::getFlag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void registerCalculationFlags(List<FlagDetail> flagDetails) {
|
||||||
|
try {
|
||||||
|
//fixme, временное решение
|
||||||
|
String jsonFlagDetail = entityToJsonMapper.writeValueAsString(flagDetails.stream()
|
||||||
|
.map(flagDetail -> new HashMap<String, Object>() {{
|
||||||
|
put("subject_id", flagDetail.getSubjectId());
|
||||||
|
put("fid", flagDetail.getFid());
|
||||||
|
put("phone", flagDetail.getPhone());
|
||||||
|
put("map_id", flagDetail.getMapId());
|
||||||
|
put("package_id", flagDetail.getPackageId());
|
||||||
|
put("flag_debt5000", flagDetail.getFlagDebt5000());
|
||||||
|
put("flag_90_12", flagDetail.getFlag90days());
|
||||||
|
put("calculated_at", flagDetail.getCalculatedAt());
|
||||||
|
}}).toList());
|
||||||
|
flagDetailMapper.registerCalcFlags(jsonFlagDetail);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package ru.nbch.credit_tracker.service.indic;
|
package ru.nbch.credit_tracker.service.indic;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BinaryOperator;
|
import java.util.function.BinaryOperator;
|
||||||
|
|
@ -8,7 +11,9 @@ import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
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.app.PhoneFidMap;
|
||||||
import ru.nbch.credit_tracker.entities.indic.Name;
|
import ru.nbch.credit_tracker.entities.indic.Name;
|
||||||
|
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
||||||
import ru.nbch.credit_tracker.model.SubjectProfile;
|
import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
import ru.nbch.credit_tracker.repository.PhoneRepository;
|
import ru.nbch.credit_tracker.repository.PhoneRepository;
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
|
@ -18,16 +23,23 @@ import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
public class PhoneService2 {
|
public class PhoneService2 {
|
||||||
|
|
||||||
private final PhoneRepository phoneRepository;
|
private final PhoneRepository phoneRepository;
|
||||||
|
private final PhoneFidMapMapper phoneFidMapMapper;
|
||||||
|
private final ObjectMapper entityToJsonMapper;
|
||||||
private final Comparator<Name> byDateThenIdNullSafe =
|
private final Comparator<Name> byDateThenIdNullSafe =
|
||||||
Comparator.comparing(Name::getFileSinceDate, Comparator.nullsFirst(Comparator.naturalOrder()))
|
Comparator.comparing(Name::getFileSinceDate, Comparator.nullsFirst(Comparator.naturalOrder()))
|
||||||
.thenComparing(Name::getFid);
|
.thenComparing(Name::getFid);
|
||||||
|
|
||||||
public PhoneService2(PhoneRepository phoneRepository) {
|
public PhoneService2(PhoneRepository phoneRepository,
|
||||||
|
PhoneFidMapMapper phoneFidMapMapper,
|
||||||
|
ObjectMapper entityToJsonMapper) {
|
||||||
this.phoneRepository = phoneRepository;
|
this.phoneRepository = phoneRepository;
|
||||||
|
this.phoneFidMapMapper = phoneFidMapMapper;
|
||||||
|
this.entityToJsonMapper = entityToJsonMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Поиск данных по таблицам PHONE_NORM и NAME по списку номеров телефонов
|
* Поиск данных по таблицам PHONE_NORM и NAME по списку номеров телефонов
|
||||||
|
*
|
||||||
* @param subjects
|
* @param subjects
|
||||||
* @return - отображение NAME к номеру телефону, отфильтрованному по логике
|
* @return - отображение NAME к номеру телефону, отфильтрованному по логике
|
||||||
* FID с максимальным значением FILE_SINCE_DT. Если FILE_SINCE_DT оказался одинаковый, берется максимальный FID
|
* FID с максимальным значением FILE_SINCE_DT. Если FILE_SINCE_DT оказался одинаковый, берется максимальный FID
|
||||||
|
|
@ -46,4 +58,21 @@ public class PhoneService2 {
|
||||||
BinaryOperator.maxBy(byDateThenIdNullSafe)
|
BinaryOperator.maxBy(byDateThenIdNullSafe)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Long> registerSubjects(List<PhoneFidMap> subjects) {
|
||||||
|
try {
|
||||||
|
//fixme, временное решение
|
||||||
|
String json = entityToJsonMapper.writeValueAsString(subjects.stream()
|
||||||
|
.map(phoneFidMap -> new HashMap<String, Object>() {{
|
||||||
|
put("subject_id", phoneFidMap.getSubjectId());
|
||||||
|
put("fid", phoneFidMap.getFid());
|
||||||
|
put("phone", phoneFidMap.getPhone());
|
||||||
|
put("package_id", phoneFidMap.getPackageId());
|
||||||
|
put("calculated_at", phoneFidMap.getCalculatedAt());
|
||||||
|
}}).toList());
|
||||||
|
return phoneFidMapMapper.registerJson(json);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
|
||||||
import ru.nbch.credit_tracker.model.SubjectProfile;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
|
||||||
import ru.nbch.credit_tracker.service.indic.FlagsService2;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class FlagsEnricher implements Runnable {
|
|
||||||
|
|
||||||
private final FlagsService2 flagsService;
|
|
||||||
private final PhoneFidMapMapper phoneFidMapMapper;
|
|
||||||
private BlockingQueue<SubjectPayload> in;
|
|
||||||
private final CompletableFuture<Void> done = new CompletableFuture<>();
|
|
||||||
private final ExecutorService ioPool;
|
|
||||||
private final ObjectMapper mapper = new ObjectMapper()
|
|
||||||
.registerModule(new JavaTimeModule())
|
|
||||||
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
|
|
||||||
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
|
||||||
|
|
||||||
public FlagsEnricher(FlagsService2 flagsService,
|
|
||||||
PhoneFidMapMapper phoneFidMapMapper) {
|
|
||||||
this.flagsService = flagsService;
|
|
||||||
this.phoneFidMapMapper = phoneFidMapMapper;
|
|
||||||
this.ioPool = new ThreadPoolExecutor(10,
|
|
||||||
10,
|
|
||||||
0L, TimeUnit.MINUTES,
|
|
||||||
new LinkedBlockingQueue<>(),
|
|
||||||
r -> {
|
|
||||||
Thread t = new Thread(r);
|
|
||||||
t.setName("queue-handler-%s-%d".formatted(this.getClass().getSimpleName(), t.threadId()));
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
List<Future<?>> inFlight = new ArrayList<>();
|
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
|
||||||
try {
|
|
||||||
SubjectPayload subjectPayload = in.poll(5, TimeUnit.SECONDS);
|
|
||||||
if (subjectPayload == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (subjectPayload.isPoison()) {
|
|
||||||
log.debug("Got poison");
|
|
||||||
for (Future<?> f : inFlight) {
|
|
||||||
f.get();
|
|
||||||
}
|
|
||||||
done.complete(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
inFlight.add(ioPool.submit(() -> process(subjectPayload)));
|
|
||||||
} catch (InterruptedException ie) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error: {}", ExceptionUtils.getStackTrace(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void process(SubjectPayload subjectPayload) {
|
|
||||||
List<SubjectProfile> subjects = subjectPayload.getSubjects();
|
|
||||||
log.debug("FlagsEnricher handle by packageId: {}, size: {}", subjectPayload.getPackageId(), subjects.size());
|
|
||||||
|
|
||||||
List<Integer> fids = subjects.stream()
|
|
||||||
.map(SubjectProfile::getFid)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.toList();
|
|
||||||
LocalDate yearAgo = LocalDate.now().minusYears(1);
|
|
||||||
|
|
||||||
Map<Integer, Integer> flagsDebt5000 = flagsService.findFlagsDebt5000(fids);
|
|
||||||
Map<Integer, Integer> flag90ByPastDueArrear = flagsService.findFlag90ByPastDueArrear(fids, yearAgo);
|
|
||||||
Map<Integer, Integer> flag90ByRuPaymt = flagsService.findFlag90ByRuPaymt(fids, yearAgo);
|
|
||||||
|
|
||||||
String json;
|
|
||||||
try {
|
|
||||||
json = mapper.writeValueAsString(subjects.stream().map(subject -> {
|
|
||||||
Integer debt5000 = null;
|
|
||||||
Integer flagDays90 = null;
|
|
||||||
LocalDateTime calculatedAt = null;
|
|
||||||
|
|
||||||
if (subject.getFid() != null) {
|
|
||||||
debt5000 = flagsDebt5000.getOrDefault(subject.getFid(), 0);
|
|
||||||
int pastDue90 = flag90ByPastDueArrear.getOrDefault(subject.getFid(), 0);
|
|
||||||
int paymt90 = flag90ByRuPaymt.getOrDefault(subject.getFid(), 0);
|
|
||||||
flagDays90 = Math.max(pastDue90, paymt90);
|
|
||||||
calculatedAt = LocalDateTime.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
Integer finalDebt500 = debt5000;
|
|
||||||
Integer finalFlagDays9 = flagDays90;
|
|
||||||
LocalDateTime finalCalculatedAt = calculatedAt;
|
|
||||||
return new HashMap<String, Object>() {{
|
|
||||||
put("subject_id", subject.getIdentifier());
|
|
||||||
put("fid", subject.getFid());
|
|
||||||
put("phone", subject.getPhone());
|
|
||||||
put("package_id", subjectPayload.getPackageId());
|
|
||||||
put("flag_debt5000", finalDebt500);
|
|
||||||
put("flag_90_12", finalFlagDays9);
|
|
||||||
put("calculated_at", finalCalculatedAt);
|
|
||||||
}};
|
|
||||||
}).toList());
|
|
||||||
} catch (JsonProcessingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
phoneFidMapMapper.registerJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPollingQueue(BlockingQueue<SubjectPayload> queue) {
|
|
||||||
this.in = queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompletableFuture<Void> doneFuture() {
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
package ru.nbch.credit_tracker.service.task.impl;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
@ -12,12 +14,9 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
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.app.FlagDetail;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
||||||
import ru.nbch.credit_tracker.model.SubjectProfile;
|
import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
|
|
@ -28,7 +27,6 @@ import ru.nbch.credit_tracker.service.indic.FlagsService2;
|
||||||
public class FlagsEnricherV2 implements Consumer<SubjectPayload> {
|
public class FlagsEnricherV2 implements Consumer<SubjectPayload> {
|
||||||
|
|
||||||
private final FlagsService2 flagsService;
|
private final FlagsService2 flagsService;
|
||||||
private final PhoneFidMapMapper phoneFidMapMapper;
|
|
||||||
private final ExecutorService ioPool;
|
private final ExecutorService ioPool;
|
||||||
private final ObjectMapper mapper = new ObjectMapper()
|
private final ObjectMapper mapper = new ObjectMapper()
|
||||||
.registerModule(new JavaTimeModule())
|
.registerModule(new JavaTimeModule())
|
||||||
|
|
@ -38,7 +36,6 @@ public class FlagsEnricherV2 implements Consumer<SubjectPayload> {
|
||||||
public FlagsEnricherV2(FlagsService2 flagsService,
|
public FlagsEnricherV2(FlagsService2 flagsService,
|
||||||
PhoneFidMapMapper phoneFidMapMapper) {
|
PhoneFidMapMapper phoneFidMapMapper) {
|
||||||
this.flagsService = flagsService;
|
this.flagsService = flagsService;
|
||||||
this.phoneFidMapMapper = phoneFidMapMapper;
|
|
||||||
this.ioPool = new ThreadPoolExecutor(10,
|
this.ioPool = new ThreadPoolExecutor(10,
|
||||||
10,
|
10,
|
||||||
0L, TimeUnit.MINUTES,
|
0L, TimeUnit.MINUTES,
|
||||||
|
|
@ -66,9 +63,7 @@ public class FlagsEnricherV2 implements Consumer<SubjectPayload> {
|
||||||
Map<Integer, Integer> flag90ByPastDueArrear = flagsService.findFlag90ByPastDueArrear(fids, yearAgo);
|
Map<Integer, Integer> flag90ByPastDueArrear = flagsService.findFlag90ByPastDueArrear(fids, yearAgo);
|
||||||
Map<Integer, Integer> flag90ByRuPaymt = flagsService.findFlag90ByRuPaymt(fids, yearAgo);
|
Map<Integer, Integer> flag90ByRuPaymt = flagsService.findFlag90ByRuPaymt(fids, yearAgo);
|
||||||
|
|
||||||
String json;
|
List<FlagDetail> flagDetails = subjects.stream().map(subject -> {
|
||||||
try {
|
|
||||||
json = mapper.writeValueAsString(subjects.stream().map(subject -> {
|
|
||||||
Integer debt5000 = null;
|
Integer debt5000 = null;
|
||||||
Integer flagDays90 = null;
|
Integer flagDays90 = null;
|
||||||
LocalDateTime calculatedAt = null;
|
LocalDateTime calculatedAt = null;
|
||||||
|
|
@ -84,28 +79,25 @@ public class FlagsEnricherV2 implements Consumer<SubjectPayload> {
|
||||||
Integer finalDebt500 = debt5000;
|
Integer finalDebt500 = debt5000;
|
||||||
Integer finalFlagDays9 = flagDays90;
|
Integer finalFlagDays9 = flagDays90;
|
||||||
LocalDateTime finalCalculatedAt = calculatedAt;
|
LocalDateTime finalCalculatedAt = calculatedAt;
|
||||||
return new HashMap<String, Object>() {{
|
|
||||||
put("subject_id", subject.getIdentifier());
|
return FlagDetail.builder()
|
||||||
put("fid", subject.getFid());
|
.mapId(subject.getMapId())
|
||||||
put("phone", subject.getPhone());
|
.subjectId(subject.getIdentifier())
|
||||||
put("package_id", subjectPayload.getPackageId());
|
.packageId(subjectPayload.getPackageId())
|
||||||
put("flag_debt5000", finalDebt500);
|
.fid(subject.getFid())
|
||||||
put("flag_90_12", finalFlagDays9);
|
.phone(subject.getPhone())
|
||||||
put("calculated_at", finalCalculatedAt);
|
.flagDebt5000(finalDebt500)
|
||||||
}};
|
.flag90days(finalFlagDays9)
|
||||||
}).toList());
|
.calculatedAt(finalCalculatedAt)
|
||||||
} catch (JsonProcessingException e) {
|
.build();
|
||||||
throw new RuntimeException(e);
|
}).toList();
|
||||||
}
|
flagsService.registerCalculationFlags(flagDetails);
|
||||||
phoneFidMapMapper.registerJson(json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(SubjectPayload subjectPayload) {
|
public void accept(SubjectPayload subjectPayload) {
|
||||||
ThreadPoolExecutor casted = (ThreadPoolExecutor) ioPool;
|
ThreadPoolExecutor casted = (ThreadPoolExecutor) ioPool;
|
||||||
log.info("submitting payload. active tasks number: {}; queue size: {}", casted.getActiveCount(), casted.getQueue().size());
|
log.info("submitting payload. active tasks number: {}; queue size: {}", casted.getActiveCount(), casted.getQueue().size());
|
||||||
this.ioPool.submit(() -> {
|
this.ioPool.submit(() -> process(subjectPayload));
|
||||||
process(subjectPayload);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
package ru.nbch.credit_tracker.service.task.impl;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
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.app.PhoneFidMap;
|
||||||
import ru.nbch.credit_tracker.entities.indic.Name;
|
import ru.nbch.credit_tracker.entities.indic.Name;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
import ru.nbch.credit_tracker.mapper.signal.PhoneFidMapMapper;
|
||||||
import ru.nbch.credit_tracker.model.NameData;
|
import ru.nbch.credit_tracker.model.NameData;
|
||||||
|
|
@ -36,9 +38,9 @@ public class SaveSubjectHandler implements Handler<SubjectPayload, SubjectPayloa
|
||||||
Long packageId = taskPayload.getPackageId();
|
Long packageId = taskPayload.getPackageId();
|
||||||
log.debug("SaveSubjectStage handle by packageId: {}, size of bucket for save: {}", taskPayload.getPackageId(), subjects.size());
|
log.debug("SaveSubjectStage handle by packageId: {}, size of bucket for save: {}", taskPayload.getPackageId(), subjects.size());
|
||||||
|
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
Map<String, Name> nameByPhone = phoneService2.findNameByNumber(subjects);
|
Map<String, Name> nameByPhone = phoneService2.findNameByNumber(subjects);
|
||||||
//todo сделать один проход для установки FID для вставки в PHONE_FID_MAP и одновременного заполнения инфо из Name для дальнейшей обработки
|
List<PhoneFidMap> subjectForSave = subjects.stream().map(subject -> {
|
||||||
subjects.forEach(subject -> {
|
|
||||||
Name name = nameByPhone.get(CTUtil.normalizePhoneNumber(subject.getPhone()));
|
Name name = nameByPhone.get(CTUtil.normalizePhoneNumber(subject.getPhone()));
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
NameData nameData = NameData.builder()
|
NameData nameData = NameData.builder()
|
||||||
|
|
@ -52,8 +54,20 @@ public class SaveSubjectHandler implements Handler<SubjectPayload, SubjectPayloa
|
||||||
subject.setFid(name.getFid());
|
subject.setFid(name.getFid());
|
||||||
subject.setNameData(nameData);
|
subject.setNameData(nameData);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
//todo стоит ли делать имутабл для subject?
|
return PhoneFidMap.builder()
|
||||||
|
.subjectId(subject.getIdentifier())
|
||||||
|
.packageId(packageId)
|
||||||
|
.phone(subject.getPhone())
|
||||||
|
.fid(subject.getFid())
|
||||||
|
.calculatedAt(now)
|
||||||
|
.build();
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
List<Long> ids = phoneService2.registerSubjects(subjectForSave);
|
||||||
|
for (int i = 0; i < subjects.size(); i++) {
|
||||||
|
subjects.get(i).setMapId(ids.get(i));
|
||||||
|
}
|
||||||
return new SubjectPayload(taskPayload.getPackageId(), subjects);
|
return new SubjectPayload(taskPayload.getPackageId(), subjects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
<mapper namespace="ru.nbch.credit_tracker.mapper.indic.FlagsMapper">
|
<mapper namespace="ru.nbch.credit_tracker.mapper.indic.IndicFlagsMapper">
|
||||||
|
|
||||||
<resultMap id="RuPastDuarearResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$RuPastDuarearData">
|
<resultMap id="RuPastDuarearResultMap" type="ru.nbch.credit_tracker.service.indic.FlagsService$RuPastDuarearData">
|
||||||
<result property="fid" column="fid" />
|
<result property="fid" column="fid" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="ru.nbch.credit_tracker.mapper.signal.FlagDetailMapper">
|
||||||
|
|
||||||
|
<insert id="registerCalcFlags" parameterType="string">
|
||||||
|
INSERT INTO signals_flags
|
||||||
|
(map_id, subject_id, fid, phone, flag_debt5000, flag_90_12, calculated_at)
|
||||||
|
SELECT map_id, subject_id, fid, phone, flag_debt5000, flag_90_12, calculated_at
|
||||||
|
FROM json_to_recordset(#{json}::json) AS t(
|
||||||
|
map_id bigint,
|
||||||
|
subject_id varchar(255),
|
||||||
|
fid int,
|
||||||
|
phone text,
|
||||||
|
flag_debt5000 smallint,
|
||||||
|
flag_90_12 smallint,
|
||||||
|
calculated_at timestamp)
|
||||||
|
</insert>
|
||||||
|
</mapper>
|
||||||
|
|
@ -33,10 +33,31 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<insert id="registerJson" parameterType="string">
|
<!-- <insert id="registerJson" parameterType="string">-->
|
||||||
INSERT INTO signals_phone_fid_map
|
<!-- INSERT INTO signals_phone_fid_map-->
|
||||||
(subject_id, fid, phone, package_id, flag_debt5000, flag_90_12, calculated_at)
|
<!-- (subject_id, fid, phone, package_id, flag_debt5000, flag_90_12, calculated_at)-->
|
||||||
SELECT subject_id, fid, phone, package_id, flag_debt5000, flag_90_12, calculated_at
|
<!-- SELECT subject_id, fid, phone, package_id, flag_debt5000, flag_90_12, calculated_at-->
|
||||||
|
<!-- FROM json_to_recordset(#{json}::json) AS t(-->
|
||||||
|
<!-- subject_id varchar(255),-->
|
||||||
|
<!-- fid int,-->
|
||||||
|
<!-- phone text,-->
|
||||||
|
<!-- package_id bigint,-->
|
||||||
|
<!-- flag_debt5000 smallint,-->
|
||||||
|
<!-- flag_90_12 smallint,-->
|
||||||
|
<!-- calculated_at timestamp)-->
|
||||||
|
<!-- </insert>-->
|
||||||
|
|
||||||
|
<select id="registerJson" parameterType="string" resultType="long">
|
||||||
|
WITH src AS (
|
||||||
|
SELECT
|
||||||
|
row_number() OVER () AS rn,
|
||||||
|
subject_id,
|
||||||
|
fid,
|
||||||
|
phone,
|
||||||
|
package_id,
|
||||||
|
flag_debt5000,
|
||||||
|
flag_90_12,
|
||||||
|
calculated_at
|
||||||
FROM json_to_recordset(#{json}::json) AS t(
|
FROM json_to_recordset(#{json}::json) AS t(
|
||||||
subject_id varchar(255),
|
subject_id varchar(255),
|
||||||
fid int,
|
fid int,
|
||||||
|
|
@ -44,8 +65,23 @@
|
||||||
package_id bigint,
|
package_id bigint,
|
||||||
flag_debt5000 smallint,
|
flag_debt5000 smallint,
|
||||||
flag_90_12 smallint,
|
flag_90_12 smallint,
|
||||||
calculated_at timestamp)
|
calculated_at timestamp
|
||||||
</insert>
|
)
|
||||||
|
)
|
||||||
|
INSERT INTO signals_phone_fid_map
|
||||||
|
(subject_id, fid, phone, package_id, flag_debt5000, flag_90_12, calculated_at)
|
||||||
|
SELECT
|
||||||
|
subject_id,
|
||||||
|
fid,
|
||||||
|
phone,
|
||||||
|
package_id,
|
||||||
|
flag_debt5000,
|
||||||
|
flag_90_12,
|
||||||
|
calculated_at
|
||||||
|
FROM src
|
||||||
|
ORDER BY rn
|
||||||
|
RETURNING id;
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="registerWithId" parameterType="java.util.List" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
<insert id="registerWithId" parameterType="java.util.List" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||||
INSERT INTO signals_phone_fid_map (subject_id, phone, package_id)
|
INSERT INTO signals_phone_fid_map (subject_id, phone, package_id)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import ru.nbch.credit_tracker.mapper.indic.FlagsMapper;
|
import ru.nbch.credit_tracker.mapper.indic.IndicFlagsMapper;
|
||||||
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
import ru.nbch.credit_tracker.service.indic.FlagsService;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -26,7 +26,7 @@ public class FlagsServiceTest {
|
||||||
private static final LocalDate INITIAL_DATE = LocalDate.parse("2025-09-25");
|
private static final LocalDate INITIAL_DATE = LocalDate.parse("2025-09-25");
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
FlagsMapper flagsMapper;
|
IndicFlagsMapper flagsMapper;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testfindFlags() {
|
public void testfindFlags() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue