From 70d02651149024833fd6c4b262f38b466fc8adf2 Mon Sep 17 00:00:00 2001 From: vananiev Date: Wed, 23 Oct 2024 00:20:46 +0300 Subject: [PATCH] refactor AbstractBrokerReport --- .../parser/AbstractBrokerReport.java | 60 +++++++++------ .../parser/AbstractExcelBrokerReport.java | 14 +++- .../parser/psb/PsbBrokerReport.java | 43 ++++++----- .../PsbBrokerForeignMarketReport.java | 45 +++++++---- .../parser/tinkoff/TinkoffBrokerReport.java | 39 +++++----- .../tinkoff/TinkoffBrokerReportHelper.java | 3 +- .../parser/uralsib/UralsibBrokerReport.java | 77 +++++++++---------- .../parser/vtb/VtbBrokerReport.java | 57 +++++++------- 8 files changed, 192 insertions(+), 146 deletions(-) diff --git a/src/main/java/ru/investbook/parser/AbstractBrokerReport.java b/src/main/java/ru/investbook/parser/AbstractBrokerReport.java index 885eec7d..45ccc431 100644 --- a/src/main/java/ru/investbook/parser/AbstractBrokerReport.java +++ b/src/main/java/ru/investbook/parser/AbstractBrokerReport.java @@ -18,14 +18,12 @@ package ru.investbook.parser; -import lombok.AccessLevel; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.Setter; +import lombok.ToString; import org.spacious_team.table_wrapper.api.ReportPage; -import java.nio.file.Path; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; @@ -33,32 +31,49 @@ import java.time.format.DateTimeFormatter; @RequiredArgsConstructor -@EqualsAndHashCode(of = "path") +@ToString(of = "reportName") +@EqualsAndHashCode(of = "reportName") public abstract class AbstractBrokerReport implements SingleBrokerReport { protected static final int LAST_TRADE_HOUR = 19; - @Getter - private final SecurityRegistrar securityRegistrar; - @Setter(AccessLevel.PROTECTED) - private DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); - @Setter(AccessLevel.PROTECTED) - private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); + protected static final ZoneId MOSCOW_ZONEID = ZoneId.of("Europe/Moscow"); + private static final DateTimeFormatter RUSSIAN_DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy"); + private static final DateTimeFormatter RUSSIAN_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); - @Setter(AccessLevel.PROTECTED) - private Path path; + private final DateTimeFormatter dateFormatter = RUSSIAN_DATE_FORMATTER; + private final DateTimeFormatter dateTimeFormatter = RUSSIAN_DATETIME_FORMATTER; + @Getter + private final ZoneId reportZoneId = MOSCOW_ZONEID; @Getter - @Setter(AccessLevel.PROTECTED) - private String portfolio; + private final ReportPage reportPage; + private final String reportName; @Getter - @Setter(AccessLevel.PROTECTED) - private ReportPage reportPage; + private final Instant reportEndDateTime; @Getter - @Setter(AccessLevel.PROTECTED) - private Instant reportEndDateTime; + private final String portfolio; @Getter - private final ZoneId reportZoneId = ZoneId.of("Europe/Moscow"); + private final SecurityRegistrar securityRegistrar; + + public AbstractBrokerReport(Attributes attributes, SecurityRegistrar securityRegistrar) { + this.reportPage = attributes.reportPage(); + this.reportName = attributes.reportName(); + this.reportEndDateTime = attributes.reportEndDateTime(); + this.portfolio = attributes.portfolio(); + this.securityRegistrar = securityRegistrar; + } public Instant convertToInstant(String value) { + return convertToInstant(value, dateFormatter, dateTimeFormatter, reportZoneId); + } + + protected static Instant convertToInstantWithRussianFormatAndMoscowZoneId(String value) { + return convertToInstant(value, RUSSIAN_DATE_FORMATTER, RUSSIAN_DATETIME_FORMATTER, MOSCOW_ZONEID); + } + + protected static Instant convertToInstant(String value, + DateTimeFormatter dateFormatter, + DateTimeFormatter dateTimeFormatter, + ZoneId reportZoneId) { value = value.trim(); if (value.contains(":")) { return LocalDateTime.parse(value, dateTimeFormatter).atZone(reportZoneId).toInstant(); @@ -67,8 +82,9 @@ public Instant convertToInstant(String value) { } } - @Override - public String toString() { - return path.getFileName().toString(); + public record Attributes(ReportPage reportPage, + String reportName, + Instant reportEndDateTime, + String portfolio) { } } diff --git a/src/main/java/ru/investbook/parser/AbstractExcelBrokerReport.java b/src/main/java/ru/investbook/parser/AbstractExcelBrokerReport.java index c04fe3a7..3d468994 100644 --- a/src/main/java/ru/investbook/parser/AbstractExcelBrokerReport.java +++ b/src/main/java/ru/investbook/parser/AbstractExcelBrokerReport.java @@ -28,8 +28,11 @@ public abstract class AbstractExcelBrokerReport extends AbstractBrokerReport { - public AbstractExcelBrokerReport(SecurityRegistrar securityRegistrar) { - super(securityRegistrar); + private final Workbook workbook; + + public AbstractExcelBrokerReport(ExcelAttributes attributes, SecurityRegistrar securityRegistrar) { + super(attributes.attributes(), securityRegistrar); + this.workbook = attributes.workbook(); } public static Workbook getWorkBook(String excelFileName, InputStream is) { @@ -45,4 +48,11 @@ public static Workbook getWorkBook(String excelFileName, InputStream is) { } } + @Override + public void close() throws IOException { + workbook.close(); + } + + public record ExcelAttributes(Workbook workbook, Attributes attributes) { + } } diff --git a/src/main/java/ru/investbook/parser/psb/PsbBrokerReport.java b/src/main/java/ru/investbook/parser/psb/PsbBrokerReport.java index e5abfa5c..55817c72 100644 --- a/src/main/java/ru/investbook/parser/psb/PsbBrokerReport.java +++ b/src/main/java/ru/investbook/parser/psb/PsbBrokerReport.java @@ -32,7 +32,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Instant; -import java.time.temporal.ChronoUnit; + +import static java.time.temporal.ChronoUnit.HOURS; @EqualsAndHashCode(callSuper = true) public class PsbBrokerReport extends AbstractExcelBrokerReport { @@ -40,25 +41,33 @@ public class PsbBrokerReport extends AbstractExcelBrokerReport { private static final String PORTFOLIO_MARKER = "Договор №:"; private static final String REPORT_DATE_MARKER = "ОТЧЕТ БРОКЕРА"; - private final Workbook book; - public PsbBrokerReport(String excelFileName, SecurityRegistrar securityRegistrar) throws IOException { this(Paths.get(excelFileName), securityRegistrar); } public PsbBrokerReport(Path report, SecurityRegistrar securityRegistrar) throws IOException { - this(report.getFileName().toString(), Files.newInputStream(report), securityRegistrar); + this(getFileName(report), Files.newInputStream(report), securityRegistrar); } public PsbBrokerReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { - super(securityRegistrar); - this.book = getWorkBook(excelFileName, is); - ReportPage reportPage = new ExcelSheet(book.getSheetAt(0)); + super(getBrokerReportAttributes(excelFileName, is), securityRegistrar); + } + + @SuppressWarnings("nullness") + private static String getFileName(Path path) { + return path.getFileName().toString(); + } + + private static ExcelAttributes getBrokerReportAttributes(String excelFileName, InputStream is) { + Workbook workbook = getWorkBook(excelFileName, is); + ReportPage reportPage = new ExcelSheet(workbook.getSheetAt(0)); checkReportFormat(excelFileName, reportPage); - setPath(Paths.get(excelFileName)); - setReportPage(reportPage); - setPortfolio(getPortfolio(reportPage)); - setReportEndDateTime(getReportEndDateTime(reportPage)); + Attributes attributes = new Attributes( + reportPage, + excelFileName, + getReportEndDateTime(reportPage), + getPortfolio(reportPage)); + return new ExcelAttributes(workbook, attributes); } public static void checkReportFormat(String excelFileName, ReportPage reportPage) { @@ -77,19 +86,15 @@ private static String getPortfolio(ReportPage reportPage) { } } - private Instant getReportEndDateTime(ReportPage reportPage) { + private static Instant getReportEndDateTime(ReportPage reportPage) { try { String value = String.valueOf(reportPage.getNextColumnValue(REPORT_DATE_MARKER)); - return convertToInstant(value.split(" ")[3]) - .plus(LAST_TRADE_HOUR, ChronoUnit.HOURS); + String date = value.split(" ")[3]; + return convertToInstantWithRussianFormatAndMoscowZoneId(date) + .plus(LAST_TRADE_HOUR, HOURS); } catch (Exception e) { throw new IllegalArgumentException( "Не найдена дата отчета по заданному шаблону '" + REPORT_DATE_MARKER + " XXX'"); } } - - @Override - public void close() throws IOException { - this.book.close(); - } } diff --git a/src/main/java/ru/investbook/parser/psb/foreignmarket/PsbBrokerForeignMarketReport.java b/src/main/java/ru/investbook/parser/psb/foreignmarket/PsbBrokerForeignMarketReport.java index c9de2950..2615ef37 100644 --- a/src/main/java/ru/investbook/parser/psb/foreignmarket/PsbBrokerForeignMarketReport.java +++ b/src/main/java/ru/investbook/parser/psb/foreignmarket/PsbBrokerForeignMarketReport.java @@ -31,12 +31,14 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.file.Paths; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; +import java.util.function.Function; + +import static java.time.temporal.ChronoUnit.HOURS; @EqualsAndHashCode(callSuper = true) public class PsbBrokerForeignMarketReport extends AbstractBrokerReport { @@ -47,14 +49,18 @@ public class PsbBrokerForeignMarketReport extends AbstractBrokerReport { private static final String REPORT_DATE_MARKER = "ОТЧЕТ БРОКЕРА"; public PsbBrokerForeignMarketReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { - super(securityRegistrar); + super(getBrokerReportAttributes(excelFileName, is), securityRegistrar); + } + + private static Attributes getBrokerReportAttributes(String excelFileName, InputStream is) { Workbook book = getWorkbook(is); ReportPage reportPage = new XmlReportPage(book.getWorksheetAt(0)); PsbBrokerReport.checkReportFormat(excelFileName, reportPage); - setPath(Paths.get(excelFileName)); - setReportPage(reportPage); - setPortfolio(getPortfolio(reportPage)); - setReportEndDateTime(getReportEndDateTime(reportPage)); + return new Attributes( + reportPage, + excelFileName, + getReportEndDateTime(reportPage), + getPortfolio(reportPage)); } private static Workbook getWorkbook(InputStream is) { @@ -88,11 +94,12 @@ private static String getPortfolio(ReportPage reportPage) { } } - private Instant getReportEndDateTime(ReportPage reportPage) { + private static Instant getReportEndDateTime(ReportPage reportPage) { try { String value = String.valueOf(reportPage.getNextColumnValue(REPORT_DATE_MARKER)); - return convertToInstant(value.split(" ")[3]) - .plus(LAST_TRADE_HOUR, ChronoUnit.HOURS); + String date = value.split(" ")[3]; + return convertToInstantWithRussianFormatAndMoscowZoneId(date) + .plus(LAST_TRADE_HOUR, HOURS); } catch (Exception e) { throw new IllegalArgumentException( "Не найдена дата отчета по заданному шаблону '" + REPORT_DATE_MARKER + " XXX'"); @@ -101,14 +108,26 @@ private Instant getReportEndDateTime(ReportPage reportPage) { @Override public Instant convertToInstant(String value) { + return convertXmlDateTimeToInstant(value, getReportZoneId(), super::convertToInstant); + } + + protected static Instant convertToInstantWithRussianFormatAndMoscowZoneId(String value) { + return convertXmlDateTimeToInstant(value, + MOSCOW_ZONEID, + AbstractBrokerReport::convertToInstantWithRussianFormatAndMoscowZoneId); + } + + private static Instant convertXmlDateTimeToInstant(String value, + ZoneId zoneId, + Function defaultConverter) { value = value.trim(); if (value.contains("/")) { return LocalDate.parse(value, PsbBrokerForeignMarketReport.dateFormatterWithSlash) - .atStartOfDay(getReportZoneId()).toInstant(); + .atStartOfDay(zoneId).toInstant(); } else if (value.contains(":") && value.length() == 16) { - return LocalDateTime.parse(value, dateTimeFormatter).atZone(getReportZoneId()).toInstant(); + return LocalDateTime.parse(value, dateTimeFormatter).atZone(zoneId).toInstant(); } else { - return super.convertToInstant(value); + return defaultConverter.apply(value); } } diff --git a/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReport.java b/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReport.java index 5079a47e..bffc6b04 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReport.java +++ b/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReport.java @@ -26,14 +26,12 @@ import ru.investbook.parser.AbstractExcelBrokerReport; import ru.investbook.parser.SecurityRegistrar; -import java.io.IOException; import java.io.InputStream; -import java.nio.file.Paths; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.function.Predicate; import java.util.regex.Pattern; +import static java.time.temporal.ChronoUnit.HOURS; import static java.util.regex.Pattern.UNICODE_CHARACTER_CLASS; import static ru.investbook.parser.tinkoff.TinkoffBrokerReportHelper.removePageNumRows; @@ -48,18 +46,21 @@ public class TinkoffBrokerReport extends AbstractExcelBrokerReport { private static final Predicate dateMarkerPredicate = cell -> (cell instanceof String) && ((String) cell).contains("за период"); - private final Workbook book; - public TinkoffBrokerReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { - super(securityRegistrar); - this.book = getWorkBook(excelFileName, is); - ExcelSheet reportPage = new ExcelSheet(book.getSheetAt(0)); + super(getBrokerReportAttributes(excelFileName, is), securityRegistrar); + } + + private static ExcelAttributes getBrokerReportAttributes(String excelFileName, InputStream is) { + Workbook workbook = getWorkBook(excelFileName, is); + ExcelSheet reportPage = new ExcelSheet(workbook.getSheetAt(0)); checkReportFormat(excelFileName, reportPage); - setPath(Paths.get(excelFileName)); - setReportPage(reportPage); - setPortfolio(getPortfolio(reportPage)); - setReportEndDateTime(getReportEndDateTime(reportPage)); removePageNumRows(reportPage); + Attributes attributes = new Attributes( + reportPage, + excelFileName, + getReportEndDateTime(reportPage), + getPortfolio(reportPage)); + return new ExcelAttributes(workbook, attributes); } public static void checkReportFormat(String excelFileName, ReportPage reportPage) { @@ -69,34 +70,32 @@ public static void checkReportFormat(String excelFileName, ReportPage reportPage } } + @SuppressWarnings({"nullness", "DataFlowIssue"}) private static String getPortfolio(ReportPage reportPage) { try { return reportPage.getCell(reportPage.findByPrefix(PORTFOLIO_MARKER)) .getStringValue() .split("/")[1] .trim() - .split("\s+")[0]; + .split("\\s+")[0]; } catch (Exception e) { throw new IllegalArgumentException( "В отчете не найден номер договора по заданному шаблону '" + PORTFOLIO_MARKER); } } - private Instant getReportEndDateTime(ReportPage reportPage) { + private static Instant getReportEndDateTime(ReportPage reportPage) { try { TableCellAddress address = reportPage.find(0, 10, dateMarkerPredicate); + @SuppressWarnings({"nullness", "DataFlowIssue"}) String[] words = reportPage.getCell(address) .getStringValue() .split("-"); String value = words[words.length - 1].trim(); - return convertToInstant(value).plus(LAST_TRADE_HOUR, ChronoUnit.HOURS); + return convertToInstantWithRussianFormatAndMoscowZoneId(value) + .plus(LAST_TRADE_HOUR, HOURS); } catch (Exception e) { throw new IllegalArgumentException("Не найдена дата отчета по заданному шаблону"); } } - - @Override - public void close() throws IOException { - this.book.close(); - } } diff --git a/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReportHelper.java b/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReportHelper.java index 9d4ab5f6..13a3b18b 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReportHelper.java +++ b/src/main/java/ru/investbook/parser/tinkoff/TinkoffBrokerReportHelper.java @@ -21,6 +21,7 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spacious_team.table_wrapper.api.ReportPage; import org.spacious_team.table_wrapper.excel.ExcelSheet; import org.springframework.util.StringUtils; @@ -66,7 +67,7 @@ private static boolean isTableHeader(ReportPage reportPage, int rowNum) { TinkoffBrokerReportHelper::isCellContainsTableName) != NOT_FOUND; } - private static boolean isCellContainsTableName(Object cell) { + private static boolean isCellContainsTableName(@Nullable Object cell) { return (cell instanceof String) && !cell.toString().isEmpty() && tableNamePattern.matcher(cell.toString()).lookingAt(); diff --git a/src/main/java/ru/investbook/parser/uralsib/UralsibBrokerReport.java b/src/main/java/ru/investbook/parser/uralsib/UralsibBrokerReport.java index 68f347b7..99c8e545 100644 --- a/src/main/java/ru/investbook/parser/uralsib/UralsibBrokerReport.java +++ b/src/main/java/ru/investbook/parser/uralsib/UralsibBrokerReport.java @@ -20,6 +20,7 @@ import lombok.EqualsAndHashCode; import org.apache.poi.ss.usermodel.Workbook; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spacious_team.table_wrapper.api.ReportPage; import org.spacious_team.table_wrapper.api.TableCell; import org.spacious_team.table_wrapper.api.TableCellAddress; @@ -27,70 +28,67 @@ import ru.investbook.parser.AbstractExcelBrokerReport; import ru.investbook.parser.SecurityRegistrar; -import java.io.IOException; import java.io.InputStream; -import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.function.Predicate; -import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import static java.util.Objects.requireNonNull; +import static java.time.temporal.ChronoUnit.HOURS; import static org.spacious_team.table_wrapper.api.TableCellAddress.NOT_FOUND; @EqualsAndHashCode(callSuper = true) public class UralsibBrokerReport extends AbstractExcelBrokerReport { // "УРАЛСИБ Брокер" или "УРАЛСИБ Кэпитал - Финансовые услуги" (старый формат 2018 г) private static final String PORTFOLIO_MARKER = "Номер счета Клиента:"; - private final Predicate uralsibReportPredicate = cell -> + private static final Predicate uralsibReportPredicate = cell -> (cell instanceof String value) && (value.contains("Твой Брокер") || value.contains("УРАЛСИБ")); - private final Predicate dateMarkerPredicate = cell -> + private static final Predicate dateMarkerPredicate = cell -> (cell instanceof String value) && value.contains("за период"); - private final Workbook book; public UralsibBrokerReport(ZipInputStream zis, SecurityRegistrar securityRegistrar) { - super(securityRegistrar); + this(getFileName(zis), zis, securityRegistrar); + } + + public UralsibBrokerReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { + super(getBrokerReportAttributes(excelFileName, is), securityRegistrar); + } + + @SuppressWarnings("DataFlowIssue") + private static String getFileName(ZipInputStream zis) { try { - ZipEntry zipEntry = requireNonNull(zis.getNextEntry()); - Path path = Paths.get(zipEntry.getName()); - this.book = getWorkBook(path.getFileName().toString(), zis); - ReportPage reportPage = new ExcelSheet(book.getSheetAt(0)); - checkReportFormat(path, reportPage); - setPath(path); - setReportPage(reportPage); - setPortfolio(getPortfolio(reportPage)); - setReportEndDateTime(getReportEndDateTime(reportPage)); + return zis.getNextEntry() + .getName(); } catch (Exception e) { throw new RuntimeException("Не смог открыть excel файл", e); } } - public UralsibBrokerReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { - super(securityRegistrar); - this.book = getWorkBook(excelFileName, is); - ReportPage reportPage = new ExcelSheet(book.getSheetAt(0)); - Path path = Paths.get(excelFileName); - checkReportFormat(path, reportPage); - setPath(path); - setReportPage(reportPage); - setPortfolio(getPortfolio(reportPage)); - setReportEndDateTime(getReportEndDateTime(reportPage)); + private static ExcelAttributes getBrokerReportAttributes(String excelFileName, InputStream is) { + Workbook workbook = getWorkBook(excelFileName, is); + ReportPage reportPage = new ExcelSheet(workbook.getSheetAt(0)); + checkReportFormat(excelFileName, reportPage); + Attributes attributes = new Attributes( + reportPage, + excelFileName, + getReportEndDateTime(reportPage), + getPortfolio(reportPage)); + return new ExcelAttributes(workbook, attributes); } - private void checkReportFormat(Path path, ReportPage reportPage) { + private static void checkReportFormat(String excelFileName, ReportPage reportPage) { if (reportPage.find(0, 1, uralsibReportPredicate) == NOT_FOUND) { - throw new RuntimeException("В файле " + path + " не содержится отчет брокера Твой Брокер (Уралсиб)"); + throw new RuntimeException("В файле " + excelFileName + " не содержится отчет брокера Твой Брокер (Уралсиб)"); } } private static String getPortfolio(ReportPage reportPage) { try { TableCellAddress address = reportPage.findByPrefix(PORTFOLIO_MARKER); - for (TableCell cell : reportPage.getRow(address.getRow())) { + //noinspection DataFlowIssue + for (@Nullable TableCell cell : reportPage.getRow(address.getRow())) { if (cell != null && cell.getColumnIndex() > address.getColumn()) { - Object value = cell.getValue(); + @SuppressWarnings("DataFlowIssue") + @Nullable Object value = cell.getValue(); if (value instanceof String) { return value.toString() .replace("_invest", "") @@ -107,14 +105,16 @@ private static String getPortfolio(ReportPage reportPage) { } } - private Instant getReportEndDateTime(ReportPage reportPage) { + private static Instant getReportEndDateTime(ReportPage reportPage) { try { TableCellAddress address = reportPage.find(0, dateMarkerPredicate); + @SuppressWarnings({"nullness", "DataFlowIssue"}) String[] words = reportPage.getCell(address) .getStringValue() .split(" "); - return convertToInstant(words[words.length - 1]) - .plus(LAST_TRADE_HOUR, ChronoUnit.HOURS); + String date = words[words.length - 1]; + return convertToInstantWithRussianFormatAndMoscowZoneId(date) + .plus(LAST_TRADE_HOUR, HOURS); } catch (Exception e) { throw new RuntimeException("Ошибка поиска даты отчета"); } @@ -123,9 +123,4 @@ private Instant getReportEndDateTime(ReportPage reportPage) { public static String convertToCurrency(String value) { return value.replace("RUR", "RUB"); // uralsib uses RUR (used till 1998) code in reports } - - @Override - public void close() throws IOException { - this.book.close(); - } } diff --git a/src/main/java/ru/investbook/parser/vtb/VtbBrokerReport.java b/src/main/java/ru/investbook/parser/vtb/VtbBrokerReport.java index ca83715b..2837c0a6 100644 --- a/src/main/java/ru/investbook/parser/vtb/VtbBrokerReport.java +++ b/src/main/java/ru/investbook/parser/vtb/VtbBrokerReport.java @@ -20,19 +20,18 @@ import lombok.EqualsAndHashCode; import org.apache.poi.ss.usermodel.Workbook; +import org.checkerframework.checker.nullness.qual.Nullable; import org.spacious_team.table_wrapper.api.ReportPage; import org.spacious_team.table_wrapper.api.TableCellAddress; import org.spacious_team.table_wrapper.excel.ExcelSheet; import ru.investbook.parser.AbstractExcelBrokerReport; import ru.investbook.parser.SecurityRegistrar; -import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; -import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Objects; @EqualsAndHashCode(callSuper = true) public class VtbBrokerReport extends AbstractExcelBrokerReport { @@ -42,33 +41,39 @@ public class VtbBrokerReport extends AbstractExcelBrokerReport { private static final String REPORT_DATE_MARKER = "Отчет Банка ВТБ"; static final BigDecimal minValue = BigDecimal.valueOf(0.01); - private final Workbook book; - public VtbBrokerReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { - super(securityRegistrar); - this.book = getWorkBook(excelFileName, is); - ReportPage reportPage = new ExcelSheet(book.getSheetAt(0)); - Path path = Paths.get(excelFileName); - checkReportFormat(path, reportPage); - setPath(path); - setReportPage(reportPage); - setPortfolio(getPortfolio(reportPage)); - setReportEndDateTime(getReportEndDateTime(reportPage)); + super(getBrokerReportAttributes(excelFileName, is), securityRegistrar); + } + + private static ExcelAttributes getBrokerReportAttributes(String excelFileName, InputStream is) { + Workbook workbook = getWorkBook(excelFileName, is); + ReportPage reportPage = new ExcelSheet(workbook.getSheetAt(0)); + checkReportFormat(excelFileName, reportPage); + Attributes attributes = new Attributes( + reportPage, + excelFileName, + getReportEndDateTime(reportPage), + getPortfolio(reportPage)); + return new ExcelAttributes(workbook, attributes); } - private static void checkReportFormat(Path path, ReportPage reportPage) { + private static void checkReportFormat(String excelFileName, ReportPage reportPage) { if (reportPage.findByPrefix(UNIQ_TEXT, 1, 2) == TableCellAddress.NOT_FOUND) { - throw new RuntimeException("В файле " + path + " не содержится отчет брокера ВТБ"); + throw new RuntimeException("В файле " + excelFileName + " не содержится отчет брокера ВТБ"); } } private static String getPortfolio(ReportPage reportPage) { try { - Object account = reportPage.getNextColumnValue(ACCOUNT_MARKER); - Object subAccount = reportPage.getNextColumnValue(SUBACCOUNT_MARKER); - if (account instanceof Number) account = ((Number) account).intValue(); - if (subAccount instanceof Number) subAccount = ((Number) subAccount).intValue(); - if (account.equals(subAccount)) { + @Nullable Object account = reportPage.getNextColumnValue(ACCOUNT_MARKER); + @Nullable Object subAccount = reportPage.getNextColumnValue(SUBACCOUNT_MARKER); + if (account instanceof Number) { + account = ((Number) account).intValue(); + } + if (subAccount instanceof Number) { + subAccount = ((Number) subAccount).intValue(); + } + if (Objects.equals(account, subAccount)) { return String.valueOf(account); } else { return account + "-" + subAccount; @@ -78,13 +83,14 @@ private static String getPortfolio(ReportPage reportPage) { } } - private Instant getReportEndDateTime(ReportPage reportPage) { + private static Instant getReportEndDateTime(ReportPage reportPage) { try { TableCellAddress address = reportPage.findByPrefix(REPORT_DATE_MARKER, 1, 2); + @SuppressWarnings({"nullness", "DataFlowIssue"}) String value = reportPage.getCell(address) .getStringValue() .split(" ")[9]; - return convertToInstant(value) + return convertToInstantWithRussianFormatAndMoscowZoneId(value) .plus(LAST_TRADE_HOUR, ChronoUnit.HOURS); } catch (Exception e) { throw new IllegalArgumentException( @@ -95,9 +101,4 @@ private Instant getReportEndDateTime(ReportPage reportPage) { public static String convertToCurrency(String value) { return value.replace("RUR", "RUB"); // vtb uses RUR (used till 1998) code in reports } - - @Override - public void close() throws IOException { - this.book.close(); - } }