From 24c203a83f0021b1202119b58d78112e12143cb3 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Tue, 30 Jan 2024 18:42:50 +0300 Subject: [PATCH] =?UTF-8?q?registry-service=20http://jira.mfd.msk:8088/bro?= =?UTF-8?q?wse/CLS-638=20LiabilitiesRegisterService=20=D1=82=D0=B5=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D1=8C=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=B2=20=D1=84=D0=B0=D0=B9=D0=BB,=20backend-api=20meta=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20CLS-635=20=D1=83=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=BB=D0=B8=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B5=D0=B5?= =?UTF-8?q?=20-=20=D0=B2=D0=B5=D1=80=D0=BD=D1=83=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/meta/meta.json | 13 +- .../src/main/resources/meta/meta.xml | 4 +- .../backend-api/src/test/resources/meta.json | 13 +- .../bean/LiabilitiesRegistryReport.java | 121 ++++++++++++ .../LiabilitiesRegistryReportBuilder.java | 74 +++++++ .../reports/builders/XLSXReportBuilder.java | 2 + .../service/LiabilitiesRegisterService.java | 182 ++++++++++-------- .../ru/spcex/platform/enumeration/Task.java | 6 +- 8 files changed, 333 insertions(+), 82 deletions(-) create mode 100644 clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/bean/LiabilitiesRegistryReport.java create mode 100644 clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/LiabilitiesRegistryReportBuilder.java diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.json b/clearing-parent/backend-api/src/main/resources/meta/meta.json index c8d296dbb..f89a1dbc8 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.json +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.json @@ -1,6 +1,6 @@ { - "version": "3.9.0.72", + "version": "3.9.0.73", "enums": { @@ -5492,6 +5492,17 @@ "fields": [] } , + {"method":"post", + + "destination": "LBSR", + + "group": "Формирование реестров", + + "name": "Формирование реестра учета обязательств", + + "fields": [] + } + , {"method":"post", "destination": "ECNR", diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.xml b/clearing-parent/backend-api/src/main/resources/meta/meta.xml index 5fc5eea94..c5fa8b302 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.xml @@ -1,6 +1,6 @@ - + @@ -1270,6 +1270,8 @@ + + diff --git a/clearing-parent/backend-api/src/test/resources/meta.json b/clearing-parent/backend-api/src/test/resources/meta.json index c8d296dbb..f89a1dbc8 100644 --- a/clearing-parent/backend-api/src/test/resources/meta.json +++ b/clearing-parent/backend-api/src/test/resources/meta.json @@ -1,6 +1,6 @@ { - "version": "3.9.0.72", + "version": "3.9.0.73", "enums": { @@ -5492,6 +5492,17 @@ "fields": [] } , + {"method":"post", + + "destination": "LBSR", + + "group": "Формирование реестров", + + "name": "Формирование реестра учета обязательств", + + "fields": [] + } + , {"method":"post", "destination": "ECNR", diff --git a/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/bean/LiabilitiesRegistryReport.java b/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/bean/LiabilitiesRegistryReport.java new file mode 100644 index 000000000..5b89f17a4 --- /dev/null +++ b/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/bean/LiabilitiesRegistryReport.java @@ -0,0 +1,121 @@ +package ru.spcex.clearing.registry.reports.bean; + +import com.opencsv.bean.CsvBindByName; +import com.opencsv.bean.CsvBindByPosition; +import com.opencsv.bean.CsvDate; +import com.opencsv.bean.CsvNumber; + +import java.math.BigDecimal; +import java.time.LocalDate; + +public class LiabilitiesRegistryReport implements FileReport { + @CsvBindByName(column = "клиринговый код") + @CsvBindByPosition(position = 0) + private String clearing_code; + + @CsvBindByName(column = "счет") + @CsvBindByPosition(position = 1) + private String account; + + @CsvBindByName(column = "код регистра") + @CsvBindByPosition(position = 2) + private String registry_code; + + @CsvBindByName(column = "статус") + @CsvBindByPosition(position = 3) + private String registry_status; + + @CsvBindByName(column = "инструмент валюта") + @CsvBindByPosition(position = 4) + private String security_symbol; + + @CsvBindByName(column = "баланс") + @CsvBindByPosition(position = 5) + @CsvNumber(value = "#0.00", writeFormat = "#0.00") + private BigDecimal balance; + + @CsvBindByName(column = "дата расчета") + @CsvBindByPosition(position = 6) + @CsvDate(value = "dd.MM.yyyy") + private LocalDate settlement_date; + + @CsvBindByName(column = "продукт") + @CsvBindByPosition(position = 7) + private String contract; + + @CsvBindByName(column = "тип сессии") + @CsvBindByPosition(position = 8) + private String session_type; + + public String getClearing_code() { + return clearing_code; + } + + public void setClearing_code(String clearing_code) { + this.clearing_code = clearing_code; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getRegistry_code() { + return registry_code; + } + + public void setRegistry_code(String registry_code) { + this.registry_code = registry_code; + } + + public String getRegistry_status() { + return registry_status; + } + + public void setRegistry_status(String registry_status) { + this.registry_status = registry_status; + } + + public String getSecurity_symbol() { + return security_symbol; + } + + public void setSecurity_symbol(String security_symbol) { + this.security_symbol = security_symbol; + } + + public BigDecimal getBalance() { + return balance; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } + + public LocalDate getSettlement_date() { + return settlement_date; + } + + public void setSettlement_date(LocalDate settlement_date) { + this.settlement_date = settlement_date; + } + + public String getContract() { + return contract; + } + + public void setContract(String contract) { + this.contract = contract; + } + + public String getSession_type() { + return session_type; + } + + public void setSession_type(String session_type) { + this.session_type = session_type; + } +} diff --git a/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/LiabilitiesRegistryReportBuilder.java b/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/LiabilitiesRegistryReportBuilder.java new file mode 100644 index 000000000..2fed707e9 --- /dev/null +++ b/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/LiabilitiesRegistryReportBuilder.java @@ -0,0 +1,74 @@ +package ru.spcex.clearing.registry.reports.builders; + +import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.platform.dictionary.RegistryStatusDictionary; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.registry.reports.bean.LiabilitiesRegistryReport; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.stream.Collectors; + +public class LiabilitiesRegistryReportBuilder extends XLSXReportBuilder { + + private final Imdg registryStatusDictionaryImdg; + + public LiabilitiesRegistryReportBuilder(ImdgProvider imdgProvider) { + registryStatusDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RegistryStatusDictionary, RegistryStatusDictionary.class); + } + + @Override + protected String reportName() { + return "registry"; + } + + @Override + protected Class getReportClass() { + return LiabilitiesRegistryReport.class; + } + + @Override + protected LiabilitiesRegistryReport toRow(Registry input) { + LiabilitiesRegistryReport entity = new LiabilitiesRegistryReport(); + + entity.setClearing_code(input.getClearingCode()); + entity.setAccount(input.getAccount()); + entity.setRegistry_code(input.getRegistryCode()); + entity.setRegistry_status(describeRegistryStatus(input.getRegistryStatus())); // CLRD + entity.setSecurity_symbol(input.getSecuritySymbol()); + entity.setBalance(input.getBalance()); + entity.setSettlement_date(input.getSettlementDate()); + entity.setContract(input.getContract()); + entity.setSession_type(input.getSessionType()); + + return entity; + } + + /** + * @param registryStatus 'CLRD', ... + * @return из справочника + */ + private String describeRegistryStatus(String registryStatus) { + if (registryStatus == null) + return registryStatus; + RegistryStatusDictionary dictionary = registryStatusDictionaryImdg.getFirstObjectByFieldValues(Map.of( + "code", registryStatus + )); + if (dictionary == null) { + log.warn("Dictionary not found for status=\"{}\"", dictionary); + return registryStatus; + } + return dictionary.getName(); + } + + @Override + protected Collection sortInput(Collection input) { + return input.stream() + .sorted(Comparator.comparing(Registry::getCreated)) + .collect(Collectors.toList()); + } + +} diff --git a/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/XLSXReportBuilder.java b/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/XLSXReportBuilder.java index 4da5360e4..88cd78c03 100644 --- a/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/XLSXReportBuilder.java +++ b/clearing-parent/registry-service/src/main/java/ru/spcex/clearing/registry/reports/builders/XLSXReportBuilder.java @@ -70,6 +70,7 @@ public abstract class XLSXReportBuilder constructor = Objects.requireNonNull(getReportClass()).getDeclaredConstructor(); @@ -166,6 +167,7 @@ public abstract class XLSXReportBuilder securitySelector; private final Function, IValidator> fieldValuesValidator; private final PreClearMap preClearMap; + private final LiabilitiesRegistryReportBuilder reportBuilder; + private final File outFolder; + private final RegistryServiceSettings settings; + private final SFTPReportsConfig.ReportsGateway reportsSftpGateway; + private final boolean deleteAfterSend; @Autowired public LiabilitiesRegisterService(Consumer kafkaQueue, Producer kafkaProducer, ImdgProvider imdgProvider, - Function, IValidator> fieldValuesValidator) { + Function, IValidator> fieldValuesValidator, + @Qualifier("reportOutDir") File outFolder, + RegistryServiceSettings settings, + SFTPReportsConfig.ReportsGateway reportsSftpGateway) { super(kafkaQueue, kafkaProducer); this.liabilitiesRegisterMap = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesRegister, LiabilitiesRegister.class); this.registryMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); @@ -62,6 +80,11 @@ public class LiabilitiesRegisterService extends QueueConsumer implements Initial this.securitySelector = new SecuritySelector<>(imdgProvider, Security.class); this.fieldValuesValidator = fieldValuesValidator; preClearMap = PreClearMap.instanceForInstantField(liabilitiesRegisterMap, "created"); + reportBuilder = new LiabilitiesRegistryReportBuilder(imdgProvider); + this.outFolder = outFolder; + this.settings = settings; + this.reportsSftpGateway = reportsSftpGateway; + this.deleteAfterSend = settings.getReportsStore().isDeleteAfterSend(); } @Override @@ -77,90 +100,97 @@ public class LiabilitiesRegisterService extends QueueConsumer implements Initial public void liabilitiesRegisterNew(BaseRequest userRequest) { - log.debug("LiabilitiesRegisterNewRequest received from {}", Consts.REGISTRY_LIABILITIES_REGISTER_NEW); - String sqlConditionForRegistry = getSqlForRegistries(); - Collection registries = registryMap.getCollectionObjectsBySQL(sqlConditionForRegistry); - log.debug("Found {} Registry by query {}", registries.size(), sqlConditionForRegistry); - preClearMap.preClearMap(); - registries.forEach((registry -> { - if (isDuplicateInMap(registry).isEmpty()) { - insertLiabilitiesRegister(registry); - } + log.debug("LiabilitiesRegisterNewRequest received from {}", createRegistry_LBSR.topic()); + boolean csvMode = settings.isCsvMode(); + + ImdgPredicate conditionForRegistry = getPredicateForRegistries(); + Collection registries = registryMap.getCollectionObjectsByPredicate(conditionForRegistry); + log.debug("Found {} Registry by query {}", registries.size(), conditionForRegistry); + if (!csvMode) + preClearMap.preClearMap(); +// registries.forEach((registry -> { +// if (isDuplicateInMap(registry).isEmpty()) { +// if (!csvMode || LocalDate.now().equals(registry.getTradingDate())) +// insertLiabilitiesRegister(registry); +// } +// } +// )); + if (csvMode) { + File reportFile = reportBuilder.buildReport(registries, outFolder); + ReportUtils.sendFilesToSftp(List.of(reportFile), reportsSftpGateway, deleteAfterSend); } - )); log.debug("successfully processed"); } - private void insertLiabilitiesRegister(Registry registry) { - log.trace("Started generating LiabilitiesRegister entity..."); - LiabilitiesRegister liabilitiesRegister = new LiabilitiesRegister(); - Session session = sessionMap.getSingleObjectByID(registry.getSessionId()); - CompanySymbols companySymbols = companySymbolsMap.getFirstObjectByFieldValues( - Map.of("companyId", registry.getCompanyId(), - "companySymbol", CompanySymbol.INN.getKey() - ) - ); - Security security = securitySelector.selectSecurityById(registry.getSecurityId()); - if (session == null) { - log.warn("Session is empty!"); - } else { - liabilitiesRegister.setValidFromDate(session.getClearingDate()); - liabilitiesRegister.setValidToDate(TimeUtil.toLocalDate(session.getUpdated())); - } - if (companySymbols == null) { - log.warn("CompanySymbols not found, for companyId={}", registry.getCompanyId()); - } else { - liabilitiesRegister.setInn(companySymbols.getCompanySymbolValue()); - } - if (security == null) { - log.warn("Security id={} not found for registry id={}", registry.getSecurityId(), registry.getId()); - } else { - if (InstrumentType.RATE.equalsByKey(security.getInstrumentType())) { - liabilitiesRegister.setCurrency(((MoneyMarketSecurity) security).getNominalCurrency()); - } else if (InstrumentType.BOND.equalsByKey(security.getInstrumentType())) { - liabilitiesRegister.setCurrency(((FixedIncomeSecurity) security).getNominalCurrency()); - } else if (InstrumentType.EQTY.equalsByKey(security.getInstrumentType())) { - // не заполняется Currency - } else { // never - log.warn("Unexpected security[{}] type {}", security.getId(), security.getInstrumentType()); - } - } - liabilitiesRegister.setSessionId(registry.getSessionId()); - liabilitiesRegister.setValidFromDate(session.getClearingDate()); - LocalDate validToDate = TimeUtil.toLocalDate(session.getUpdated()); - liabilitiesRegister.setValidToDate(validToDate); - liabilitiesRegister.setCompanyId(registry.getCompanyId()); - liabilitiesRegister.setCompanyFullName(registry.getFullName()); - liabilitiesRegister.setRegistryCode(registry.getRegistryCode()); - liabilitiesRegister.setAccount(registry.getAccount()); - liabilitiesRegister.setRegistryStatus(registry.getRegistryStatus()); - liabilitiesRegister.setSumLiabilities(registry.getBalance()); - liabilitiesRegister.setSettlementDate(registry.getSettlementDate()); - liabilitiesRegister.setCreated(Instant.now()); - liabilitiesRegister.setUpdated(liabilitiesRegister.getCreated()); - liabilitiesRegisterMap.insert(liabilitiesRegister); - log.debug("inserted successfully LiabilitiesRegister entity with id: {}", liabilitiesRegister.getId()); - } +// private void insertLiabilitiesRegister(Registry registry) { +// log.trace("Started generating LiabilitiesRegister entity..."); +// LiabilitiesRegister liabilitiesRegister = new LiabilitiesRegister(); +// Session session = sessionMap.getSingleObjectByID(registry.getSessionId()); +// CompanySymbols companySymbols = companySymbolsMap.getFirstObjectByFieldValues( +// Map.of("companyId", registry.getCompanyId(), +// "companySymbol", CompanySymbol.INN.getKey() +// ) +// ); +// Security security = securitySelector.selectSecurityById(registry.getSecurityId()); +// if (session == null) { +// log.warn("Session is empty!"); +// } else { +// liabilitiesRegister.setValidFromDate(session.getClearingDate()); +// liabilitiesRegister.setValidToDate(TimeUtil.toLocalDate(session.getUpdated())); +// } +// if (companySymbols == null) { +// log.warn("CompanySymbols not found, for companyId={}", registry.getCompanyId()); +// } else { +// liabilitiesRegister.setInn(companySymbols.getCompanySymbolValue()); +// } +// if (security == null) { +// log.warn("Security id={} not found for registry id={}", registry.getSecurityId(), registry.getId()); +// } else { +// if (InstrumentType.RATE.equalsByKey(security.getInstrumentType())) { +// liabilitiesRegister.setCurrency(((MoneyMarketSecurity) security).getNominalCurrency()); +// } else if (InstrumentType.BOND.equalsByKey(security.getInstrumentType())) { +// liabilitiesRegister.setCurrency(((FixedIncomeSecurity) security).getNominalCurrency()); +// } else if (InstrumentType.EQTY.equalsByKey(security.getInstrumentType())) { +// // не заполняется Currency +// } else { // never +// log.warn("Unexpected security[{}] type {}", security.getId(), security.getInstrumentType()); +// } +// } +// liabilitiesRegister.setSessionId(registry.getSessionId()); +// liabilitiesRegister.setValidFromDate(session.getClearingDate()); +// LocalDate validToDate = TimeUtil.toLocalDate(session.getUpdated()); +// liabilitiesRegister.setValidToDate(validToDate); +// liabilitiesRegister.setCompanyId(registry.getCompanyId()); +// liabilitiesRegister.setCompanyFullName(registry.getFullName()); +// liabilitiesRegister.setRegistryCode(registry.getRegistryCode()); +// liabilitiesRegister.setAccount(registry.getAccount()); +// liabilitiesRegister.setRegistryStatus(registry.getRegistryStatus()); +// liabilitiesRegister.setSumLiabilities(registry.getBalance()); +// liabilitiesRegister.setSettlementDate(registry.getSettlementDate()); +// liabilitiesRegister.setCreated(Instant.now()); +// liabilitiesRegister.setUpdated(liabilitiesRegister.getCreated()); +// liabilitiesRegisterMap.insert(liabilitiesRegister); +// log.debug("inserted successfully LiabilitiesRegister entity with id: {}", liabilitiesRegister.getId()); +// } - protected String getSqlForRegistries() { - return String.format("registryDesignation = '%s' and " + - "registryInstrumentType in ('%s','%s') and " + - "registryUnit = '%s'", - RegistryDesignation.L.getKey(), - RegistryInstrumentType.S.getKey(), - RegistryInstrumentType.M.getKey(), - RegistryUnit.T.getKey()); + protected ImdgPredicate getPredicateForRegistries() { + ImdgPredicateBuilder pb = registryMap.predicateBuilder(); + return pb.and( + RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.OM_T, RegistryTradingParams.OS_T).buildPredicate(pb), + pb.equals("registryStatus", RegistryStatus.CLRD.getKey()), + pb.equals("settlementDate", LocalDate.now()) + ); +// return String.format("registryDesignation = '%s' and " + +// "registryInstrumentType in ('%s','%s') and " + +// "registryUnit = '%s'", +// RegistryDesignation.L.getKey(), +// RegistryInstrumentType.S.getKey(), +// RegistryInstrumentType.M.getKey(), +// RegistryUnit.T.getKey()); } @Override public Optional isDuplicateInMap(Registry entity) { return Optional.empty(); -// Map> fieldValues = Map.of("companyId", entity.getCompanyId(), "sessionId", entity.getSessionId()); -// Optional message = fieldValuesValidator.apply(fieldValues).tillFirstError(); -// if (message.isPresent()) { -// log.warn("Illegal value in map for request to imdg: {}", message.get()); -// throw new IllegalArgumentException(MessageFormat.format("Illegal value in request to imdg: {0}", message.get())); -// } -// return Optional.ofNullable(liabilitiesRegisterMap.getFirstObjectByFieldValues(fieldValues)); } } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java index f507fc3ef..896c5c7f2 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java @@ -40,9 +40,9 @@ public enum Task implements IEnumKey { createRegistry_GCMR("GCMR"), // Формирование реестра участников клиринга createRegistry_GSRR("GSRR"), // Формирование реестра отправленных отчетов createRegistry_GACA("GACA"), // Создание файла остатков CSV по клиринговым счетам - createRegistry_ADLR("ADLR"), // формирование admittedLiabilitiesRegister - createRegistry_CDLR("CDLR"), // формирование coveredLiabilitiesRegister - createRegistry_EXLR("EXLR"), // формирование excludeLiabilitiesRegister + @Deprecated createRegistry_ADLR("ADLR"), // формирование admittedLiabilitiesRegister + @Deprecated createRegistry_CDLR("CDLR"), // формирование coveredLiabilitiesRegister + @Deprecated createRegistry_EXLR("EXLR"), // формирование excludeLiabilitiesRegister createRegistry_LBSR("LBSR"), // формирование liabilitiesRegister createRegistry_ECNR("ECNR"), // формирование executionRegister createRegistry_STRS("STRS"), // Начало торговой сессии