etreschenkov 2026-04-17 15:26:00 +03:00
parent 2f27d41972
commit 5f2cc2577d
12 changed files with 418 additions and 6 deletions

View file

@ -1,22 +1,31 @@
package ru.spcex.clearing.backendapi.controller.queue.misc; package ru.spcex.clearing.backendapi.controller.queue.misc;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses; 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.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller; 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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import ru.clearing.classes.statics.data.misc.SCrossRate; import ru.clearing.classes.statics.data.misc.SCrossRate;
import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; 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.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IOperator;
import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.backendapi.service.IStateLoader;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import java.util.Collection;
import java.util.Map;
@Controller @Controller
@RequestMapping("/cross-rate") @RequestMapping("/cross-rate")
@ -40,4 +49,27 @@ public class SCrossRateController extends AbstractQueueController {
response.fromEntity(all); response.fromEntity(all);
return response; 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);
}
} }

View file

@ -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<SCrossRateNewRequest> {
@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;
}
}

View file

@ -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<SCrossRateUpdateRequest> {
@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;
}
}

View file

@ -1,6 +1,6 @@
{ {
"version": "3.23.295.153", "version": "3.23.295.154",
"enums": { "enums": {
@ -10901,7 +10901,69 @@
"field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true,"ignore": true "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": { "blacklistMarket": {

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?--> <!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?-->
<meta version="3.23.295.153"> <meta version="3.23.295.154">
<!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" --> <!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" -->
<!--Здесь словари--> <!--Здесь словари-->
<enums> <enums>
@ -2525,6 +2525,23 @@
<generationId type="1" name="Идентификатор взаимодействия" shortname="ID взаимодействия" searchable="true" sortable="true" visible="true"/> <generationId type="1" name="Идентификатор взаимодействия" shortname="ID взаимодействия" searchable="true" sortable="true" visible="true"/>
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<actions>
<post name="Добавление центрального курса" class="ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateNewRequest">
<date name="Дата торгов" shortname="Дата" type="6" required="true"/>
<currency name="Наименование валюты" shortname="Валюта" type="2" length="50" link="currencyCode" linkCode="code" required="true"/>
<faceValue name="Единица базовой валюты" shortname="Единица базовой валюты" type="10"/>
<rate type="10" name="Курс валюты с учетом размера лота" shortname="Курс валюты"/>
<unitRate type="10" name="Курс за единицу иностранной валюты" shortname="Курс за единицу валюты" required="true"/>
</post>
<put name="Изменение центрального курса" class="ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateUpdateRequest">
<id type="1" name="Идентификатор записи" shortname="ID" link="sCrossRate" linkCode="id" required="true"/>
<date name="Дата торгов" shortname="Дата" type="6" required="true"/>
<currency name="Наименование валюты" shortname="Валюта" type="2" length="50" link="currencyCode" linkCode="code" required="true"/>
<faceValue name="Единица базовой валюты" shortname="Единица базовой валюты" type="10"/>
<rate type="10" name="Курс валюты с учетом размера лота" shortname="Курс валюты"/>
<unitRate type="10" name="Курс за единицу базовой валюты" shortname="Курс за единицу валюты" required="true"/>
</put>
</actions>
</sCrossRate> </sCrossRate>
<blacklistMarket name="blacklist площадок" destination="blacklist-market" class="ru.clearing.classes.statics.data.misc.BlacklistMarket" table="blacklist_market"> <blacklistMarket name="blacklist площадок" destination="blacklist-market" class="ru.clearing.classes.statics.data.misc.BlacklistMarket" table="blacklist_market">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true" visible="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true" visible="true"/>

View file

@ -4,6 +4,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope; 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.Rates;
import ru.clearing.classes.statics.data.security.RiskParameter; import ru.clearing.classes.statics.data.security.RiskParameter;
import ru.clearing.platform.dictionary.CountryCodeDictionary; import ru.clearing.platform.dictionary.CountryCodeDictionary;
@ -33,6 +34,7 @@ public class ValidationConfig {
addImdg.accept(IMDGDistributedNames.Map_FixedIncomeCashFlow, CountryCodeDictionary.class); addImdg.accept(IMDGDistributedNames.Map_FixedIncomeCashFlow, CountryCodeDictionary.class);
addImdg.accept(IMDGDistributedNames.Map_Rates, Rates.class); addImdg.accept(IMDGDistributedNames.Map_Rates, Rates.class);
addImdg.accept(IMDGDistributedNames.Map_RiskParameter, RiskParameter.class); addImdg.accept(IMDGDistributedNames.Map_RiskParameter, RiskParameter.class);
addImdg.accept(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class);
return imdg; return imdg;
} }

View file

@ -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<SCrossRateNewRequest, IValidator> sCrossRatesNewValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return ratesRequest -> {
ImdgValidationContext<SCrossRateNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(ratesRequest);
Consumer<String> 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<SCrossRateUpdateRequest, IValidator> sCrossRatesUpdateValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return ratesUpdateRequest -> {
ImdgValidationContext<SCrossRateUpdateRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(ratesUpdateRequest);
Consumer<String> 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)
);
};
}
}

