diff --git a/pom.xml b/pom.xml
index ffd17aa..c57d7bc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,6 +126,11 @@
3.0.4
test
+
+ com.h2database
+ h2
+ test
+
org.mockito
mockito-junit-jupiter
diff --git a/src/test/java/ru/nbch/credit_tracker/service/FlagsService2Test.java b/src/test/java/ru/nbch/credit_tracker/service/FlagsService2Test.java
new file mode 100644
index 0000000..77bce91
--- /dev/null
+++ b/src/test/java/ru/nbch/credit_tracker/service/FlagsService2Test.java
@@ -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 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 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 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 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 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 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);
+ }
+}
+
+