From f4b49c06ed0fe0259950d4fca72cc9290302fc3e Mon Sep 17 00:00:00 2001 From: Mikhail Trofimov Date: Mon, 6 Oct 2025 10:21:37 +0300 Subject: [PATCH] Added processSubjects method to SignalService; Load Name data with fids in PhoneService2 --- .../entities/dto/PhoneFidMap.java | 8 ++ .../repository/PhoneRepository.java | 53 +++++++++++++ .../credit_tracker/service/SignalService.java | 19 +++++ .../service/indic/PhoneService2.java | 79 +++++++++++++++++++ .../service/PhoneService2Test.java | 64 ++++++++++++++- 5 files changed, 220 insertions(+), 3 deletions(-) diff --git a/src/main/java/ru/nbch/credit_tracker/entities/dto/PhoneFidMap.java b/src/main/java/ru/nbch/credit_tracker/entities/dto/PhoneFidMap.java index 0ed7836..39f9200 100644 --- a/src/main/java/ru/nbch/credit_tracker/entities/dto/PhoneFidMap.java +++ b/src/main/java/ru/nbch/credit_tracker/entities/dto/PhoneFidMap.java @@ -2,6 +2,7 @@ package ru.nbch.credit_tracker.entities.dto; import lombok.*; +import java.time.LocalDate; import java.time.LocalDateTime; @Getter @@ -19,4 +20,11 @@ public class PhoneFidMap { private Integer flag90days; private LocalDateTime calculatedAt; private String errorText; + + // NAME data + private String firstName; + private String lastName; + private String middleName; + private LocalDate birthDate; + private LocalDate fileSinceDate; } diff --git a/src/main/java/ru/nbch/credit_tracker/repository/PhoneRepository.java b/src/main/java/ru/nbch/credit_tracker/repository/PhoneRepository.java index de2a326..b3615ee 100644 --- a/src/main/java/ru/nbch/credit_tracker/repository/PhoneRepository.java +++ b/src/main/java/ru/nbch/credit_tracker/repository/PhoneRepository.java @@ -31,6 +31,27 @@ public class PhoneRepository { WITH UR """; + private static final String SELCT_FIDS_WITH_NAME = """ + SELECT + pn.number, + pn.fid, + pn.file_since_dt, + nf.first, + nf.middle, + nf.name_1, + nf.birth_dt, + nf.file_since_dt as file_since_dt_name + FROM PHONE_NORM pn + JOIN 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 PhoneRepository(@Qualifier("jdbcTemplateIndic") NamedParameterJdbcTemplate jdbcTemplate) { @@ -47,6 +68,23 @@ public class PhoneRepository { ); } + public List findFidsWithName(List phones) { + MapSqlParameterSource params = new MapSqlParameterSource(); + params.addValue("phones", phones); + + return jdbcTemplate.query(SELCT_FIDS_WITH_NAME, params, (rs, rowNum) -> + new PhoneRepository.FidsDataWithName( + rs.getInt("FID"), + rs.getString("NUMBER"), + rs.getObject("FILE_SINCE_DT", LocalDate.class), + rs.getString("FIRST"), + rs.getString("NAME_1"), + rs.getString("MIDDLE"), + rs.getObject("BIRTH_DT", LocalDate.class), + rs.getObject("FILE_SINCE_DT_NAME", LocalDate.class) + )); + } + public List findFidsLong(List phones) { MapSqlParameterSource params = new MapSqlParameterSource(); params.addValue("phones", phones); @@ -66,6 +104,21 @@ public class PhoneRepository { private LocalDate fileSinceDate; } + @Getter + @Setter + @AllArgsConstructor + @NoArgsConstructor + public static class FidsDataWithName { + private Integer fid; + private String phone; + private LocalDate fileSinceDate; + private String firstName; + private String lastName; + private String middleName; + private LocalDate birthDate; + private LocalDate fileSinceDateName; + } + @Getter @Setter @AllArgsConstructor diff --git a/src/main/java/ru/nbch/credit_tracker/service/SignalService.java b/src/main/java/ru/nbch/credit_tracker/service/SignalService.java index 24c031b..8eca0bf 100644 --- a/src/main/java/ru/nbch/credit_tracker/service/SignalService.java +++ b/src/main/java/ru/nbch/credit_tracker/service/SignalService.java @@ -103,6 +103,25 @@ public class SignalService { log.info("Subjects were registered. PackageId: {}", packageId); } + /** + * Выгружает {@link PhoneFidMap} батчами. Передает обогащенные фидами и данными из Name {@link PhoneFidMap} + * на поиск флагов и формирование отчета в оф. сервис сигналов + * @param packageId id пакета, по которому идет выборка {@link PhoneFidMap} + */ + public void processSubjects(Integer packageId) { + int offset = 0; + List batch; + do { + batch = phoneFidMapService.findFullPhoneFidMap(packageId, offset, batchSize); + if (!batch.isEmpty()) { + Map fidsMapByBatch = phoneService2.defineFidsAndNameByPhone(batch); + // TODO process fidsMapByBatch here + } + offset += batchSize; + } while (!batch.isEmpty()); + } + + /** * Обрабатывает все PhoneFidMap по packageId, выгружая их пачками и фильтруя по переданному фильтру */ diff --git a/src/main/java/ru/nbch/credit_tracker/service/indic/PhoneService2.java b/src/main/java/ru/nbch/credit_tracker/service/indic/PhoneService2.java index f5f827f..f608876 100644 --- a/src/main/java/ru/nbch/credit_tracker/service/indic/PhoneService2.java +++ b/src/main/java/ru/nbch/credit_tracker/service/indic/PhoneService2.java @@ -6,7 +6,9 @@ import org.springframework.stereotype.Service; import ru.nbch.credit_tracker.entities.dto.PhoneFidMap; import ru.nbch.credit_tracker.repository.PhoneRepository; +import java.time.LocalDate; import java.util.*; +import java.util.stream.Collectors; @Slf4j @Service @@ -60,6 +62,83 @@ public class PhoneService2 { return phoneFidMap; } + /** + * Ищет фиды по номерам телефона. Обогащает {@link PhoneFidMap} для найденных фидов данными из Name и фидом. + * @return Map: key - FID, value - {@link PhoneFidMap} + */ + public Map defineFidsAndNameByPhone(List subjects) { + Map phoneFidMap = new HashMap<>(); + + List phones = subjects.stream(). + map(subject -> "9" + subject.getPhone()) + .toList(); + + subjects.sort( + Comparator.comparing( + PhoneFidMap::getPhone, + Comparator.naturalOrder() + ) + ); + + List phonesByFid = phoneRepository.findFidsWithName(phones); + + log.debug("Start merging fids and names"); + Map> fidFidsDataMap = phonesByFid.stream() + .collect(Collectors.groupingBy(PhoneRepository.FidsDataWithName::getFid)); + + Map phoneToFidsMap = new HashMap<>(); + for (PhoneRepository.FidsDataWithName fidsData : phonesByFid) { + if (!phoneToFidsMap.containsKey(fidsData.getPhone())) { + phoneToFidsMap.put(fidsData.getPhone(), fidsData); + } + } + + for (PhoneFidMap phoneFid : subjects) { + String phone = "9" + phoneFid.getPhone(); + PhoneRepository.FidsDataWithName fidsData = phoneToFidsMap.get(phone); + if (fidsData != null) { + phoneFid.setFid(fidsData.getFid()); + + PhoneRepository.FidsDataWithName nameData = defineNameData(fidFidsDataMap.get(fidsData.getFid())); + + if (nameData != null) { + phoneFid.setFirstName(nameData.getFirstName()); + phoneFid.setMiddleName(nameData.getMiddleName()); + phoneFid.setLastName(nameData.getLastName()); + phoneFid.setBirthDate(nameData.getBirthDate()); + phoneFid.setFileSinceDate(nameData.getFileSinceDateName()); + } + + phoneFidMap.put(fidsData.getFid(), phoneFid); + phoneToFidsMap.remove(phone); + fidFidsDataMap.remove(fidsData.getFid()); + } + } + log.debug("End merging fids and names"); + + return phoneFidMap; + } + + private PhoneRepository.FidsDataWithName defineNameData(List dataList) { + PhoneRepository.FidsDataWithName currentData = null; + for (PhoneRepository.FidsDataWithName fidsData : dataList) { + if (currentData == null) { + currentData = fidsData; + continue; + } + LocalDate currentDate = currentData.getFileSinceDateName(); + LocalDate newDate = fidsData.getFileSinceDateName(); + if (currentDate != null && newDate != null) { + if (currentDate.isBefore(newDate)) { + currentData = fidsData; + } + } else if (currentDate == null) { + currentData = fidsData; + } + } + return currentData; + } + private Map merger(List subjects, List phonesByFid) { Map phoneFidMap = new HashMap<>(); Iterator iterator = phonesByFid.iterator(); diff --git a/src/test/java/ru/nbch/credit_tracker/service/PhoneService2Test.java b/src/test/java/ru/nbch/credit_tracker/service/PhoneService2Test.java index 7588d3f..509324a 100644 --- a/src/test/java/ru/nbch/credit_tracker/service/PhoneService2Test.java +++ b/src/test/java/ru/nbch/credit_tracker/service/PhoneService2Test.java @@ -58,7 +58,65 @@ public class PhoneService2Test { ); Comparator byDbOrder = - Comparator.comparing(PhoneRepository.FidsData::getPhone, Comparator.nullsFirst(Comparator.naturalOrder())) // pn.number ASC - .thenComparing(PhoneRepository.FidsData::getFileSinceDate, Comparator.nullsLast(Comparator.reverseOrder())) // file_since_dt DESC - .thenComparing(PhoneRepository.FidsData::getFid, Comparator.reverseOrder()); + Comparator.comparing(PhoneRepository.FidsData::getPhone, Comparator.nullsFirst(Comparator.naturalOrder())) // pn.number ASC + .thenComparing(PhoneRepository.FidsData::getFileSinceDate, Comparator.nullsLast(Comparator.reverseOrder())) // file_since_dt DESC + .thenComparing(PhoneRepository.FidsData::getFid, Comparator.reverseOrder()); + + @Test + void defineFidsAndNameByPhoneTest() { + PhoneService2 phoneService = new PhoneService2(phoneRepository); + + fidsDataWithNameEqualSinceDt.sort(byDbOrderWithName); + when(phoneRepository.findFidsWithName(any())).thenReturn(fidsDataWithNameEqualSinceDt); + + List 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()); + phoneFidMap.add(PhoneFidMap.builder().phone("1115").build()); + + Map res = phoneService.defineFidsAndNameByPhone(phoneFidMap); + Assertions.assertEquals(4, res.size()); + Assertions.assertEquals("1111", res.get(124).getPhone()); + Assertions.assertEquals("1112", res.get(125).getPhone()); + Assertions.assertEquals("1114", res.get(126).getPhone()); + Assertions.assertEquals("1115", res.get(127).getPhone()); + + Assertions.assertEquals("found124", res.get(124).getFirstName()); + Assertions.assertNull(res.get(125).getFirstName()); + Assertions.assertEquals("found126", res.get(126).getFirstName()); + Assertions.assertNull(res.get(128)); + + } + private final List fidsDataWithNameEqualSinceDt = new ArrayList<>( + List.of( + new PhoneRepository.FidsDataWithName(123, "91111", LocalDate.of(2025, 9, 10), "skip", null, null, null, null), + new PhoneRepository.FidsDataWithName(123, "91111", LocalDate.of(2025, 9, 10), "skip", null, null, null, LocalDate.of(2025, 10, 9)), + new PhoneRepository.FidsDataWithName(124, "91111", LocalDate.of(2025, 9, 9), "found124", null, null, null, LocalDate.of(2025, 9, 9)), + new PhoneRepository.FidsDataWithName(124, "91111", LocalDate.of(2025, 9, 10), "skip124", null, null, null, LocalDate.of(2025, 9, 8)), + new PhoneRepository.FidsDataWithName(124, "91111", LocalDate.of(2025, 9, 9), "skip124", null, null, null, LocalDate.of(2025, 9, 8)), + new PhoneRepository.FidsDataWithName(124, "91111", LocalDate.of(2025, 9, 10), "found124", null, null, null, LocalDate.of(2025, 9, 9)), + + + + + new PhoneRepository.FidsDataWithName(125, "91112", LocalDate.of(2024, 10, 10), null, null, null, null, null), + + new PhoneRepository.FidsDataWithName(126, "91114", LocalDate.of(2024, 10, 11), "skip126", null, null, null, null), + new PhoneRepository.FidsDataWithName(126, "91114", LocalDate.of(2024, 10, 11), "found126", null, null, null, LocalDate.of(2025, 9, 9)), + new PhoneRepository.FidsDataWithName(126, "91114", LocalDate.of(2024, 10, 5), "found126", null, null, null, LocalDate.of(2025, 9, 9)), + new PhoneRepository.FidsDataWithName(126, "91114", LocalDate.of(2024, 10, 5), "skip126", null, null, null, null), + + + new PhoneRepository.FidsDataWithName(127, "91115", LocalDate.of(2025, 9, 11), null, null, null, null, null), + new PhoneRepository.FidsDataWithName(128, "91115", LocalDate.of(2025, 9, 10), "found128", null, null, null, LocalDate.of(2025, 9, 9)) + ) + ); + + Comparator byDbOrderWithName = + Comparator.comparing(PhoneRepository.FidsDataWithName::getPhone, Comparator.nullsFirst(Comparator.naturalOrder())) // pn.number ASC + .thenComparing(PhoneRepository.FidsDataWithName::getFileSinceDate, Comparator.nullsLast(Comparator.reverseOrder())) // file_since_dt DESC + .thenComparing(PhoneRepository.FidsDataWithName::getFid, Comparator.reverseOrder()); + }