diff --git a/src/main/java/ru/investbook/parser/alfa/AlfaBrokerReportFactory.java b/src/main/java/ru/investbook/parser/alfa/AlfaBrokerReportFactory.java new file mode 100644 index 00000000..1067391c --- /dev/null +++ b/src/main/java/ru/investbook/parser/alfa/AlfaBrokerReportFactory.java @@ -0,0 +1,60 @@ +/* + * InvestBook + * Copyright (C) 2023 Spacious Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package ru.investbook.parser.alfa; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.spacious_team.broker.report_parser.api.AbstractBrokerReportFactory; +import org.spacious_team.broker.report_parser.api.BrokerReport; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import ru.investbook.parser.SecurityRegistrar; + +import java.io.InputStream; +import java.util.Optional; +import java.util.regex.Pattern; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +@Slf4j +@RequiredArgsConstructor +public class AlfaBrokerReportFactory extends AbstractBrokerReportFactory { + private final SecurityRegistrar securityRegistrar; + + @Getter + private final String brokerName = "Альфа-Инвестиции"; + private final Pattern expectedFileNamePattern = Pattern.compile("^Брокерский.*(Альфа|[0-9]+\\([0-9.\\-]+\\)).xls(x)?$"); + + @Override + public boolean canCreate(String excelFileName, InputStream is) { + return super.canCreate(expectedFileNamePattern, excelFileName, is); + } + + @Override + public Optional create(String excelFileName, InputStream is) { + Optional brokerReport = create(excelFileName, is, + (fileName, stream) -> new AlfaCashflowBrokerReport(fileName, stream, securityRegistrar)); + if (brokerReport.isPresent()) { + log.info("Обнаружен отчет '{}' Альфа брокера", excelFileName); + } + return brokerReport; + } +} diff --git a/src/main/java/ru/investbook/parser/alfa/AlfaBrokerReportWrapper.java b/src/main/java/ru/investbook/parser/alfa/AlfaBrokerReportWrapper.java new file mode 100644 index 00000000..01e5e28d --- /dev/null +++ b/src/main/java/ru/investbook/parser/alfa/AlfaBrokerReportWrapper.java @@ -0,0 +1,40 @@ +/* + * InvestBook + * Copyright (C) 2023 Spacious Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package ru.investbook.parser.alfa; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.spacious_team.broker.report_parser.api.BrokerReport; +import org.spacious_team.table_wrapper.api.ReportPage; + +@Getter +@RequiredArgsConstructor +public class AlfaBrokerReportWrapper implements BrokerReport { + + private final AlfaCashflowBrokerReport alfaCashflowBrokerReport; + + @Override + public ReportPage getReportPage() { + throw new UnsupportedOperationException(); + } + + @Override + public void close() { + } +} diff --git a/src/main/java/ru/investbook/parser/alfa/AlfaCashflowBrokerReport.java b/src/main/java/ru/investbook/parser/alfa/AlfaCashflowBrokerReport.java new file mode 100644 index 00000000..c6866985 --- /dev/null +++ b/src/main/java/ru/investbook/parser/alfa/AlfaCashflowBrokerReport.java @@ -0,0 +1,106 @@ +/* + * InvestBook + * Copyright (C) 2023 Spacious Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package ru.investbook.parser.alfa; + +import lombok.EqualsAndHashCode; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.Workbook; +import org.spacious_team.table_wrapper.api.ReportPage; +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.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.time.temporal.ChronoUnit; + +import static org.spacious_team.table_wrapper.api.TableCellAddress.NOT_FOUND; + +@EqualsAndHashCode(callSuper = true) +public class AlfaCashflowBrokerReport extends AbstractExcelBrokerReport { + public static final String UNIQ_TEXT = "Движение денежных средств за период"; + private static final String PORTFOLIO_MARKER = "Ген. соглашение"; + private static final String REPORT_DATE_MARKER = "Отчетный период"; + + private final Workbook book; + + public AlfaCashflowBrokerReport(String excelFileName, SecurityRegistrar securityRegistrar) throws IOException { + this(Paths.get(excelFileName), securityRegistrar); + } + + public AlfaCashflowBrokerReport(Path report, SecurityRegistrar securityRegistrar) throws IOException { + this(report.getFileName().toString(), Files.newInputStream(report), securityRegistrar); + } + + public AlfaCashflowBrokerReport(String excelFileName, InputStream is, SecurityRegistrar securityRegistrar) { + super(securityRegistrar); + this.book = getWorkBook(excelFileName, is); + ReportPage reportPage = new ExcelSheet(book.getSheetAt(3)); + checkReportFormat(excelFileName, reportPage); + setPath(Paths.get(excelFileName)); + setReportPage(reportPage); + setPortfolio(getPortfolio(reportPage)); + setReportEndDateTime(getReportEndDateTime(reportPage)); + } + + public static void checkReportFormat(String excelFileName, ReportPage reportPage) { + if (reportPage instanceof ExcelSheet excelSheet) { + + if (!excelSheet.getSheet().getSheetName().trim().equals("Движение ДС")) { + throw new RuntimeException("В файле " + excelFileName + " не содержится отчет брокера Альфа-Инвестиции"); + } + + if (reportPage.findByPrefix(UNIQ_TEXT, 11, 13) == NOT_FOUND) { + throw new RuntimeException("В файле " + excelFileName + " не содержится отчет брокера Альфа-Инвестиции"); + } + } + } + + private static String getPortfolio(ReportPage reportPage) { + try { + String value = String.valueOf(reportPage.getNextColumnValue(PORTFOLIO_MARKER)); + + return StringUtils.substringBetween(value, "№ ", " от"); + + } catch (Exception e) { + throw new IllegalArgumentException( + "В отчете не найден номер договора по заданному шаблону '" + PORTFOLIO_MARKER + " XXX'"); + } + } + + private Instant getReportEndDateTime(ReportPage reportPage) { + try { + String value = String.valueOf(reportPage.getNextColumnValue(REPORT_DATE_MARKER)); + return convertToInstant(value.split(" - ")[1].trim()) + .plus(LAST_TRADE_HOUR, ChronoUnit.HOURS); + } catch (Exception e) { + throw new IllegalArgumentException( + "Не найдена дата отчета по заданному шаблону '" + REPORT_DATE_MARKER + " XXX'"); + } + } + + @Override + public void close() throws IOException { + book.close(); + } +}