diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/CSVReportBuilder.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/CSVReportBuilder.java new file mode 100644 index 000000000..92f57089d --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/CSVReportBuilder.java @@ -0,0 +1,115 @@ +package ru.spcex.clearing.reports.reports; + +import com.opencsv.CSVWriterBuilder; +import com.opencsv.ICSVWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.spcex.platform.enumeration.ReportType; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.time.format.DateTimeFormatter; +import java.util.List; + +/** + * Класс для построения отчетов в формате CSV + * + * @param

тип параметров, используемых при построении отчета + */ +public abstract class CSVReportBuilder

{ + protected static final Logger log = LoggerFactory.getLogger(CSVReportBuilder.class); + + protected DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy"); + protected DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy'T'HH:mm:ss"); + protected DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss"); + + /** + * Метод получения заголовков для CSV отчета + */ + protected abstract String[] getHeaders(); + + /** + * Возвращает списком значения CSV отчета. Каждый элемент списка - строка, элемент массива внутри списка - столбец. + */ + protected abstract List getLines(); + + /** + * Название отчета, используется для формирования имени отчета + * + * @param params Параметры формирования отчета + */ + protected abstract String getReportFilename(P params); + + /** + * Тип отчета по {@link ReportType} + */ + protected abstract ReportType getReportType(); + + /** + * Формирование отчета на основе параметров + * + * @param params Параметры формирования отчета + */ + protected abstract void collect(P params); + + /** + * Создает CSVWriter. Если требуется изменить параметры выходного CSV файла, этот метод следует переопределить. + * + * @param file Файл отчета + * @return Созданный CSVWriter + * + * todo check it + */ + protected ICSVWriter createCsvWriter(File file) throws IOException { + Writer writer = new FileWriter(file); + CSVWriterBuilder csvWriterBuilder = new CSVWriterBuilder(writer) + .withLineEnd("\n") + .withSeparator(',') + .withQuoteChar('\'') + .withEscapeChar('\"'); + return csvWriterBuilder.build(); + } + + public File createReport(P params, File outFolder) { + assert outFolder != null && outFolder.isDirectory(); + + File reportFile = new File(outFolder, normalizeFilenameForOS(getReportFilename(params))); + + collect(params); + String[] headers = getHeaders(); + List lines = getLines(); + + assert headers != null; + assert lines != null; + + try (ICSVWriter csvWriter = createCsvWriter(reportFile)) { + csvWriter.writeNext(headers); + csvWriter.writeAll(lines, true); + } catch (IOException e) { + // todo check it + e.printStackTrace(); + } + + return reportFile; + } + + protected String normalizeFilenameForOS(String filename) { + if (System.getProperty("os.name").toLowerCase().contains("windows")) + return filename.replace(":", "_"); + return filename; + } + + public void setDateFormatter(DateTimeFormatter dateFormatter) { + this.dateFormatter = dateFormatter; + } + + public void setDateTimeFormatter(DateTimeFormatter dateTimeFormatter) { + this.dateTimeFormatter = dateTimeFormatter; + } + + public void setTimeFormatter(DateTimeFormatter timeFormatter) { + this.timeFormatter = timeFormatter; + } +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/PeriodParams.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/PeriodParams.java new file mode 100644 index 000000000..4d30c335a --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/PeriodParams.java @@ -0,0 +1,27 @@ +package ru.spcex.clearing.reports.reports; + +import java.time.LocalDate; + +/** + * Параметры для формирования отчета на период + */ +public class PeriodParams { + private LocalDate startDate; + private LocalDate endDate; + + public LocalDate getStartDate() { + return startDate; + } + + public void setStartDate(LocalDate startDate) { + this.startDate = startDate; + } + + public LocalDate getEndDate() { + return endDate; + } + + public void setEndDate(LocalDate endDate) { + this.endDate = endDate; + } +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/SessionIdParam.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/SessionIdParam.java new file mode 100644 index 000000000..e2a529e6b --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/SessionIdParam.java @@ -0,0 +1,16 @@ +package ru.spcex.clearing.reports.reports; + +/** + * Параметры для формирования отчета по SessionId + */ +public class SessionIdParam { + private Long sessionId; + + public Long getSessionId() { + return sessionId; + } + + public void setSessionId(Long sessionId) { + this.sessionId = sessionId; + } +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/ExecutedDealReport.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/ExecutedDealReport.java deleted file mode 100644 index ab4b4faf2..000000000 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/ExecutedDealReport.java +++ /dev/null @@ -1,40 +0,0 @@ -package ru.spcex.clearing.reports.reports.bp; - -import ru.spcex.clearing.reports.reports.ReportId; -import ru.spcex.clearing.reports.reports.ReportWithPeriod; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -public class ExecutedDealReport extends ReportWithPeriod { - - private final String[] headers = { - "id", "securityId", "tradeNo", "tradeDate", "tradeTime", "settleDate", "settleCode", "price", "quanity", "value" - }; - - public ExecutedDealReport(LocalDate startDate, LocalDate endDate) { - super(ReportId.EXECUTED_DEAL_REPORT, - "0.0.1", - "BP", - "Реестр сделок, принятых на клиринг", - startDate, - endDate); - } - - @Override - public String getReportName(LocalDateTime reportDateTime) { - return "executed_deal_report.%s-%s.%s".formatted( - DATE_FORMATTER.format(startDate), - DATE_FORMATTER.format(endDate), - DATE_TIME_FORMATTER.format(reportDateTime) - ); - } - - public String[] getHeaders() { - return headers; - } - - public record InfoExecutedDeal(String id, String securityId, String tradeNo, String tradeDate, String tradeTime, - String settleDate, String settleCode, String price, String quanity, String value) { - } -} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/ExecutedDealReportBuilder.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/ExecutedDealReportBuilder.java new file mode 100644 index 000000000..e44f37993 --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/ExecutedDealReportBuilder.java @@ -0,0 +1,108 @@ +package ru.spcex.clearing.reports.reports.bp; + +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.execution.ExecutionFond; +import ru.clearing.classes.statics.data.misc.STrades; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.reports.reports.CSVReportBuilder; +import ru.spcex.clearing.reports.reports.SessionIdParam; +import ru.spcex.platform.enumeration.Allowed; +import ru.spcex.platform.enumeration.ReportType; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; + +import java.math.RoundingMode; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class ExecutedDealReportBuilder extends CSVReportBuilder { + private final Imdg executionFondImdg; + private final Imdg companyImdg; + private final Imdg sTradesImdg; + + private final String[] headers = { + "id", "securityId", "tradeNo", "tradeDate", "tradeTime", + "settleDate", "settleCode", "price", "quanity", "value" + }; + private List lines = null; + + public ExecutedDealReportBuilder(ImdgProvider imdgProvider) { + this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.sTradesImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_STrades, STrades.class); + } + + @Override + public String[] getHeaders() { + return headers; + } + + @Override + protected List getLines() { + return lines; + } + + @Override + protected String getReportFilename(SessionIdParam params) { + return "executed_deal_report.%s".formatted(LocalDateTime.now()); + } + + @Override + protected ReportType getReportType() { + return ReportType.EXECUTED_DEAL_REPORT; + } + + @Override + protected void collect(SessionIdParam params) { + ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder(); + ImdgPredicate predicate = pb.and( + pb.equals("sessionId", params.getSessionId()), + pb.equals("coverageStatus", Allowed.DENIED.getKey()) + ); + Collection executionFonds = executionFondImdg.getCollectionObjectsByPredicate(predicate); + + lines = new ArrayList<>(executionFonds.size()); + for (ExecutionFond executionFond : executionFonds) { + Company company = companyImdg.getSingleObjectByID(executionFond.getCompanyId()); + if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) continue; + STrades sTrade = sTradesImdg.getSingleObjectByFieldValues( + Map.of( + "tradeNum", executionFond.getExchangeExecutionId(), + "operation", executionFond.getSide() + ) + ); + + String id = String.valueOf(executionFond.getId()); + String securityId = String.valueOf(executionFond.getSecurityId()); + String tradeNo = String.valueOf(executionFond.getExchangeExecutionId()); + String tradeDate = dateFormatter.format(executionFond.getTradingDate()); + String tradeTime = dateFormatter.format(executionFond.getCreated()); + String settleDate = dateFormatter.format(executionFond.getSettlementDate()); + String settleCode = sTrade != null ? sTrade.getSettleCode() : ""; + String quantity = String.valueOf(executionFond.getQuantity()); + String value = String.valueOf(executionFond.getSettlementAmount()); + String price = String.valueOf(executionFond.getSettlementAmount().divide(executionFond.getQuantity(), RoundingMode.HALF_UP)); + + int valueIdx = 0; + String[] line = new String[getHeaders().length]; + line[valueIdx++] = id; + line[valueIdx++] = securityId; + line[valueIdx++] = tradeNo; + line[valueIdx++] = tradeDate; + line[valueIdx++] = tradeTime; + line[valueIdx++] = settleDate; + line[valueIdx++] = settleCode; + line[valueIdx++] = price; + line[valueIdx++] = quantity; + line[valueIdx++] = value; + lines.add(line); + } + } + +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalLiabilitiesClaimsReport.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalLiabilitiesClaimsReport.java deleted file mode 100644 index 7953a2614..000000000 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalLiabilitiesClaimsReport.java +++ /dev/null @@ -1,53 +0,0 @@ -package ru.spcex.clearing.reports.reports.bp; - -import ru.spcex.clearing.reports.reports.ReportId; -import ru.spcex.clearing.reports.reports.ReportWithPeriod; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -// todo check typo -public class OperationalLiabilitiesClaimsReport extends ReportWithPeriod { - - private final String[] headers = { - "id", "doc_date", "doc_time", "doc_type", "clearingHouse", "firmId", "firName", "session_id", - "clearing_date", "clearing_time", "trdAccId", "account", "depo_account", "currency", "tr_id", "securityId", - "tr_buySell", "tr_date", "tr_execDate", "exec_status", "repaym_date", "tr_price", "nominal", "lot_value", - "tr_lot", "tr_quantity", "tr_value", "tr_accruedint", "accruedint", "tr_clrComm", "tr_exhComm", "cash_liability", - "depo_liability", "cash_netto", "depo_netto" - }; - - public OperationalLiabilitiesClaimsReport(LocalDate startDate, LocalDate endDate) { - super(ReportId.OPERATIONAL_LIABILITIES_CLAIMS, - "0.0.1", - "BP2", - "Операционный отчет. Отчет об обязательствах", - startDate, - endDate); - } - - @Override - public String getReportName(LocalDateTime reportDateTime) { - return "operational_liabilities_claims.%s-%s.%s".formatted( - DATE_FORMATTER.format(startDate), - DATE_FORMATTER.format(endDate), - DATE_TIME_FORMATTER.format(reportDateTime) - ); - } - - public String[] getHeaders() { - return headers; - } - - public record InfoOperationalLiabilitiesClaims(String id, String docDate, String docTime, String docName, - String docType, String clearingHouse, String firmId, String firName, - String sessionId, String clearingDate, String clearingTime, - String trdAccId, String account, String depoAccount, String currency, - String trId, String securityId, String trBuySell, String trDate, - String trExecDate, String execStatus, String repaymDate, String trPrice, - String nominal, String lotValue, String trLot, String trQuantity, - String trValue, String trAccruedInt, String accruedInt, String trClrComm, - String trExhComm, String cashLiability, String depoLiability, - String cashNetto, String depoNetto) { - } -} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalLiabilitiesClaimsReportBuilder.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalLiabilitiesClaimsReportBuilder.java new file mode 100644 index 000000000..766f436a8 --- /dev/null +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalLiabilitiesClaimsReportBuilder.java @@ -0,0 +1,263 @@ +package ru.spcex.clearing.reports.reports.bp; + +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.clearing.classes.statics.data.execution.ExecutionFond; +import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity; +import ru.clearing.classes.statics.data.misc.Listing; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.reports.reports.CSVReportBuilder; +import ru.spcex.clearing.reports.reports.SessionIdParam; +import ru.spcex.platform.enumeration.Market; +import ru.spcex.platform.enumeration.ReportType; +import ru.spcex.platform.enumeration.Side; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; + +import java.math.RoundingMode; +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +// todo check typo +public class OperationalLiabilitiesClaimsReportBuilder extends CSVReportBuilder { + private final Imdg executionFondImdg; + private final Imdg executionDepositImdg; + private final Imdg companyImdg; + private final Imdg registryImdg; + private final Imdg

