diff --git a/.gitignore b/.gitignore index 9f4f166a..a0272d19 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ investbook/ !.idea/codeStyles !.idea/copyright !.idea/inspectionProfiles +!.idea/encodings.xml ### NetBeans ### /nbproject/private/ diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 00000000..1d82e82f --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index d97c7421..ee9014b8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ [![java-version](https://img.shields.io/badge/java-20-brightgreen?style=flat-square)](https://openjdk.org/) -[![spring-boot-version](https://img.shields.io/badge/spring--boot-3.0.6-brightgreen?style=flat-square)](https://github.com/spring-projects/spring-boot/releases) +[![spring-boot-version](https://img.shields.io/badge/spring--boot-3.0.7-brightgreen?style=flat-square)](https://github.com/spring-projects/spring-boot/releases) [![hits-of-code](https://img.shields.io/badge/dynamic/json?style=flat-square&color=lightblue&label=hits-of-code&url=https://hitsofcode.com/github/spacious-team/investbook/json?branch=develop&query=$.count)](https://hitsofcode.com/github/spacious-team/investbook/view?branch=develop) -![github-closed-pull-requests](https://img.shields.io/github/issues-pr-closed/spacious-team/investbook?style=flat-square&color=brightgreen) -![github-workflow-status](https://img.shields.io/github/actions/workflow/status/spacious-team/investbook/publish-docker.yml?style=flat-square&branch=master) +[![github-closed-pull-requests](https://img.shields.io/github/issues-pr-closed/spacious-team/investbook?style=flat-square&color=brightgreen)](https://github.com/spacious-team/investbook/pulls?q=is%3Apr+is%3Aclosed) +[![github-workflow-status](https://img.shields.io/github/actions/workflow/status/spacious-team/investbook/publish-docker.yml?style=flat-square&branch=master)](https://github.com/spacious-team/investbook/actions/workflows/publish-docker.yml) [![github-all-releases](https://img.shields.io/github/downloads/spacious-team/investbook/total?style=flat-square&logo=github&color=lightblue)](https://github.com/spacious-team/investbook/releases/latest) [![docker-pulls](https://img.shields.io/docker/pulls/spaciousteam/investbook?style=flat-square&logo=docker&color=lightblue&logoColor=white)](https://hub.docker.com/r/spaciousteam/investbook) [![telegram-channel](https://img.shields.io/endpoint?style=flat-square&color=2ca5e0&label=news&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Finvestbook_official)](https://t.me/investbook_official) diff --git a/docs/dbms-changing.md b/docs/dbms-changing.md index 3f737a2f..111cb072 100644 --- a/docs/dbms-changing.md +++ b/docs/dbms-changing.md @@ -6,6 +6,7 @@ Если у вас недостаточно опыта, то рекомендуется пропустить этот раздел. Возможен переход на [MariaDB](https://downloads.mariadb.org/). +Поддерживаются версии, указанные в документации [Flyway](https://documentation.red-gate.com/fd/mariadb-184127600.html). После установки в файле `application-conf.properties` необходимо прописать ``` spring.profiles.active=core,mariadb,conf diff --git a/pom.xml b/pom.xml index 4d7241e9..2748328d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,12 +23,12 @@ org.springframework.boot spring-boot-starter-parent - 3.0.6 + 3.0.7 ru.investbook investbook - 2023.1 + 2023.2 investbook Investor Accounting Book @@ -62,7 +62,7 @@ - 23.1 + 23.2 20 @@ -427,7 +427,7 @@ - gcr.io/paketo-buildpacks/java:9.8.0 + gcr.io/paketo-buildpacks/java:9.20.0 diff --git a/src/main/java/ru/investbook/parser/tinkoff/SecurityCodeAndIsinTable.java b/src/main/java/ru/investbook/parser/tinkoff/SecurityCodeAndIsinTable.java index 291723b2..adaed583 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/SecurityCodeAndIsinTable.java +++ b/src/main/java/ru/investbook/parser/tinkoff/SecurityCodeAndIsinTable.java @@ -20,20 +20,22 @@ import jakarta.validation.constraints.NotNull; import lombok.Getter; +import lombok.RequiredArgsConstructor; import org.spacious_team.broker.pojo.SecurityType; import org.spacious_team.broker.report_parser.api.AbstractReportTable; import org.spacious_team.broker.report_parser.api.BrokerReport; +import org.spacious_team.table_wrapper.api.OptionalTableColumn; import org.spacious_team.table_wrapper.api.PatternTableColumn; import org.spacious_team.table_wrapper.api.TableColumn; import org.spacious_team.table_wrapper.api.TableHeaderColumn; import org.spacious_team.table_wrapper.api.TableRow; -import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import static org.springframework.util.StringUtils.hasLength; import static ru.investbook.parser.tinkoff.SecurityCodeAndIsinTable.SecurityAndCodeTableHeader.*; import static ru.investbook.parser.tinkoff.TinkoffBrokerReport.tablesLastRowPattern; @@ -54,8 +56,10 @@ protected SecurityCodeAndIsinTable(BrokerReport report) { @Override protected Void parseRow(TableRow row) { String code = row.getStringCellValueOrDefault(CODE, null); - if (StringUtils.hasLength(code) && !code.contains("Код актива")) { // exclude table's empty row - codeToIsin.put(code, row.getStringCellValue(ISIN)); + if (hasLength(code) && !code.contains("Код актива")) { // exclude table's empty row + // если колонка ISIN отсутствует, то ISIN используется в отчете вместо кода (SBERP) + String isin = row.getStringCellValueOrDefault(ISIN, code); + codeToIsin.put(code, isin); String type = row.getStringCellValueOrDefault(TYPE, "").toLowerCase(); SecurityType securityType; @@ -74,7 +78,7 @@ protected Void parseRow(TableRow row) { } String shortName = row.getStringCellValueOrDefault(SHORT_NAME, null); - if (StringUtils.hasLength(shortName)) { + if (hasLength(shortName)) { shortNameToCode.put(shortName, code); } } @@ -105,10 +109,11 @@ public String getCode(String shortName) { return Objects.requireNonNull(shortNameToCode.get(shortName), "Не найден код бумаги"); } + @RequiredArgsConstructor protected enum SecurityAndCodeTableHeader implements TableHeaderColumn { SHORT_NAME("Сокращенное", "наименование"), - CODE("код", "актива"), - ISIN("isin"), + CODE("код", "актива"), // код (SBERP) или ISIN + ISIN(optional("isin")), // может отсутствовать, если колонка CODE заполняется ISIN TYPE("^Тип$"), FACE_VALUE("Номинал"); @@ -118,5 +123,9 @@ protected enum SecurityAndCodeTableHeader implements TableHeaderColumn { SecurityAndCodeTableHeader(String... words) { this.column = PatternTableColumn.of(words); } + + static OptionalTableColumn optional(String... words) { + return OptionalTableColumn.of(PatternTableColumn.of(words)); + } } } diff --git a/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTables.java b/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTables.java index e8a6b386..a99348d8 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTables.java +++ b/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTables.java @@ -40,10 +40,12 @@ public class TinkoffReportTables extends AbstractReportTables getSecuritiesTable() { @Override public ReportTable getTransactionTable() { ReportTable transactionTable = - TinkoffSecurityTransactionTable.of(report, securityCodeAndIsinTable, transactionValueAndFeeParser); + TinkoffSecurityTransactionTable.of(report, securityCodeAndIsinTable, transactionValueAndFeeParser, + tinkoffSecurityTransactionTableHelper); TinkoffDepositAndWithdrawalTable depositAndWithdrawalTable = new TinkoffDepositAndWithdrawalTable(report, transactionTable, securityCodeAndIsinTable); return WrappingReportTable.of(transactionTable, depositAndWithdrawalTable); diff --git a/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTablesFactory.java b/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTablesFactory.java index 3e462f13..8866d226 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTablesFactory.java +++ b/src/main/java/ru/investbook/parser/tinkoff/TinkoffReportTablesFactory.java @@ -25,12 +25,14 @@ import org.springframework.stereotype.Component; import ru.investbook.parser.TransactionValueAndFeeParser; import ru.investbook.report.ForeignExchangeRateService; +import ru.investbook.service.moex.MoexDerivativeCodeService; @Component @RequiredArgsConstructor public class TinkoffReportTablesFactory implements ReportTablesFactory { private final TransactionValueAndFeeParser transactionValueAndFeeParser; private final ForeignExchangeRateService foreignExchangeRateService; + private final MoexDerivativeCodeService moexDerivativeCodeService; @Override public boolean canCreate(BrokerReport brokerReport) { @@ -39,7 +41,9 @@ public boolean canCreate(BrokerReport brokerReport) { @Override public ReportTables create(BrokerReport brokerReport) { + TinkoffSecurityTransactionTableHelper tinkoffSecurityTransactionTableHelper = + new TinkoffSecurityTransactionTableHelper(moexDerivativeCodeService); return new TinkoffReportTables((TinkoffBrokerReport) brokerReport, - transactionValueAndFeeParser, foreignExchangeRateService); + transactionValueAndFeeParser, foreignExchangeRateService, tinkoffSecurityTransactionTableHelper); } } diff --git a/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTable.java b/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTable.java index 696be0b1..f2a0df27 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTable.java +++ b/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTable.java @@ -21,6 +21,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.spacious_team.broker.pojo.SecurityType; import org.spacious_team.broker.report_parser.api.AbstractTransaction; import org.spacious_team.broker.report_parser.api.DerivativeTransaction; import org.spacious_team.broker.report_parser.api.ForeignExchangeTransaction; @@ -39,37 +40,39 @@ import java.time.Instant; import static ru.investbook.parser.tinkoff.TinkoffSecurityTransactionTable.TransactionTableHeader.*; -import static ru.investbook.parser.tinkoff.TinkoffSecurityTransactionTableHelper.getSecurityId; -import static ru.investbook.parser.tinkoff.TinkoffSecurityTransactionTableHelper.getSecurityType; @Slf4j public class TinkoffSecurityTransactionTable extends SingleAbstractReportTable { private final SecurityCodeAndIsinTable codeAndIsin; private final TransactionValueAndFeeParser transactionValueAndFeeParser; + private final TinkoffSecurityTransactionTableHelper transactionTableHelper; public static ReportTable of(TinkoffBrokerReport report, SecurityCodeAndIsinTable codeAndIsin, - TransactionValueAndFeeParser transactionValueAndFeeParser) { + TransactionValueAndFeeParser transactionValueAndFeeParser, + TinkoffSecurityTransactionTableHelper transactionTableHelper) { return WrappingReportTable.of( new TinkoffSecurityTransactionTable( "1.1 Информация о совершенных и исполненных сделках", - report, codeAndIsin, transactionValueAndFeeParser), + report, codeAndIsin, transactionValueAndFeeParser, transactionTableHelper), new TinkoffSecurityTransactionTable( "1.2 Информация о неисполненных сделках на конец отчетного периода", - report, codeAndIsin, transactionValueAndFeeParser)); + report, codeAndIsin, transactionValueAndFeeParser, transactionTableHelper)); } private TinkoffSecurityTransactionTable(String tableNamePrefix, TinkoffBrokerReport report, SecurityCodeAndIsinTable codeAndIsin, - TransactionValueAndFeeParser transactionValueAndFeeParser) { + TransactionValueAndFeeParser transactionValueAndFeeParser, + TinkoffSecurityTransactionTableHelper transactionTableHelper) { super(report, cell -> cell.startsWith(tableNamePrefix), cell -> TinkoffBrokerReport.tablesLastRowPattern.matcher(cell).lookingAt(), TransactionTableHeader.class); this.codeAndIsin = codeAndIsin; this.transactionValueAndFeeParser = transactionValueAndFeeParser; + this.transactionTableHelper = transactionTableHelper; } @Override @@ -78,7 +81,7 @@ protected AbstractTransaction parseRow(TableRow row) { if (_tradeId == -1) return null; String tradeId = String.valueOf(_tradeId); - int securityId = getSecurityId(row, codeAndIsin, getReport().getSecurityRegistrar()); + int securityId = transactionTableHelper.getSecurityId(row, codeAndIsin, getReport().getSecurityRegistrar()); boolean isBuy = row.getStringCellValue(OPERATION).toLowerCase().contains("покупка"); int count = Math.abs(row.getIntCellValue(COUNT)); BigDecimal amount = row.getBigDecimalCellValue(AMOUNT).abs(); @@ -86,7 +89,8 @@ protected AbstractTransaction parseRow(TableRow row) { count = isBuy ? count : -count; Instant timestamp = null; - AbstractTransaction.AbstractTransactionBuilder builder = switch (getSecurityType(row)) { + SecurityType securityType = transactionTableHelper.getSecurityType(row); + AbstractTransaction.AbstractTransactionBuilder builder = switch (securityType) { case STOCK -> SecurityTransaction.builder() .timestamp(timestamp = getStockAndBondTransactionInstant(row)); case BOND, STOCK_OR_BOND -> { @@ -137,7 +141,11 @@ protected AbstractTransaction parseRow(TableRow row) { } private Instant getStockAndBondTransactionInstant(TableRow row) { - return getReport().convertToInstant(row.getStringCellValue(SETTLEMENT_DATE)); + String settlementDate = row.getStringCellValue(SETTLEMENT_DATE); + // В старых отчетах одна дата, с января 2023 две: план/факт + String[] dates = settlementDate.split("/"); + String date = (dates.length == 1) ? dates[0] : dates[1]; + return getReport().convertToInstant(date); } private Instant getDerivativeAndCurrencyPairTransactionInstant(TableRow row) { @@ -150,7 +158,7 @@ protected enum TransactionTableHeader implements TableHeaderColumn { TRADE_ID("номер", "сделки"), TRANSACTION_DATE("дата", "заклю", "чения"), TRANSACTION_TIME("время"), - TYPE("режим", "торгов"), + TYPE(optional("режим", "торгов")), OPERATION("вид", "сделки"), SHORT_NAME("сокращен", "наименова"), CODE("код", "актива"), @@ -177,5 +185,9 @@ protected enum TransactionTableHeader implements TableHeaderColumn { TransactionTableHeader(String... words) { this.column = PatternTableColumn.of(words); } + + static OptionalTableColumn optional(String... words) { + return OptionalTableColumn.of(PatternTableColumn.of(words)); + } } } diff --git a/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTableHelper.java b/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTableHelper.java index 2063826b..7fd595ad 100644 --- a/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTableHelper.java +++ b/src/main/java/ru/investbook/parser/tinkoff/TinkoffSecurityTransactionTableHelper.java @@ -18,19 +18,25 @@ package ru.investbook.parser.tinkoff; +import lombok.RequiredArgsConstructor; import org.spacious_team.broker.pojo.Security; import org.spacious_team.broker.pojo.SecurityType; import org.spacious_team.table_wrapper.api.TableRow; +import org.springframework.stereotype.Component; import ru.investbook.parser.SecurityRegistrar; +import ru.investbook.service.moex.MoexDerivativeCodeService; import java.math.BigDecimal; import java.util.Objects; import static ru.investbook.parser.tinkoff.TinkoffSecurityTransactionTable.TransactionTableHeader.*; -class TinkoffSecurityTransactionTableHelper { +@Component +@RequiredArgsConstructor +public class TinkoffSecurityTransactionTableHelper { + private final MoexDerivativeCodeService moexDerivativeCodeService; - static int getSecurityId(TableRow row, + int getSecurityId(TableRow row, SecurityCodeAndIsinTable codeAndIsin, SecurityRegistrar registrar) { String code = row.getStringCellValue(CODE); @@ -40,7 +46,7 @@ static int getSecurityId(TableRow row, return declareSecurity(security, registrar); } - static SecurityType getSecurityType(TableRow row) { + SecurityType getSecurityType(TableRow row) { BigDecimal accruedInterest = row.getBigDecimalCellValueOrDefault(ACCRUED_INTEREST, BigDecimal.ZERO); if (accruedInterest.floatValue() > 1e-3) { return SecurityType.BOND; @@ -56,6 +62,8 @@ static SecurityType getSecurityType(TableRow row) { String shortName = row.getStringCellValueOrDefault(SHORT_NAME, ""); if (shortName != null && shortName.length() == 10 && shortName.charAt(6) == '_') { // USDRUB_TOM return SecurityType.CURRENCY_PAIR; + } else if (moexDerivativeCodeService.isFuturesCode(shortName) || moexDerivativeCodeService.isOption(shortName)) { + return SecurityType.DERIVATIVE; } return SecurityType.STOCK; diff --git a/src/main/java/ru/investbook/service/moex/MoexDerivativeCodeService.java b/src/main/java/ru/investbook/service/moex/MoexDerivativeCodeService.java index fd7471d6..64ca1642 100644 --- a/src/main/java/ru/investbook/service/moex/MoexDerivativeCodeService.java +++ b/src/main/java/ru/investbook/service/moex/MoexDerivativeCodeService.java @@ -38,9 +38,9 @@ * * @see Specifications ticker codes for Futures and Options */ +@Slf4j @Component @RequiredArgsConstructor -@Slf4j public class MoexDerivativeCodeService { private final Map codeToShortnames = Stream.of(new String[][]{ @@ -56,6 +56,8 @@ public class MoexDerivativeCodeService { {"MA", "MMI"}, // Индекс МосБиржи металлов и добычи {"FN", "FNI"}, // Индекс МосБиржи финансов {"CS", "CNI"}, // Индекс МосБиржи потребительского сектора + {"RB", "RGBI"}, // Индекс RGBI + {"AF", "AFLT"}, // ПАО "Аэрофлот" (о.а.) {"AL", "ALRS"}, // АК "АЛРОСА" (ПАО) (о.а.) {"CH", "CHMF"}, // ПАО "Северсталь" (о.а.) @@ -80,7 +82,7 @@ public class MoexDerivativeCodeService { {"TF", "TRNS"}, // 0, 1 стоимости одной акции ПАО "Транснефть" {"VB", "VTBR"}, // Банк ВТБ (ПАО) (о.а.) {"MG", "MAGN"}, // ПАО "Магнитогорский металлургический комбинат" (о.а.) - {"PL", "PLZL"}, // ПАО "Полюс" (о.а.) + {"PZ", "PLZL"}, // ПАО "Полюс" (о.а.) {"YN", "YNDF"}, // Яндекс Н.В. (о.а.) {"AK", "AFKS"}, // АФК Система (о.а.) {"IR", "IRAO"}, // ПАО "Интер РАО ЕЭС" (о.а.) @@ -102,6 +104,7 @@ public class MoexDerivativeCodeService { {"BI", "BIDU"}, // АДР Байду Инк {"BA", "BABA"}, // АДР Алибаба Груп Холдинг Лимитед {"SF", "SPYF"}, // SPDR S&P 500 ETF Trust + {"NA", "NASD"}, // Invesco QQQ ETF Trust Unit Series 1 {"DM", "GDAI"}, // Daimler AG (о.а.) {"DB", "GDBK"}, // Deutsche Bank AG (о.а.) {"SM", "GSIE"}, // Siemens AG (о.а.) @@ -112,27 +115,55 @@ public class MoexDerivativeCodeService { {"O4", "OFZ4"}, // "четырехлетние" облигации федерального займа {"O6", "OFZ6"}, // "шестилетние" облигации федерального займа {"MP", "MOPR"}, // ставка MosPrime + {"PS", "POSI"}, // ПАО Группа Позитив + {"SX", "STOX"}, // iShares Core EURO STOXX 50 UCITS ETF EUR (Dist) + {"HS", "HANG"}, // Tracker Fund of Hong Kong ETF + {"DX", "DAX"}, // iShares Core DAX UCITS ETF (DE) + {"N2", "NIKK"}, // iShares Core Nikkei 225 ETF + {"IS", "ISKJ"}, // ПАО "ИСКЧ" + {"WU", "WUSH"}, // ПАО "ВУШ Холдинг" + {"MV", "MVID"}, // ПАО "М.видео" + {"CM", "CBOM"}, // ПАО "М.видео" + {"SZ", "SGZH"}, // ПАО "Сегежа Групп" + {"BE", "BELU"}, // ПАО "Белуга Групп" + {"FL", "FLOT"}, // ПАО "Совкомфлот" + {"RR", "RUON"}, // ставка RUONIA {"MF", "1MFR"}, // ставка RUSFAR {"DF", "1MDR"}, // Ставка RUSFARUSD - {"AU", "AUDU"}, // курс австралийский доллар – доллар США - {"CY", "CY"}, // курс китайский юань – российский рубль - {"ED", "ED"}, // курс евро – доллар США + + {"CY", "CY"}, // курс китайский юань – российский рубль (старый) + {"CR", "CNY"}, // курс китайский юань – российский рубль (актуальный) {"Eu", "Eu"}, // курс евро – российский рубль - {"GU", "GBPU"}, // курс фунт стерлингов – доллар США {"Si", "Si"}, // курс доллар США – российский рубль + {"USDRUBF", "USDRUBF"}, // курс доллара США - российский рубль + {"EURRUBF", "EURRUBF"}, // курс евро - российский рубль + {"CNYRUBF", "CNYRUBF"}, // курс китайский юань – российский рубль + {"TY", "TRY"}, // курс турецкая лира – российский рубль + {"HK", "HKD"}, // курс гонконгский доллар – российский рубль + {"AE", "AED"}, // курс дирхам ОАЭ – российский рубль + {"I2", "INR"}, // курс индийская рупия – российский рубль + {"KZ", "KZT"}, // курс казахстанский тенге – российский рубль + {"AR", "AMD"}, // курс армянский драм – российский рубль + {"ED", "ED"}, // курс евро – доллар США + {"AU", "AUDU"}, // курс австралийский доллар – доллар США + {"GU", "GBPU"}, // курс фунт стерлингов – доллар США {"CA", "UCAD"}, // курс доллар США – канадский доллар {"CF", "UCHF"}, // курс доллар США – швейцарский франк {"JP", "UJPY"}, // курс доллар США – японская йена {"TR", "UTRY"}, // курс доллар США – турецкая лира + {"UC", "UCNY"}, // курс доллар США – китайский юань {"IN", "UINR"}, // курс доллара США к индийской рупии {"UU", "UUAH"}, // курс доллар США – украинская гривна {"EG", "EGBP"}, // курс евро – фунт стерлингов {"EC", "ECAD"}, // курс евро – канадский доллар {"EJ", "EJPY"}, // курс евро – японская йена + {"BR", "BR"}, // нефть BRENT {"CU", "CU"}, // медь {"GD", "GOLD"}, // золото + {"GL", "GL"}, // Золото (в рублях) + {"GLDRUBF", "GLDRUBF"}, // золото {"PD", "PLD"}, // палладий {"PT", "PLT"}, // платина {"SV", "SILV"}, // серебро @@ -145,7 +176,8 @@ public class MoexDerivativeCodeService { {"Nl", "Nl"}, // никель с чистотой 99,80% (минимум) {"Zn", "Zn"}, // цинк {"NG", "NG"}, // природный газ - {"WH", "WH4"} // пшеница + {"WH", "WH4"}, // пшеница + {"W4", "WHEAT"} // Индекс пшеницы }).collect(Collectors.toMap(a -> a[0], a -> a[1])); private final Map shortnameToCodes = codeToShortnames.entrySet() diff --git a/src/main/java/ru/investbook/web/forms/model/TransactionModel.java b/src/main/java/ru/investbook/web/forms/model/TransactionModel.java index 96d55783..8afeddea 100644 --- a/src/main/java/ru/investbook/web/forms/model/TransactionModel.java +++ b/src/main/java/ru/investbook/web/forms/model/TransactionModel.java @@ -89,7 +89,7 @@ public class TransactionModel { private BigDecimal price; @Nullable - @Positive + @PositiveOrZero private BigDecimal accruedInterest; /** diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index c5a6a3e8..c077630a 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -17,10 +17,11 @@ # # MariaDB -#spring.datasource.url = jdbc:mysql://localhost:3306/portfolio?createDatabaseIfNotExist=true&serverTimezone=Europe/Moscow +#spring.datasource.url = jdbc:mariadb://localhost:3306/portfolio?createDatabaseIfNotExist=true&serverTimezone=Europe/Moscow #spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MariaDBDialect #spring.datasource.username = root #spring.datasource.password = 123456 +#spring.datasource.driver-class-name=org.mariadb.jdbc.Driver # H2 spring.datasource.url=jdbc:h2:file:~/investbook2-test;mode=mysql;non_keywords=value diff --git a/src/main/resources/application-mariadb.properties b/src/main/resources/application-mariadb.properties index c3e10dd5..b5b6be7a 100644 --- a/src/main/resources/application-mariadb.properties +++ b/src/main/resources/application-mariadb.properties @@ -1,4 +1,5 @@ -spring.datasource.url=jdbc:mysql://localhost:3306/portfolio?createDatabaseIfNotExist=true&serverTimezone=Europe/Moscow +spring.datasource.url=jdbc:mariadb://localhost:3306/portfolio?createDatabaseIfNotExist=true&serverTimezone=Europe/Moscow spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MariaDBDialect spring.datasource.username=root -spring.datasource.password=123456 \ No newline at end of file +spring.datasource.password=123456 +spring.datasource.driver-class-name=org.mariadb.jdbc.Driver \ No newline at end of file diff --git a/src/main/resources/db/migration/h2/V2023_2_0_0.sql b/src/main/resources/db/migration/h2/V2023_2_0_0.sql new file mode 100644 index 00000000..d017157e --- /dev/null +++ b/src/main/resources/db/migration/h2/V2023_2_0_0.sql @@ -0,0 +1,26 @@ +/* + * 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 . + */ + +ALTER TABLE `event_cash_flow` + ALTER COLUMN `value` DECIMAL(15,6) NOT NULL COMMENT 'Размер'; + +ALTER TABLE `security_event_cash_flow` + ALTER COLUMN `value` DECIMAL(15,6) NOT NULL COMMENT 'Размер'; + +ALTER TABLE `transaction_cash_flow` + ALTER COLUMN `value` DECIMAL(15,6) NOT NULL COMMENT 'Размер'; diff --git a/src/main/resources/db/migration/mysql/V2020_11_0_0.sql b/src/main/resources/db/migration/mariadb/V2020_11_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2020_11_0_0.sql rename to src/main/resources/db/migration/mariadb/V2020_11_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2020_13_0_0.sql b/src/main/resources/db/migration/mariadb/V2020_13_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2020_13_0_0.sql rename to src/main/resources/db/migration/mariadb/V2020_13_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2020_7_0_0.sql b/src/main/resources/db/migration/mariadb/V2020_7_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2020_7_0_0.sql rename to src/main/resources/db/migration/mariadb/V2020_7_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_11_0_0.sql b/src/main/resources/db/migration/mariadb/V2021_11_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_11_0_0.sql rename to src/main/resources/db/migration/mariadb/V2021_11_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_11_0_2.sql b/src/main/resources/db/migration/mariadb/V2021_11_0_2.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_11_0_2.sql rename to src/main/resources/db/migration/mariadb/V2021_11_0_2.sql diff --git a/src/main/resources/db/migration/mysql/V2021_11_0_4.sql b/src/main/resources/db/migration/mariadb/V2021_11_0_4.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_11_0_4.sql rename to src/main/resources/db/migration/mariadb/V2021_11_0_4.sql diff --git a/src/main/resources/db/migration/mysql/V2021_2_0_0.sql b/src/main/resources/db/migration/mariadb/V2021_2_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_2_0_0.sql rename to src/main/resources/db/migration/mariadb/V2021_2_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_2_1_0.sql b/src/main/resources/db/migration/mariadb/V2021_2_1_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_2_1_0.sql rename to src/main/resources/db/migration/mariadb/V2021_2_1_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_4_1_0.sql b/src/main/resources/db/migration/mariadb/V2021_4_1_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_4_1_0.sql rename to src/main/resources/db/migration/mariadb/V2021_4_1_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_5_0_0.sql b/src/main/resources/db/migration/mariadb/V2021_5_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_5_0_0.sql rename to src/main/resources/db/migration/mariadb/V2021_5_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_6_0_0.sql b/src/main/resources/db/migration/mariadb/V2021_6_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_6_0_0.sql rename to src/main/resources/db/migration/mariadb/V2021_6_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2021_9_0_0.sql b/src/main/resources/db/migration/mariadb/V2021_9_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2021_9_0_0.sql rename to src/main/resources/db/migration/mariadb/V2021_9_0_0.sql diff --git a/src/main/resources/db/migration/mysql/V2022_2_0_0.sql b/src/main/resources/db/migration/mariadb/V2022_2_0_0.sql similarity index 100% rename from src/main/resources/db/migration/mysql/V2022_2_0_0.sql rename to src/main/resources/db/migration/mariadb/V2022_2_0_0.sql diff --git a/src/main/resources/db/migration/mariadb/V2023_2_0_0.sql b/src/main/resources/db/migration/mariadb/V2023_2_0_0.sql new file mode 100644 index 00000000..fd4e2977 --- /dev/null +++ b/src/main/resources/db/migration/mariadb/V2023_2_0_0.sql @@ -0,0 +1,26 @@ +/* + * 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 . + */ + +ALTER TABLE `event_cash_flow` CHANGE COLUMN `value` + `value` DECIMAL(15,6) NOT NULL COMMENT 'Размер' AFTER `type`; + +ALTER TABLE `security_event_cash_flow` CHANGE COLUMN `value` + `value` DECIMAL(15,6) NOT NULL COMMENT 'Размер' AFTER `type`; + +ALTER TABLE `transaction_cash_flow` CHANGE COLUMN `value` + `value` DECIMAL(15,6) NOT NULL COMMENT 'Размер' AFTER `type`; diff --git a/src/main/resources/templates/events/edit-form.html b/src/main/resources/templates/events/edit-form.html index a4c0a360..169c875d 100644 --- a/src/main/resources/templates/events/edit-form.html +++ b/src/main/resources/templates/events/edit-form.html @@ -100,7 +100,7 @@

Редактировать событие