Added processSubjects method to SignalService; Load Name data with fids in PhoneService2

This commit is contained in:
Mikhail Trofimov 2025-10-06 10:21:37 +03:00
parent fcca92e6a5
commit f4b49c06ed
5 changed files with 220 additions and 3 deletions

View file

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

View file

@ -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<FidsDataWithName> findFidsWithName(List<String> 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<FidsDataLong> findFidsLong(List<String> 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

View file

@ -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<PhoneFidMap> batch;
do {
batch = phoneFidMapService.findFullPhoneFidMap(packageId, offset, batchSize);
if (!batch.isEmpty()) {
Map<Integer, PhoneFidMap> fidsMapByBatch = phoneService2.defineFidsAndNameByPhone(batch);
// TODO process fidsMapByBatch here
}
offset += batchSize;
} while (!batch.isEmpty());
}
/**
* Обрабатывает все PhoneFidMap по packageId, выгружая их пачками и фильтруя по переданному фильтру
*/

View file

@ -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<Integer, PhoneFidMap> defineFidsAndNameByPhone(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()
)
);
List<PhoneRepository.FidsDataWithName> phonesByFid = phoneRepository.findFidsWithName(phones);
log.debug("Start merging fids and names");
Map<Integer, List<PhoneRepository.FidsDataWithName>> fidFidsDataMap = phonesByFid.stream()
.collect(Collectors.groupingBy(PhoneRepository.FidsDataWithName::getFid));
Map<String, PhoneRepository.FidsDataWithName> 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<PhoneRepository.FidsDataWithName> 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<Integer, PhoneFidMap> merger(List<PhoneFidMap> subjects, List<PhoneRepository.FidsData> phonesByFid) {
Map<Integer, PhoneFidMap> phoneFidMap = new HashMap<>();
Iterator<PhoneRepository.FidsData> iterator = phonesByFid.iterator();

View file

@ -58,7 +58,65 @@ public class PhoneService2Test {
);
Comparator<PhoneRepository.FidsData> 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> 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<Integer, PhoneFidMap> 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<PhoneRepository.FidsDataWithName> 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<PhoneRepository.FidsDataWithName> 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());
}