View file

@ -38,6 +38,9 @@ public class SCrossRateFacade {
public void update(SCrossRateUpdateRequest req) { public void update(SCrossRateUpdateRequest req) {
SCrossRate sCrossRate = sCrossRateImdg.getSingleObjectByID(req.getId()); SCrossRate sCrossRate = sCrossRateImdg.getSingleObjectByID(req.getId());
if (req.getDate() != null) {
sCrossRate.setDate(req.getDate());
}
sCrossRate.setUnitRate(req.getUnitRate()); sCrossRate.setUnitRate(req.getUnitRate());
sCrossRate.setFaceValue(req.getFaceValue()); sCrossRate.setFaceValue(req.getFaceValue());
sCrossRate.setRate(req.getRate()); sCrossRate.setRate(req.getRate());

View file

@ -2,6 +2,8 @@ package ru.spcex.clearing.securities.service.listeners;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Collection; 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.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.Producer;
import org.slf4j.Logger; 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.CurrencyRateGatewayElem;
import ru.spcex.clearing.platform.messaging.domain.gateway.rate.SCrossRateGatewayRequest; 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.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.securities.service.facade.SCrossRateFacade; import ru.spcex.clearing.securities.service.facade.SCrossRateFacade;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; 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.enumeration.IMessageResolver;
import ru.spcex.platform.utils.validation.IValidator;
@Service @Service
public class SCrossRatesMessageListener extends QueueConsumer implements InitializingBean { public class SCrossRatesMessageListener extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private final UserRoleVerification userRoleVerification; private final UserRoleVerification userRoleVerification;
private final Function<SCrossRateNewRequest, IValidator> sCrossRatesNewValidator;
private final Function<SCrossRateUpdateRequest, IValidator> sCrossRatesUpdateValidator;
private final IMessageResolver messageResolver; private final IMessageResolver messageResolver;
private final Imdg<SCrossRate> sCrossRateImdg; private final Imdg<SCrossRate> sCrossRateImdg;
private final Imdg<CurrencyCodeDictionary> currencyCodeDictionaryImdg; private final Imdg<CurrencyCodeDictionary> currencyCodeDictionaryImdg;
@ -38,6 +45,8 @@ public class SCrossRatesMessageListener extends QueueConsumer implements Initial
public SCrossRatesMessageListener(Consumer<String, Object> kafkaQueue, public SCrossRatesMessageListener(Consumer<String, Object> kafkaQueue,
Producer<String, Object> kafkaProducer, Producer<String, Object> kafkaProducer,
ImdgProvider imdgProvider, ImdgProvider imdgProvider,
Function<SCrossRateNewRequest, IValidator> sCrossRatesNewValidator,
Function<SCrossRateUpdateRequest, IValidator> sCrossRatesUpdateValidator,
UserRoleVerification userRoleVerification, UserRoleVerification userRoleVerification,
IMessageResolver messageResolver, IMessageResolver messageResolver,
SCrossRateFacade sCrossRateFacade) { SCrossRateFacade sCrossRateFacade) {
@ -45,6 +54,8 @@ public class SCrossRatesMessageListener extends QueueConsumer implements Initial
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.userRoleVerification = userRoleVerification; this.userRoleVerification = userRoleVerification;
this.messageResolver = messageResolver; this.messageResolver = messageResolver;
this.sCrossRatesNewValidator = sCrossRatesNewValidator;
this.sCrossRatesUpdateValidator = sCrossRatesUpdateValidator;
this.sCrossRateImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class); this.sCrossRateImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SCrossRate, SCrossRate.class);
this.sCrossRateFacade = sCrossRateFacade; this.sCrossRateFacade = sCrossRateFacade;
this.currencyCodeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class); this.currencyCodeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class);
@ -53,13 +64,54 @@ public class SCrossRatesMessageListener extends QueueConsumer implements Initial
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
imdgProvider.waitAvailable(); 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) callback(SCrossRateGatewayRequest.class)
.setConsumer(this::sCrossRatesProcess) .setConsumer(this::sCrossRatesProcess)
.forDestination(Consts.DESTINATION_S_CROSS_RATES_GATEWAY, callbacks::put); .forDestination(Consts.DESTINATION_S_CROSS_RATES_GATEWAY, callbacks::put);
init(); init();
} }
private RequestInfoUpdate sCrossRatesNew(BaseRequest<SCrossRateNewRequest> ratesNewRequest) {
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(ratesNewRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
SCrossRateNewRequest request = ratesNewRequest.getRequestPayload();
IValidator validator = sCrossRatesNewValidator.apply(request);
Optional<EnumMessage> 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<SCrossRateUpdateRequest> ratesUpdateRequest) {
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(ratesUpdateRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
SCrossRateUpdateRequest request = ratesUpdateRequest.getRequestPayload();
IValidator validator = sCrossRatesUpdateValidator.apply(request);
Optional<EnumMessage> 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<SCrossRateGatewayRequest> sCrossRatesReq) { private void sCrossRatesProcess(BaseRequest<SCrossRateGatewayRequest> sCrossRatesReq) {
SCrossRateGatewayRequest payload = sCrossRatesReq.getRequestPayload(); SCrossRateGatewayRequest payload = sCrossRatesReq.getRequestPayload();

View file

@ -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<ImdgValidationContext<SCrossRateNewRequest>> {
CHECK_ON_EXIST() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SCrossRateNewRequest> context) {
SCrossRateNewRequest action = context.getValidatedObject();
Imdg<SCrossRate> 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();
}
}

View file

@ -133,6 +133,8 @@ public interface Consts {
String DESTINATION_RATES_NEW = "rates-new"; String DESTINATION_RATES_NEW = "rates-new";
String DESTINATION_RATES_UPDATE = "rates-update"; 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_RATES_GATEWAY = "rates-gateway";
String DESTINATION_S_CROSS_RATES_GATEWAY = "sCross-rates-gateway"; String DESTINATION_S_CROSS_RATES_GATEWAY = "sCross-rates-gateway";
String DESTINATION_VALIDATE_SYMBOLS_NEW = "validate-symbols-new"; String DESTINATION_VALIDATE_SYMBOLS_NEW = "validate-symbols-new";

View file

@ -2,11 +2,16 @@ package ru.spcex.clearing.platform.messaging.domain.cud.securitites;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate;
public class SCrossRateUpdateRequest { public class SCrossRateUpdateRequest {
@JsonProperty @JsonProperty
private Long id; private Long id;
@JsonProperty @JsonProperty
private LocalDate date;
@JsonProperty
private String currency;
@JsonProperty
private BigDecimal unitRate; private BigDecimal unitRate;
@JsonProperty @JsonProperty
private BigDecimal faceValue; private BigDecimal faceValue;
@ -43,4 +48,20 @@ public class SCrossRateUpdateRequest {
public void setRate(BigDecimal rate) { public void setRate(BigDecimal rate) {
this.rate = 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;
}
} }