listingImdg; + private final Imdg fixedIncomeSecurityImdg; + private final Imdg tradingClearingRegistryImdg; + + private final String[] headers = { + "id", "doc_date", "doc_time", "doc_type", "clearingHouse", "firmId", "firName", "session_id", + "clearing_date", "clearing_time", "trdAccId", "account", "depo_account", "currency", "tr_id", "securityId", + "tr_buySell", "tr_date", "tr_execDate", "exec_status", "repaym_date", "tr_price", "nominal", "lot_value", + "tr_lot", "tr_quantity", "tr_value", "tr_accruedint", "accruedint", "tr_clrComm", "tr_exhComm", "cash_liability", + "depo_liability", "cash_netto", "depo_netto" + }; + private List lines = null; + + public OperationalLiabilitiesClaimsReportBuilder(ImdgProvider imdgProvider) { + this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class); + this.fixedIncomeSecurityImdg = imdgProvider.getImdg( + IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class + ); + this.tradingClearingRegistryImdg = imdgProvider.getImdg( + IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class + ); + } + + @Override + public String[] getHeaders() { + return headers; + } + + @Override + protected List getLines() { + return lines; + } + + @Override + protected String getReportFilename(SessionIdParam params) { + return "operational_liabilities_claims.%s".formatted(LocalDateTime.now()); + } + + @Override + protected ReportType getReportType() { + return ReportType.OPERATIONAL_LIABILITIES_CLAIMS; + } + + @Override + protected void collect(SessionIdParam params) { + ImdgPredicate executionFondPredicate = executionFondImdg + .predicateBuilder() + .equals("sessionId", params.getSessionId()); + Collection executionFonds = executionFondImdg.getCollectionObjectsByPredicate(executionFondPredicate); + + ImdgPredicate executionDepositPredicate = executionDepositImdg + .predicateBuilder() + .equals("sessionId", params.getSessionId()); + Collection executionDeposits = executionDepositImdg.getCollectionObjectsByPredicate(executionDepositPredicate); + + List executions = new ArrayList<>(executionFonds.size() + executionDeposits.size()); + executions.addAll(executionFonds); + executions.addAll(executionDeposits); + + Company clearingHouseCompany = companyImdg.getSingleObjectByID(1L); + String clearingHouse = clearingHouseCompany.getFullName(); + + Instant now = Instant.now(); + lines = new ArrayList<>(executions.size()); + for (ExecutionCommon execution : executions) { + Company company = companyImdg.getSingleObjectByID(execution.getCompanyId()); + if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) continue; + + Registry registry = registryImdg.getSingleObjectByFieldValues(Map.of("companyId", execution.getCompanyId())); + Collection registriesForSessionId = registryImdg.getCollectionObjectsByFieldValues( + Map.of("sessionId", execution.getSessionId()) + ); + Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", execution.getSecurityId())); + FixedIncomeSecurity fixedIncomeSecurity = fixedIncomeSecurityImdg.getSingleObjectByFieldValues( + Map.of("securityId", execution.getSecurityId()) + ); + TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getSingleObjectByID( + execution.getTradingClearingRegistryId() + ); + + String id = String.valueOf(execution.getId()); + String docDate = dateFormatter.format(now); + String docTime = timeFormatter.format(now); + String docName = "Отчет об обязательствах/требованиях Участника клиринга"; + String docType = "KS_FIRMID_LIABILITIES"; + String firmId = String.valueOf(execution.getCompanyId()); + String firName = company.getFullName(); + String sessionId = String.valueOf(execution.getSessionId()); + String clearingDate = dateFormatter.format(execution.getClearingDate()); + String trdAccId = registry.getTradingClearingRegistry(); + String account = String.valueOf(tradingClearingRegistry.getMoneyAccountId()); + String depoAccount = String.valueOf(tradingClearingRegistry.getDepoAaccountId()); + String currency = execution.getSettlementCurrency(); + String trId = String.valueOf(execution.getExchangeExecutionId()); + String securityId = String.valueOf(execution.getSecurityId()); + + String trBuySell = ""; + if (Side.BUY.equalsByKey(execution.getSide())) + trBuySell = "B"; + else if (Side.SELL.equalsByKey(execution.getSide())) + trBuySell = "S"; + String trDate = dateFormatter.format(execution.getTradingDate()); + + String trExecDate = ""; + String execStatus = ""; + String repaymDate = ""; + String trPrice = ""; + String nominal = ""; + String trQuantity = ""; + String trValue = ""; + String trAccruedInt = ""; + String accruedInt = ""; + String cashLiability = ""; + String depoLiability = ""; + if (execution instanceof ExecutionDeposit executionDeposit) { + trExecDate = dateFormatter.format(executionDeposit.getSecondLegSettlementDate()); + if (Market.mkrs.equalsByKey(execution.getMarket())) { + execStatus = "Y"; + repaymDate = dateFormatter.format(executionDeposit.getSecondLegSettlementDate()); + trPrice = String.valueOf(executionDeposit.getPrice()); + trValue = String.valueOf(executionDeposit.getFirstLegAmount()); + cashLiability = String.valueOf(executionDeposit.getFirstLegAmount()); + } + } else if (execution instanceof ExecutionFond executionFond) { + trExecDate = dateFormatter.format(executionFond.getSettlementDate()); + if (Market.fond.equalsByKey(execution.getMarket())) { + trPrice = String.valueOf( + executionFond.getSettlementAmount().divide(executionFond.getQuantity(), RoundingMode.HALF_UP) + ); + trQuantity = String.valueOf(executionFond.getQuantity()); + nominal = String.valueOf(fixedIncomeSecurity.getNominalValue()); + trValue = String.valueOf(executionFond.getSettlementAmount()); + trAccruedInt = String.valueOf(fixedIncomeSecurity.getCoupon()); + accruedInt = String.valueOf( + fixedIncomeSecurity.getCoupon().divide(executionFond.getQuantity(), RoundingMode.HALF_UP) + ); + cashLiability = String.valueOf(executionFond.getSettlementAmount()); + depoLiability = String.valueOf(executionFond.getQuantity()); + } + } + + String lotValue = String.valueOf(listing.getLotSize()); + String trLot = String.valueOf(execution.getLots()); + String trClrComm = ""; + String trExhComm = ""; + + Registry tm_tRegistry = null; + Registry om_tRegistry = null; + Registry ts_tRegistry = null; + Registry os_tRegistry = null; + for (Registry currRegistry : registriesForSessionId) { + String registryCode = currRegistry.getRegistryCode(); + if (registryCode.endsWith("T")) { + if (registryCode.startsWith("TM")) { + if (tm_tRegistry != null && tm_tRegistry.getUpdatedAt().isAfter(currRegistry.getUpdatedAt())) continue; + tm_tRegistry = currRegistry; + } + if (registryCode.startsWith("OM")) { + if (om_tRegistry != null && om_tRegistry.getUpdatedAt().isAfter(currRegistry.getUpdatedAt())) continue; + om_tRegistry = currRegistry; + } + if (registryCode.startsWith("TS")) { + if (ts_tRegistry != null && ts_tRegistry.getUpdatedAt().isAfter(currRegistry.getUpdatedAt())) continue; + ts_tRegistry = currRegistry; + } + if (registryCode.startsWith("OS")) { + if (os_tRegistry != null && os_tRegistry.getUpdatedAt().isAfter(currRegistry.getUpdatedAt())) continue; + os_tRegistry = currRegistry; + } + } + } + String cashNetto = ""; + if (tm_tRegistry != null && om_tRegistry != null) { + cashNetto = String.valueOf(tm_tRegistry.getBalance().subtract(om_tRegistry.getBalance())); + } + + String depoNetto = ""; + if (ts_tRegistry != null && os_tRegistry != null) { + depoNetto = String.valueOf(ts_tRegistry.getBalance().subtract(os_tRegistry.getBalance())); + } + + + int valueIdx = 0; + String[] line = new String[getHeaders().length]; + line[valueIdx++] = id; + line[valueIdx++] = docDate; + line[valueIdx++] = docTime; + line[valueIdx++] = docName; + line[valueIdx++] = docType; + line[valueIdx++] = clearingHouse; + line[valueIdx++] = firmId; + line[valueIdx++] = firName; + line[valueIdx++] = sessionId; + line[valueIdx++] = clearingDate; + line[valueIdx++] = trdAccId; + line[valueIdx++] = account; + line[valueIdx++] = depoAccount; + line[valueIdx++] = currency; + line[valueIdx++] = trId; + line[valueIdx++] = securityId; + line[valueIdx++] = trBuySell; + line[valueIdx++] = trDate; + line[valueIdx++] = trExecDate; + line[valueIdx++] = execStatus; + line[valueIdx++] = repaymDate; + line[valueIdx++] = trPrice; + line[valueIdx++] = nominal; + line[valueIdx++] = lotValue; + line[valueIdx++] = trLot; + line[valueIdx++] = trQuantity; + line[valueIdx++] = trValue; + line[valueIdx++] = trAccruedInt; + line[valueIdx++] = accruedInt; + line[valueIdx++] = trClrComm; + line[valueIdx++] = trExhComm; + line[valueIdx++] = cashLiability; + line[valueIdx++] = depoLiability; + line[valueIdx++] = cashNetto; + line[valueIdx] = depoNetto; + lines.add(line); + } + } + +} diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalMoneyChangeReport.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalMoneyChangeReport.java index 2f253b5b2..cc99998bf 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalMoneyChangeReport.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/OperationalMoneyChangeReport.java @@ -1,49 +1,148 @@ package ru.spcex.clearing.reports.reports.bp; -import ru.spcex.clearing.reports.reports.ReportId; -import ru.spcex.clearing.reports.reports.ReportWithPeriod; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.misc.Listing; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.classes.statics.data.statement.Statement; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.reports.reports.CSVReportBuilder; +import ru.spcex.clearing.reports.reports.PeriodParams; +import ru.spcex.platform.enumeration.InOutDirection; +import ru.spcex.platform.enumeration.ReportType; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; -import java.time.LocalDate; +import java.time.Instant; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; -public class OperationalMoneyChangeReport extends ReportWithPeriod { - +public class OperationalMoneyChangeReport extends CSVReportBuilder { + private final Imdg registryImdg; + private final Imdg companyImdg; + private final Imdg listingImdg; + private final Imdg statementImdg; + private final Imdg paymentInstructionImdg; private final String[] headers = { "id", "doc_date", "doc_time", "doc_name", "doc_type", "clearingHouse", "firmId", "firName", "trdAccId", "account", "currency", "registry_code", "registry_name", "open_balance", "change_balance", "add_withdraw", "close_balance", "remarks", "add_sum", "add_time", "withdraw_sum", "withdraw_time" }; + private List lines = null; - - public OperationalMoneyChangeReport(LocalDate startDate, LocalDate endDate) { - super(ReportId.OPERATIONAL_MONEY_CHANGE, - "0.0.1", - "BP3", - "Операционный отчет. Отчет о денежных средствах", - startDate, - endDate); + public OperationalMoneyChangeReport(ImdgProvider imdgProvider) { + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class); + this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); + this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); } @Override - public String getReportName(LocalDateTime reportDateTime) { - return "operational_money_change.%s-%s.%s".formatted( - DATE_FORMATTER.format(startDate), - DATE_FORMATTER.format(endDate), - DATE_TIME_FORMATTER.format(reportDateTime) - ); - } - public String[] getHeaders() { return headers; } - public record InfoOperationalMoneyChangeReport(String id, String docDate, String docTime, String docName, - String docType, String clearingHouse, String firmId, String firName, - String trdAccId, String account, String currency, String registryCode, - String registryName, String openBalance, String changeBalance, - String addWithdraw, String closeBalance, String remarks, String addSum, - String addTime, String withdrawSum, String withdrawTime) { + @Override + protected List getLines() { + return lines; + } + @Override + protected String getReportFilename(PeriodParams params) { + return "operational_money_change.%s-%s.%s".formatted( + dateFormatter.format(params.getStartDate()), + dateFormatter.format(params.getEndDate()), + dateTimeFormatter.format(LocalDateTime.now()) + ); + } + + @Override + protected ReportType getReportType() { + return ReportType.OPERATIONAL_MONEY_CHANGE; + } + + @Override + protected void collect(PeriodParams params) { + ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); + Collection registries = registryImdg.getCollectionObjectsByPredicate( + pb.and( + pb.greatEqual("clearingDate", params.getStartDate()), + pb.lessEqual("clearingDate", params.getEndDate()) + ) + ); + + Company clearingHouseCompany = companyImdg.getSingleObjectByID(1L); + String clearingHouse = clearingHouseCompany.getFullName(); + + Instant now = Instant.now(); + lines = new ArrayList<>(registries.size()); + for (Registry registry : registries) { + Company company = companyImdg.getSingleObjectByID(registry.getCompanyId()); + if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) continue; + + Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", registry.getSecurityId())); + Statement statement = statementImdg.getSingleObjectByFieldValues(Map.of("addresseeId", registry.getCompanyId())); + PaymentInstruction paymentInstruction = paymentInstructionImdg.getSingleObjectByFieldValues( + Map.of( + "id", registry.getPaymentId(), + "creditLegDirection", InOutDirection.out.getKey() + ) + ); + + String id = String.valueOf(registry.getId()); + String docDate = dateFormatter.format(now); + String docTime = timeFormatter.format(now); + String docName = "Отчет об изменении суммы денежных средств и (или) количества иного имущества Участника клиринга"; + String docType = "KS_FIRMID_ASSETS"; + String firmId = String.valueOf(registry.getCompanyId()); + String firName = company.getFullName(); + String trdAccId = registry.getTradingClearingRegistry(); + String account = String.valueOf(registry.getAccountId()); // todo * + String currency = listing.getTradingCurrency(); // todo * + String registryCode = String.valueOf(registry.getId()); + String registryName = registry.getFullName(); // todo * + String openBalance = String.valueOf(registry.getOpenBalance()); + String changeBalance = String.valueOf(registry.getCloseBalance().subtract(registry.getOpenBalance())); + String addWithdraw = String.valueOf(registry.getCredit().subtract(registry.getDebit())); + String closeBalance = String.valueOf(registry.getCloseBalance()); + String remarks = ""; + String addSum = String.valueOf(registry.getCredit()); + String addTime = dateTimeFormatter.format(statement.getCreated()); + String withdrawSum = String.valueOf(registry.getDebit()); + String withdrawTime = dateTimeFormatter.format(paymentInstruction.getPaymentDate()); + + int valueIdx = 0; + String[] line = new String[getHeaders().length]; + line[valueIdx++] = id; + line[valueIdx++] = docDate; + line[valueIdx++] = docTime; + line[valueIdx++] = docName; + line[valueIdx++] = docTime; + line[valueIdx++] = clearingHouse; + line[valueIdx++] = firmId; + line[valueIdx++] = firName; + line[valueIdx++] = trdAccId; + line[valueIdx++] = account; + line[valueIdx++] = currency; + line[valueIdx++] = registryCode; + line[valueIdx++] = registryName; + line[valueIdx++] = openBalance; + line[valueIdx++] = changeBalance; + line[valueIdx++] = addWithdraw; + line[valueIdx++] = closeBalance; + line[valueIdx++] = remarks; + line[valueIdx++] = addSum; + line[valueIdx++] = addTime; + line[valueIdx++] = withdrawSum; + line[valueIdx++] = withdrawTime; + lines.add(line); + } } } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/UnfulfilledDealReport.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/UnfulfilledDealReport.java index 8de76a447..4f5d8d585 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/UnfulfilledDealReport.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bp/UnfulfilledDealReport.java @@ -1,39 +1,95 @@ package ru.spcex.clearing.reports.reports.bp; -import ru.spcex.clearing.reports.reports.ReportId; -import ru.spcex.clearing.reports.reports.ReportWithPeriod; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.execution.ExecutionFond; +import ru.clearing.classes.statics.data.misc.STrades; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.reports.reports.CSVReportBuilder; +import ru.spcex.clearing.reports.reports.SessionIdParam; +import ru.spcex.platform.enumeration.Allowed; +import ru.spcex.platform.enumeration.ReportType; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; -import java.time.LocalDate; -import java.time.LocalDateTime; - -public class UnfulfilledDealReport extends ReportWithPeriod { +import java.time.Instant; +import java.util.Collection; +import java.util.List; +import java.util.Map; +public class UnfulfilledDealReport extends CSVReportBuilder { + private final Imdg executionFondImdg; + private final Imdg companyImdg; + private final Imdg sTradesImdg; private final String[] headers = { "id", "securityId", "tradeNo", "tradeDate", "settleCode" }; + private final List lines = null; - public UnfulfilledDealReport(LocalDate startDate, LocalDate endDate) { - super(ReportId.UNFULFILLED_DEAL_REPORT, - "0.0.1", - "BP", - "Реестр сделок, принятых на клиринг", - startDate, - endDate); + public UnfulfilledDealReport(ImdgProvider imdgProvider) { + executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + sTradesImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_STrades, STrades.class); } @Override - public String getReportName(LocalDateTime reportDateTime) { - return "unfulfilled_deal_report.%s-%s.%s".formatted( - DATE_FORMATTER.format(startDate), - DATE_FORMATTER.format(endDate), - DATE_TIME_FORMATTER.format(reportDateTime) - ); - } - public String[] getHeaders() { return headers; } - public record InfoUnfulfilledDealReport(String id, String securityId, String tradeNo, String tradeDate, String settleCode) { + @Override + protected List getLines() { + return lines; } + + @Override + protected String getReportFilename(SessionIdParam params) { + return "unfulfilled_deal_report.%s".formatted( + dateTimeFormatter.format(Instant.now()) + ); + } + + @Override + protected ReportType getReportType() { + return ReportType.UNFULFILLED_DEAL_REPORT; + } + + @Override + protected void collect(SessionIdParam params) { + ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder(); + ImdgPredicate predicate = pb.and( + pb.equals("sessionId", params.getSessionId()), + pb.equals("coverageStatus", Allowed.DENIED.getKey()) + ); + Collection executionFonds = executionFondImdg.getCollectionObjectsByPredicate(predicate); + + for (ExecutionFond executionFond : executionFonds) { + Company company = companyImdg.getSingleObjectByID(executionFond.getCompanyId()); + if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) continue; + STrades sTrade = sTradesImdg.getSingleObjectByFieldValues( + Map.of( + "settleCode", executionFond.getSettlementCode(), + "operation", executionFond.getSide() + ) + ); + + String id = String.valueOf(executionFond.getId()); + String securityId = String.valueOf(executionFond.getSecurityId()); + String tradeNo = String.valueOf(executionFond.getExchangeExecutionId()); + String tradeDate = dateFormatter.format(executionFond.getTradingDate()); + String settleCode = sTrade != null ? sTrade.getClassCode() : null; + + int valueIdx = 0; + String[] line = new String[getHeaders().length]; + line[valueIdx++] = id; + line[valueIdx++] = securityId; + line[valueIdx++] = tradeNo; + line[valueIdx++] = tradeDate; + line[valueIdx++] = settleCode; + lines.add(line); + } + } + } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Market.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Market.java index 8d20c67ef..ff11d32b0 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Market.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Market.java @@ -3,7 +3,9 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum Market implements IEnumKey { - mkrs("MKRS"); + mkrs("MKRS"), + fond("FOND"), + ; private final String key;