From 5f2cc2577db5e6c33446e46fdad588f1d2246a33 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Fri, 17 Apr 2026 15:26:00 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-967 --- .../queue/misc/SCrossRateController.java | 38 +++++++- .../cud/securities/SCrossRateNewAction.java | 37 ++++++++ .../securities/SCrossRateUpdateAction.java | 88 +++++++++++++++++++ .../src/main/resources/meta/meta.json | 64 +++++++++++++- .../src/main/resources/meta/meta.xml | 19 +++- .../securities/config/ValidationConfig.java | 2 + .../SCrossRatesValidationConfig.java | 57 ++++++++++++ .../service/facade/SCrossRateFacade.java | 3 + .../listeners/SCrossRatesMessageListener.java | 54 +++++++++++- .../rule/SCrossRatesValidationRule.java | 39 ++++++++ .../platform/messaging/domain/Consts.java | 2 + .../securitites/SCrossRateUpdateRequest.java | 21 +++++ 12 files changed, 418 insertions(+), 6 deletions(-) create mode 100644 clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java create mode 100644 clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java create mode 100644 clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/validation/SCrossRatesValidationConfig.java create mode 100644 clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/SCrossRatesValidationRule.java diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/SCrossRateController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/SCrossRateController.java index 7222c670d..062c787de 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/SCrossRateController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/SCrossRateController.java @@ -1,22 +1,31 @@ package ru.spcex.clearing.backendapi.controller.queue.misc; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ExecutionException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import ru.clearing.classes.statics.data.misc.SCrossRate; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; +import ru.spcex.clearing.backendapi.controller.request.cud.securities.SCrossRateNewAction; +import ru.spcex.clearing.backendapi.controller.request.cud.securities.SCrossRateUpdateAction; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; +import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; - -import java.util.Collection; -import java.util.Map; +import ru.spcex.clearing.platform.messaging.domain.Consts; @Controller @RequestMapping("/cross-rate") @@ -40,4 +49,27 @@ public class SCrossRateController extends AbstractQueueController { response.fromEntity(all); return response; } + + @ApiOperation(value = "create sCrossRates.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse create( + @ApiParam(value = "Значения полей нового объекта.", required = true) + @RequestBody SCrossRateNewAction ratesNewAction) throws ExecutionException, InterruptedException { + return processRequest(Consts.DESTINATION_S_CROSS_RATES_NEW, ratesNewAction); + } + + @ApiOperation(value = "update sCrossRates.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse update( + @ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234") + @PathVariable("id") Long id, + @ApiParam(value = "Новые значения полей объекта.", required = true) + @RequestBody SCrossRateUpdateAction ratesUpdateAction) throws ExecutionException, InterruptedException { + ratesUpdateAction.setId(id); + return processRequest(Consts.DESTINATION_S_CROSS_RATES_UPDATE, ratesUpdateAction); + } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java new file mode 100644 index 000000000..b257585cb --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java @@ -0,0 +1,37 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.securities; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateNewRequest; + +public class SCrossRateNewAction implements IAction { + @JsonProperty + private LocalDate date; + @JsonProperty + private String currency; + @JsonProperty + private BigDecimal unitRate; + @JsonProperty + private BigDecimal faceValue; + @JsonProperty + private BigDecimal rate; + + @Override + public SCrossRateNewRequest toRequest() { + SCrossRateNewRequest sCrossRateNewRequest = new SCrossRateNewRequest(); + sCrossRateNewRequest.setDate(date); + sCrossRateNewRequest.setCurrency(currency); + sCrossRateNewRequest.setUnitRate(unitRate); + sCrossRateNewRequest.setFaceValue(faceValue); + sCrossRateNewRequest.setRate(rate); + return sCrossRateNewRequest; + } + + @Override + public ActionType getActionType() { + return ActionType.NEW; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java new file mode 100644 index 000000000..564ce5625 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java @@ -0,0 +1,88 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.securities; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateUpdateRequest; + +public class SCrossRateUpdateAction implements IAction { + @JsonProperty + private Long id; + @JsonProperty + private LocalDate date; + @JsonProperty + private String currency; + @JsonProperty + private BigDecimal unitRate; + @JsonProperty + private BigDecimal faceValue; + @JsonProperty + private BigDecimal rate; + + @Override + public SCrossRateUpdateRequest toRequest() { + SCrossRateUpdateRequest sCrossRateUpdateRequest = new SCrossRateUpdateRequest(); + sCrossRateUpdateRequest.setId(id); + sCrossRateUpdateRequest.setDate(date); + sCrossRateUpdateRequest.setCurrency(currency); + sCrossRateUpdateRequest.setUnitRate(unitRate); + sCrossRateUpdateRequest.setFaceValue(faceValue); + sCrossRateUpdateRequest.setRate(rate); + return sCrossRateUpdateRequest; + } + + @Override + public ActionType getActionType() { + return ActionType.UPDATE; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getCurrency() { + return currency; + } + + public void setCurrency(String currency) { + this.currency = currency; + } + + public BigDecimal getUnitRate() { + return unitRate; + } + + public void setUnitRate(BigDecimal unitRate) { + this.unitRate = unitRate; + } + + public BigDecimal getFaceValue() { + return faceValue; + } + + public void setFaceValue(BigDecimal faceValue) { + this.faceValue = faceValue; + } + + public BigDecimal getRate() { + return rate; + } + + public void setRate(BigDecimal rate) { + this.rate = rate; + } +} 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 1087eec0d..5bd36957e 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.23.295.153", + "version": "3.23.295.154", "enums": { @@ -10901,7 +10901,69 @@ "field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true,"ignore": true } ] + ,"actions":[ + {"method":"post", + "name": "Добавление центрального курса", + + "class": "ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateNewRequest", + + "fields": [ + {"code": "date", + "name": "Дата торгов","shortname": "Дата","type": 6,"required": true + } + , + {"code": "currency", + "name": "Наименование валюты","shortname": "Валюта","type": 2,"length": 50,"link": "currencyCode","linkCode": "code","required": true + } + , + {"code": "faceValue", + "name": "Единица базовой валюты","shortname": "Единица базовой валюты","type": 10 + } + , + {"code": "rate", + "type": 10,"name": "Курс валюты с учетом размера лота","shortname": "Курс валюты" + } + , + {"code": "unitRate", + "type": 10,"name": "Курс за единицу иностранной валюты","shortname": "Курс за единицу валюты","required": true + } + ] + } + , + {"method":"put", + + "name": "Изменение центрального курса", + + "class": "ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateUpdateRequest", + + "fields": [ + {"code": "id", + "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "sCrossRate","linkCode": "id","required": true + } + , + {"code": "date", + "name": "Дата торгов","shortname": "Дата","type": 6,"required": true + } + , + {"code": "currency", + "name": "Наименование валюты","shortname": "Валюта","type": 2,"length": 50,"link": "currencyCode","linkCode": "code","required": true + } + , + {"code": "faceValue", + "name": "Единица базовой валюты","shortname": "Единица базовой валюты","type": 10 + } + , + {"code": "rate", + "type": 10,"name": "Курс валюты с учетом размера лота","shortname": "Курс валюты" + } + , + {"code": "unitRate", + "type": 10,"name": "Курс за единицу базовой валюты","shortname": "Курс за единицу валюты","required": true + } + ] + } + ] } , "blacklistMarket": { 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 2f2b747a6..de2e62cd1 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 @@ - + @@ -2525,6 +2525,23 @@ + + + + + + + + + + + + + + + + + diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/ValidationConfig.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/ValidationConfig.java index aea9bb26a..eed5c8680 100644 --- a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/ValidationConfig.java +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/ValidationConfig.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; +import ru.clearing.classes.statics.data.misc.SCrossRate; import ru.clearing.classes.statics.data.security.Rates; import ru.clearing.classes.statics.data.security.RiskParameter; import ru.clearing.platform.dictionary.CountryCodeDictionary; @@ -33,6 +34,7 @@ public class ValidationConfig { addImdg.accept(IMDGDistributedNames.Map_FixedIncomeCashFlow, CountryCodeDictionary.class); addImdg.accept(IMDGDistributedNames.Map_Rates, Rates.class); addImdg.accept(IMDGDistributedNames.Map_RiskParameter, RiskParameter.class); + addImdg.accept(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class); return imdg; } diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/validation/SCrossRatesValidationConfig.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/validation/SCrossRatesValidationConfig.java new file mode 100644 index 000000000..217b1a75f --- /dev/null +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/config/validation/SCrossRatesValidationConfig.java @@ -0,0 +1,57 @@ +package ru.spcex.clearing.securities.config.validation; + +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.clearing.classes.statics.data.misc.SCrossRate; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateUpdateRequest; +import ru.spcex.clearing.securities.errors.SecuritiesError; +import ru.spcex.clearing.securities.validation.rule.SCrossRatesValidationRule; +import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; +import ru.spcex.clearing.validation.common.rules.IdPresentRule; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +@Configuration +public class SCrossRatesValidationConfig { + + @Bean("sCrossRatesNewValidator") + public Function sCrossRatesNewValidator(Map> imdgForValidation) { + return ratesRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(ratesRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_SCrossRate); + return new ValidatorImpl<>(context, + FieldRequiredRule.instance("currency", SCrossRateNewRequest::getCurrency, SecuritiesError.RequiredFieldIsEmpty), + FieldRequiredRule.instance("date", SCrossRateNewRequest::getDate, SecuritiesError.RequiredFieldIsEmpty), + SCrossRatesValidationRule.CHECK_ON_EXIST + ); + }; + } + + @Bean("sCrossRatesUpdateValidator") + public Function sCrossRatesUpdateValidator(Map> imdgForValidation) { + return ratesUpdateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(ratesUpdateRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_SCrossRate); + return new ValidatorImpl<>(context, + IdPresentRule.instance("id", + SCrossRateUpdateRequest::getId, + IMDGDistributedNames.Map_SCrossRate, + SCrossRate.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.RequiredFieldIsEmpty) + ); + }; + } +} 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 index 4fc8b7761..319754a03 100644 --- 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 @@ -38,6 +38,9 @@ public class SCrossRateFacade { public void update(SCrossRateUpdateRequest req) { SCrossRate sCrossRate = sCrossRateImdg.getSingleObjectByID(req.getId()); + if (req.getDate() != null) { + sCrossRate.setDate(req.getDate()); + } sCrossRate.setUnitRate(req.getUnitRate()); sCrossRate.setFaceValue(req.getFaceValue()); sCrossRate.setRate(req.getRate()); diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/listeners/SCrossRatesMessageListener.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/listeners/SCrossRatesMessageListener.java index 82922c8cf..12deafe01 100644 --- a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/listeners/SCrossRatesMessageListener.java +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/listeners/SCrossRatesMessageListener.java @@ -2,6 +2,8 @@ package ru.spcex.clearing.securities.service.listeners; import java.math.BigDecimal; import java.util.Collection; +import java.util.Optional; +import java.util.function.Function; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.producer.Producer; import org.slf4j.Logger; @@ -18,18 +20,23 @@ import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateUpd import ru.spcex.clearing.platform.messaging.domain.gateway.rate.CurrencyRateGatewayElem; import ru.spcex.clearing.platform.messaging.domain.gateway.rate.SCrossRateGatewayRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.securities.service.facade.SCrossRateFacade; import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.validation.IValidator; @Service public class SCrossRatesMessageListener extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final ImdgProvider imdgProvider; private final UserRoleVerification userRoleVerification; + private final Function sCrossRatesNewValidator; + private final Function sCrossRatesUpdateValidator; private final IMessageResolver messageResolver; private final Imdg sCrossRateImdg; private final Imdg currencyCodeDictionaryImdg; @@ -38,6 +45,8 @@ public class SCrossRatesMessageListener extends QueueConsumer implements Initial public SCrossRatesMessageListener(Consumer kafkaQueue, Producer kafkaProducer, ImdgProvider imdgProvider, + Function sCrossRatesNewValidator, + Function sCrossRatesUpdateValidator, UserRoleVerification userRoleVerification, IMessageResolver messageResolver, SCrossRateFacade sCrossRateFacade) { @@ -45,6 +54,8 @@ public class SCrossRatesMessageListener extends QueueConsumer implements Initial this.imdgProvider = imdgProvider; this.userRoleVerification = userRoleVerification; this.messageResolver = messageResolver; + this.sCrossRatesNewValidator = sCrossRatesNewValidator; + this.sCrossRatesUpdateValidator = sCrossRatesUpdateValidator; this.sCrossRateImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class); this.sCrossRateFacade = sCrossRateFacade; this.currencyCodeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class); @@ -53,13 +64,54 @@ public class SCrossRatesMessageListener extends QueueConsumer implements Initial @Override public void afterPropertiesSet() { imdgProvider.waitAvailable(); - + callback(SCrossRateNewRequest.class) + .setFunction(this::sCrossRatesNew) + .forDestination(Consts.DESTINATION_S_CROSS_RATES_NEW, callbacks::put); + callback(SCrossRateUpdateRequest.class) + .setFunction(this::sCrossRatesUpdate) + .forDestination(Consts.DESTINATION_S_CROSS_RATES_UPDATE, callbacks::put); callback(SCrossRateGatewayRequest.class) .setConsumer(this::sCrossRatesProcess) .forDestination(Consts.DESTINATION_S_CROSS_RATES_GATEWAY, callbacks::put); init(); } + private RequestInfoUpdate sCrossRatesNew(BaseRequest ratesNewRequest) { + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(ratesNewRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + SCrossRateNewRequest request = ratesNewRequest.getRequestPayload(); + IValidator validator = sCrossRatesNewValidator.apply(request); + Optional error = validator.tillFirstError(); + if (error.isPresent()) { + String errMsg = messageResolver.resolve(error.get()); + return new RequestInfoUpdate() + .setId(ratesNewRequest.getId()) + .setStatus(ru.spcex.clearing.platform.messaging.service.Status.Error) + .setMessage(errMsg); + } + + sCrossRateFacade.create(request); + return null; + } + + private RequestInfoUpdate sCrossRatesUpdate(BaseRequest ratesUpdateRequest) { + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(ratesUpdateRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + SCrossRateUpdateRequest request = ratesUpdateRequest.getRequestPayload(); + IValidator validator = sCrossRatesUpdateValidator.apply(request); + Optional error = validator.tillFirstError(); + if (error.isPresent()) { + String errMsg = messageResolver.resolve(error.get()); + return new RequestInfoUpdate() + .setId(ratesUpdateRequest.getId()) + .setStatus(ru.spcex.clearing.platform.messaging.service.Status.Error) + .setMessage(errMsg); + } + + sCrossRateFacade.update(request); + return null; + } + private void sCrossRatesProcess(BaseRequest sCrossRatesReq) { SCrossRateGatewayRequest payload = sCrossRatesReq.getRequestPayload(); diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/SCrossRatesValidationRule.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/SCrossRatesValidationRule.java new file mode 100644 index 000000000..fccf12ac9 --- /dev/null +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/SCrossRatesValidationRule.java @@ -0,0 +1,39 @@ +package ru.spcex.clearing.securities.validation.rule; + +import java.util.Optional; +import ru.clearing.classes.statics.data.misc.SCrossRate; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateNewRequest; +import ru.spcex.clearing.securities.errors.SecuritiesError; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidationRule; + +public enum SCrossRatesValidationRule implements IValidationRule> { + CHECK_ON_EXIST() { + @Override + public Optional validate(ImdgValidationContext context) { + SCrossRateNewRequest action = context.getValidatedObject(); + Imdg imdgDictionary = context.obtainMap(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class); + + ImdgPredicateBuilder predicateBuilder = imdgDictionary.predicateBuilder(); + SCrossRate rates = imdgDictionary.getFirstObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("currency", action.getCurrency()), + predicateBuilder.equals("date", action.getDate()) + ) + ); + if (rates != null) { + return of(SecuritiesError.RatesAlreadyExist, action.getCurrency()); + } + return empty(); + } + }; + + @Override + public String ruleName() { + return "SCrossRateNewValidationRule." + name(); + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java index 7253ea097..72558fe86 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java @@ -133,6 +133,8 @@ public interface Consts { String DESTINATION_RATES_NEW = "rates-new"; String DESTINATION_RATES_UPDATE = "rates-update"; + String DESTINATION_S_CROSS_RATES_NEW = "s-cross-rates-new"; + String DESTINATION_S_CROSS_RATES_UPDATE = "s-cross-rates-update"; String DESTINATION_RATES_GATEWAY = "rates-gateway"; String DESTINATION_S_CROSS_RATES_GATEWAY = "sCross-rates-gateway"; String DESTINATION_VALIDATE_SYMBOLS_NEW = "validate-symbols-new"; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java index f48667b2c..ebe8f1e88 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java @@ -2,11 +2,16 @@ package ru.spcex.clearing.platform.messaging.domain.cud.securitites; import com.fasterxml.jackson.annotation.JsonProperty; import java.math.BigDecimal; +import java.time.LocalDate; public class SCrossRateUpdateRequest { @JsonProperty private Long id; @JsonProperty + private LocalDate date; + @JsonProperty + private String currency; + @JsonProperty private BigDecimal unitRate; @JsonProperty private BigDecimal faceValue; @@ -43,4 +48,20 @@ public class SCrossRateUpdateRequest { public void setRate(BigDecimal rate) { this.rate = rate; } + + public LocalDate getDate() { + return date; + } + + public void setDate(LocalDate date) { + this.date = date; + } + + public String getCurrency() { + return currency; + } + + public void setCurrency(String currency) { + this.currency = currency; + } }