From 46afedede1c325b490b098cf816a309c5a0823b3 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Mon, 30 Mar 2026 12:01:31 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-911 --- .../src/main/resources/meta/meta.xml | 2 + .../src/main/resources/db/DICTIONARIES.sql | 9 +- .../main/resources/db/SECTION_DICTIONARY.sql | 16 +++ .../resources/db/SECTION_DICTIONARY_LCC.sql | 16 +++ .../gatewayapi/enums/OutboundRequestType.java | 1 + .../gatewayapi/service/GatewayService.java | 25 ++++ .../service/builders/ContentBuilder.java | 33 ++++++ .../service/facade/SCrossRateFacade.java | 43 +++++++ .../ru/spcex/platform/enumeration/Task.java | 1 + .../cud/securitites/SCrossRateRequest.java | 109 ++++++++++++++++++ 10 files changed, 247 insertions(+), 8 deletions(-) create mode 100644 clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY.sql create mode 100644 clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY_LCC.sql create mode 100644 clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/builders/ContentBuilder.java create mode 100644 clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/facade/SCrossRateFacade.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateRequest.java 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 fe8618a4c..85e10f5a3 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.xml @@ -1439,6 +1439,8 @@ + + diff --git a/clearing-parent/db-scripts/src/main/resources/db/DICTIONARIES.sql b/clearing-parent/db-scripts/src/main/resources/db/DICTIONARIES.sql index c884c79ce..54bd1d8c1 100644 --- a/clearing-parent/db-scripts/src/main/resources/db/DICTIONARIES.sql +++ b/clearing-parent/db-scripts/src/main/resources/db/DICTIONARIES.sql @@ -265,14 +265,6 @@ INSERT INTO COUNTRY_CODE_DICTIONARY(ID, CODE, NAME) values (897, 'DNR', 'ДНР' INSERT INTO COUNTRY_CODE_DICTIONARY(ID, CODE, NAME) values (898, 'LNR', 'ЛНР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; INSERT INTO COUNTRY_CODE_DICTIONARY(ID, CODE, NAME) values (998, '998', 'МЕЖДУНАРОДНАЯ ОРГАНИЗАЦИЯ') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; -INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (1, 'MKR', 'Секция Денежного рынка МКР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; - -INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (2, 'FOND', 'Фондовая секция') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; - -INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (3, 'CURR', 'Валютная секция') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; - -INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (4, 'MULT', 'Единая') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; - INSERT INTO USER_ROLE_DICTIONARY(ID, CODE, NAME) values (1, 'ADMN', 'Администратор Клиринга МКР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; INSERT INTO USER_ROLE_DICTIONARY(ID, CODE, NAME) values (2, 'SPVS', 'Супервайзер Клиринга МКР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; @@ -750,6 +742,7 @@ INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (33, 'GREC', 'Формиро INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (34, 'CX84', 'Формирование отчета CCX84') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (35, 'GVTF', 'Проведение сверки по регистрам AMAT и AMAF') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; +INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (36, 'LORT', 'Загрузка курсов валют') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; INSERT INTO TASK_STATUS_DICTIONARY(ID, CODE, NAME) values (1, 'ACTV', 'Активна') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; diff --git a/clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY.sql b/clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY.sql new file mode 100644 index 000000000..e98da5c29 --- /dev/null +++ b/clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY.sql @@ -0,0 +1,16 @@ +-- DB version: 3.22 +-- SECTION_DICTIONARY LCC version: 3.22.0.0 + + +/* Dictionaries */ + +/* Business objects */ + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (1, 'MKR', 'Секция Валютного рынка') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (2, 'FOND', 'Фондовая секция') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (3, 'CURR', 'Валютная секция') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (4, 'MULT', 'Единая') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + diff --git a/clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY_LCC.sql b/clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY_LCC.sql new file mode 100644 index 000000000..41143b334 --- /dev/null +++ b/clearing-parent/db-scripts/src/main/resources/db/SECTION_DICTIONARY_LCC.sql @@ -0,0 +1,16 @@ +-- DB version: 3.22 +-- SECTION_DICTIONARY LCC version: 3.22.0.0 + + +/* Dictionaries */ + +/* Business objects */ + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (1, 'MKR', 'Секция Денежного и Валютного рынков') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (2, 'FOND', 'Фондовая секция') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (3, 'CURR', 'Валютная секция') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + +INSERT INTO SECTION_DICTIONARY(ID, CODE, NAME) values (4, 'MULT', 'Единая') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME; + diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/OutboundRequestType.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/OutboundRequestType.java index 89208ce66..8553b871e 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/OutboundRequestType.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/OutboundRequestType.java @@ -12,6 +12,7 @@ public enum OutboundRequestType implements IEnumKey { REPORT_KS_TMP("REPORT_KS_TMP"), REPORT_KS_FINAL("REPORT_KS_FINAL"), MEMBER_RESPONSE_TKR("MEMBER_RESPONSE_TKR"), + CURRENCY_RATE("CURRENCY_RATE"), ; private final String key; diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/GatewayService.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/GatewayService.java index e77461afe..00f16200e 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/GatewayService.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/GatewayService.java @@ -32,6 +32,7 @@ import ru.spcex.clearing.gatewayapi.controller.inbound.request.operations.SentAs import ru.spcex.clearing.gatewayapi.controller.outbound.request.OutboundRequest; import ru.spcex.clearing.gatewayapi.controller.outbound.response.SuccessResponse; import ru.spcex.clearing.gatewayapi.enums.OutboundRequestType; +import ru.spcex.clearing.gatewayapi.service.builders.ContentBuilder; import ru.spcex.clearing.gatewayapi.service.builders.GatewayResultBuilder; import ru.spcex.clearing.gatewayapi.service.builders.OutboundRequestBuilder; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -97,6 +98,9 @@ public class GatewayService extends QueueConsumer implements InitializingBean { callback(GatewayTaskRequest.class) .setConsumer(this::requestOnDemandSecurity) .forDestination(Task.loadIssue_LOSC.topic(), callbacks::put); + callback(GatewayTaskRequest.class) + .setConsumer(this::requestOn) + .forDestination(Task.LORT.topic(), callbacks::put); callback(LimExportedRequest.class) .setConsumer(this::requestOnLimit) .forDestination(Consts.LIM_EXPORTED, callbacks::put); @@ -191,6 +195,27 @@ public class GatewayService extends QueueConsumer implements InitializingBean { log.debug("LOSC task 4/4 complete (CURR section)"); } + public void requestOn(BaseRequest userRequest) { + OutboundRequest settleRateReq = OutboundRequestBuilder.builder() + .type(OutboundRequestType.CURRENCY_RATE.getKey()) + .content(ContentBuilder.builder().settleRateBuild()) + .clearingSystem(clearingSystemValue) + .build(); + + OutboundRequest cbRateReq = OutboundRequestBuilder.builder() + .type(OutboundRequestType.CURRENCY_RATE.getKey()) + .content(ContentBuilder.builder().cbRateBuild()) + .clearingSystem(clearingSystemValue) + .build(); + + outboundRequestByUuid.put(settleRateReq.getId(), settleRateReq); + outboundRequestByUuid.put(cbRateReq.getId(), cbRateReq); + log.debug("LORT task 1/2 complete (SETTLE_RATE)"); + sendRequest(settleRateReq); + log.debug("LORT task 2/2 complete (CB_RATE)"); + sendRequest(cbRateReq); + } + public void requestOnAsset(BaseRequest request) { Long requestId = request.getId(); Collection assetOperations = request.getRequestPayload().getAssetOperationRequests(); diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/builders/ContentBuilder.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/builders/ContentBuilder.java new file mode 100644 index 000000000..1f9bd2cab --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/builders/ContentBuilder.java @@ -0,0 +1,33 @@ +package ru.spcex.clearing.gatewayapi.service.builders; + +import java.util.HashMap; +import java.util.Map; + +public class ContentBuilder { + + private ContentBuilder(){} + + public static ContentBuilder builder(){ + return new ContentBuilder(); + } + + public Map settleRateBuild() { + return new HashMap<>() {{ + put("sender_organization_code", "SPVB"); + put("sender_subsystem_code", "KS"); + put("recipient_organization_code", "SPVB"); + put("sender_rate_type_code", "SETTLE_RATE"); + put("recipient_rate_type_code", "NCC_RATE"); + }}; + } + + public Map cbRateBuild() { + return new HashMap<>() {{ + put("sender_organization_code", "SPVB"); + put("sender_subsystem_code", "KS"); + put("recipient_organization_code", "SPVB"); + put("sender_rate_type_code", "CB_RATE"); + put("recipient_rate_type_code", "CBR_RATE"); + }}; + } +} diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/facade/SCrossRateFacade.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/facade/SCrossRateFacade.java new file mode 100644 index 000000000..27a691069 --- /dev/null +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/facade/SCrossRateFacade.java @@ -0,0 +1,43 @@ +package ru.spcex.clearing.securities.service.facade; + +import java.math.BigDecimal; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.misc.Listing; +import ru.clearing.classes.statics.data.misc.SCrossRate; +import ru.clearing.classes.statics.data.security.Security; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateRequest; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; + +@Service +public class SCrossRateFacade { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final SecuritySelector securitySelector; + private final ImdgProvider imdgProvider; + private final ImdgId idGenerator; + private final Imdg sCrossRateImdg; + + public SCrossRateFacade(SecuritySelector securitySelector, ImdgProvider imdgProvider) { + this.securitySelector = securitySelector; + this.imdgProvider = imdgProvider; + this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.sCrossRateImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class); + } + + public Listing newSCrossRate(SCrossRateRequest req) { + + SCrossRate sCrossRate = new SCrossRate(); + sCrossRate.setDate(req.getDate()); + sCrossRate.setCurrency(req.getBaseCurrencyLetterCode()); + sCrossRate.setUnitRate(req.getRate()); + sCrossRate.setFaceValue(new BigDecimal(req.getBaseCurrencyUnit())); + sCrossRate.setRate(req.getPrice()); + return null; + } + +} 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 f6526cfa0..65765fd86 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 @@ -62,6 +62,7 @@ public enum Task implements IEnumKey { makeFiles_MTCR("MTCR"), // Формирование файлов с МТКР CX84("CX84"), // Формирование отчета CCX84 GVTF("GVTF"), // Проведение сверки по регистрам AMAT и AMAF + LORT("LORT"), // Загрузка курсов валют ; private final String key; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateRequest.java new file mode 100644 index 000000000..aa8a3e62c --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateRequest.java @@ -0,0 +1,109 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class SCrossRateRequest { + @JsonProperty + private String type; + @JsonProperty + private LocalDate date; + @JsonProperty + private String baseCurrencyLetterCode; + @JsonProperty + private String associatedCurrencyLetterCode; + @JsonProperty + private BigDecimal rate; + @JsonProperty + private Integer priceAccuracy; + @JsonProperty + private Integer baseCurrencyUnit; + @JsonProperty + private BigDecimal price; + @JsonProperty + private LocalDateTime updateDateTime; + @JsonProperty + private LocalDateTime sourceDateTime; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getBaseCurrencyLetterCode() { + return baseCurrencyLetterCode; + } + + public void setBaseCurrencyLetterCode(String baseCurrencyLetterCode) { + this.baseCurrencyLetterCode = baseCurrencyLetterCode; + } + + public String getAssociatedCurrencyLetterCode() { + return associatedCurrencyLetterCode; + } + + public void setAssociatedCurrencyLetterCode(String associatedCurrencyLetterCode) { + this.associatedCurrencyLetterCode = associatedCurrencyLetterCode; + } + + public BigDecimal getRate() { + return rate; + } + + public void setRate(BigDecimal rate) { + this.rate = rate; + } + + public Integer getPriceAccuracy() { + return priceAccuracy; + } + + public void setPriceAccuracy(Integer priceAccuracy) { + this.priceAccuracy = priceAccuracy; + } + + public Integer getBaseCurrencyUnit() { + return baseCurrencyUnit; + } + + public void setBaseCurrencyUnit(Integer baseCurrencyUnit) { + this.baseCurrencyUnit = baseCurrencyUnit; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public LocalDateTime getUpdateDateTime() { + return updateDateTime; + } + + public void setUpdateDateTime(LocalDateTime updateDateTime) { + this.updateDateTime = updateDateTime; + } + + public LocalDateTime getSourceDateTime() { + return sourceDateTime; + } + + public void setSourceDateTime(LocalDateTime sourceDateTime) { + this.sourceDateTime = sourceDateTime; + } +}