Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Релиз 2022.9 #521

Merged
merged 13 commits into from
Jan 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ mvn compile
Перед запуском приложения средствами IntelliJ IDEA обязательна [компиляция](#компиляция), после которой можно
запустить приложение по кнопке в верхней панели.

На Linux и Mac перед запуском не из под root дополнительно потребуется сменить порт с 80 на свободный больше 1024.
Порт редактируется в файле `src/main/resources/application-conf.properties`, однако делать commit изменения не нужно.

Если у вас другая среда разработки или вы работаете из консоли, то приложение можно запустить без предварительной
компиляции командой:
```
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</parent>
<groupId>ru.investbook</groupId>
<artifactId>investbook</artifactId>
<version>2022.8.4</version>
<version>2022.9</version>

<name>investbook</name>
<description>Investor Accounting Book</description>
Expand Down Expand Up @@ -62,7 +62,7 @@

<properties>
<!-- Valid version is (0-255).(0-255).(0-65535) -->
<win.msi.version>22.8.4</win.msi.version>
<win.msi.version>22.9</win.msi.version>
<java.version>18</java.version>
<!-- version 3.2.0 provided by Spring Boot 2.4.1 bugged, using version from Spring Boot 2.3.4
https://stackoverflow.com/questions/65910112/maven-clean-install-failed-to-execute-goal-org-apache-maven-pluginsmaven-resou
Expand Down Expand Up @@ -164,7 +164,7 @@
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.6.1</version>
<version>7.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/ru/investbook/InvestbookProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
import java.util.Collection;
import java.util.Collections;

@Component
@ConfigurationProperties("investbook")
@Getter
@Setter
@Component
@ConfigurationProperties("investbook")
public class InvestbookProperties {

private Path reportBackupPath = Paths.get(System.getProperty("user.home", ""), "investbook", "report-backups");
private Path dataPath = Paths.get(System.getProperty("user.home", ""), "investbook");

private Path reportBackupPath = dataPath.resolve("report-backups");

private boolean openHomePageAfterStart = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import ru.investbook.parser.SingleAbstractReportTable;
import ru.investbook.parser.SingleBrokerReport;

import java.time.Instant;
import java.util.Collection;

import static org.springframework.util.StringUtils.hasLength;
Expand Down Expand Up @@ -59,22 +60,40 @@ protected SecurityEventCashFlow parseRow(TableRow row) {
return null;
}

if (operation.contains("выплата") && operation.contains("дивиденд")) {
if (operation.contains("выплата") && operation.contains("дивиденд")) { // Выплата дивидендов
return getBuilder(row, currency)
.eventType(CashFlowType.DIVIDEND)
.value(row.getBigDecimalCellValue(DEPOSIT))
.build();
} else if (operation.contains("выплата") && operation.contains("купон")) {
} else if (operation.contains("выплата") && operation.contains("купон")) { // Выплата купонов
return getBuilder(row, currency)
.eventType(CashFlowType.COUPON)
.value(row.getBigDecimalCellValue(DEPOSIT))
.build();
} else if (operation.contains("налог") && operation.contains("дивиденд")) {
} else if (operation.contains("амортизация")) { // Частичное погашение облигации (амортизация номинала)
Instant timestamp = getReport()
.convertToInstant(row.getStringCellValue(DATE))
.plusSeconds(1); // gh-510
return getBuilder(row, currency)
.timestamp(timestamp)
.eventType(CashFlowType.AMORTIZATION)
.value(row.getBigDecimalCellValue(DEPOSIT))
.build();
} else if (operation.contains("погашение") && operation.contains("облигации")) { // Погашение облигации
Instant timestamp = getReport()
.convertToInstant(row.getStringCellValue(DATE))
.plusSeconds(1); // gh-510
return getBuilder(row, currency)
.timestamp(timestamp)
.eventType(CashFlowType.REDEMPTION)
.value(row.getBigDecimalCellValue(DEPOSIT))
.build();
} else if (operation.contains("налог") && operation.contains("дивиденд")) { // Налог (дивиденды)
return getBuilder(row, currency)
.eventType(CashFlowType.TAX)
.value(row.getBigDecimalCellValue(WITHDRAWAL).negate())
.build();
} else if (operation.contains("налог") && operation.contains("купон")) { // предположение, нет примера
} else if (operation.contains("налог") && operation.contains("купон")) { // Налог (купонный доход)
return getBuilder(row, currency)
.eventType(CashFlowType.TAX)
.value(row.getBigDecimalCellValue(WITHDRAWAL).negate())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private Predicate filterByCurrency(Root<ForeignExchangeRateEntity> root, Criteri
if (hasText(currency)) {
Path<String> path = root.get(ForeignExchangeRateEntity_.pk)
.get(ForeignExchangeRateEntityPk_.CURRENCY_PAIR);
return builder.like(path, currency + "%");
return builder.like(builder.lower(path), "%" + currency.toLowerCase() + "%");
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ static <T> Predicate filterBySecurity(Root<T> root,
return builder.or(
builder.equal(securityPath.get(SecurityEntity_.ticker), security),
builder.equal(securityPath.get(SecurityEntity_.isin), security),
builder.like(securityPath.get(SecurityEntity_.name), "%" + security + "%"));
builder.like(builder.lower(securityPath.get(SecurityEntity_.name)),
"%" + security.toLowerCase() + "%"));
}
return null;
}
Expand All @@ -74,7 +75,8 @@ static <T> Predicate filterBySecurityId(Root<T> root,
.where(builder.or(
builder.equal(securities.get(SecurityEntity_.ticker), security),
builder.equal(securities.get(SecurityEntity_.isin), security),
builder.like(securities.get(SecurityEntity_.name), "%" + security + "%")));
builder.like(builder.lower(securities.get(SecurityEntity_.name)),
"%" + security.toLowerCase() + "%")));

Path<Integer> securityIdPath = root.get(attribute);
return builder.in(securityIdPath)
Expand Down Expand Up @@ -190,7 +192,7 @@ static <X> Predicate filterByLike(Root<X> root,
@Nullable String value) {
if (hasText(value)) {
Path<String> path = root.get(attribute);
return builder.like(path, value + "%");
return builder.like(builder.lower(path), value.toLowerCase() + "%");
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import java.util.Optional;

import static org.spacious_team.broker.pojo.SecurityType.ASSET;
import static org.spacious_team.broker.pojo.SecurityType.CURRENCY_PAIR;
import static ru.investbook.repository.RepositoryHelper.isUniqIndexViolationException;

Expand All @@ -42,21 +43,27 @@ public class MoexIssSecurityQuoteService {
private final SecurityQuoteRepository securityQuoteRepository;

public void updateQuote(SecurityEntity security) {
Integer securityId = security.getId();
SecurityType securityType = security.getType();
if (securityType == CURRENCY_PAIR) {
return; // currency pair quote derived from foreign exchange rate, use CbrForeignExchangeRateService
} else if (moexClient.isDerivativeAndExpired(security.getTicker(), securityType)) {
return;
try {
Integer securityId = security.getId();
SecurityType securityType = security.getType();
if (securityType == CURRENCY_PAIR) {
return; // currency pair quote derived from foreign exchange rate, use CbrForeignExchangeRateService
} else if (securityType == ASSET) {
return; // moex has no quotes for arbitrary assets
} else if (moexClient.isDerivativeAndExpired(security.getTicker(), securityType)) {
return;
}
String isinOrContractName = Optional.ofNullable(security.getIsin())
.or(() -> Optional.ofNullable(security.getTicker()))
.orElseThrow();
moexClient.getSecId(isinOrContractName, securityType)
.flatMap(this::getSecurityQuote)
.ifPresentOrElse(
quote -> saveQuote(securityId, quote),
() -> log.debug("Котировка не обновлена. На сайте МосБиржи отсутствует котировка {}", securityId));
} catch (Exception e) {
log.debug("Котировка не обновлена для {}", security, e);
}
String isinOrContractName = Optional.ofNullable(security.getIsin())
.or(() -> Optional.ofNullable(security.getTicker()))
.orElseThrow();
moexClient.getSecId(isinOrContractName, securityType)
.flatMap(this::getSecurityQuote)
.ifPresentOrElse(
quote -> saveQuote(securityId, quote),
() -> log.debug("Котировка не обновлена. На сайте МосБиржи отсутствует котировка {}", securityId));
}

private Optional<SecurityQuote> getSecurityQuote(String moexSecId) {
Expand Down
64 changes: 64 additions & 0 deletions src/main/java/ru/investbook/upgrade/SqlDataExporter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* InvestBook
* Copyright (C) 2023 Spacious Team <spacious-team@ya.ru>
*
* 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 <https://www.gnu.org/licenses/>.
*/

package ru.investbook.upgrade;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.info.BuildProperties;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import ru.investbook.InvestbookProperties;

import javax.annotation.PreDestroy;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.Objects;

@Slf4j
@Service
@RequiredArgsConstructor
public class SqlDataExporter {
private static final String EXPECTED_INVESTBOOK_VERSION_FOR_EXPORT = "2022.9";
private final BuildProperties buildProperties;
private final InvestbookProperties investbookProperties;
private final JdbcTemplate jdbcTemplate;

@PreDestroy
public void preDestroy() {
String version = buildProperties.getVersion();
if (Objects.equals(version, EXPECTED_INVESTBOOK_VERSION_FOR_EXPORT)) {
Path file = investbookProperties.getDataPath()
.resolve("export-" + version + ".sql")
.toAbsolutePath();
exportSqlData(file);
}
}

private void exportSqlData(Path file) {
try {
Instant t0 = Instant.now();
jdbcTemplate.execute("SCRIPT DROP TO '" + file + "' CHARSET 'UTF-8'");
Instant t1 = Instant.now();
log.info("Экспорт БД в файл '{}' завершен за {}", file, Duration.between(t0, t1));
} catch (Exception e) {
log.error("Не смог выполнить экспорт БД в файл '{}'", file, e);
}
}
}
15 changes: 14 additions & 1 deletion src/main/resources/db/migration/h2/beforeValidate.sql
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,17 @@ EXECUTE IMMEDIATE NVL2(
QUOTE_IDENT((SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'flyway_schema_history')),
'UPDATE "flyway_schema_history" SET "checksum" = 38693906 WHERE "version" = ''2021.5.0.0'' AND "installed_rank" <> 1',
'CREATE ALIAS MY_SQRT10 FOR "java.lang.Math.sqrt"' -- do any noop command
);
);

-- Drop previously created temporary objects
DROP ALIAS IF EXISTS MY_SQRT;
DROP ALIAS IF EXISTS MY_SQRT2;
DROP ALIAS IF EXISTS MY_SQRT3;
DROP ALIAS IF EXISTS MY_SQRT4;
DROP ALIAS IF EXISTS MY_SQRT5;
DROP ALIAS IF EXISTS MY_SQRT6;
DROP ALIAS IF EXISTS MY_SQRT7;
DROP ALIAS IF EXISTS MY_SQRT8;
DROP ALIAS IF EXISTS MY_SQRT9;
DROP ALIAS IF EXISTS MY_SQRT10;
DROP ALIAS IF EXISTS MY_SQRT11;