This commit is contained in:
AKurakin 2024-04-23 15:05:03 +03:00
parent b004b9191a
commit 48c843e5c1
12 changed files with 650 additions and 3 deletions

View file

@ -87,8 +87,13 @@ public class RestTemplateErrorHandler implements ResponseErrorHandler {
case ON_DEMAND -> {
if (Section.MKR == section) {
prefix = "Ошибка загрузки инструментов";
} else {
} else if (Section.FOND == section) {
prefix = "Ошибка загрузки биржевых инструментов";
} else if (Section.CURR == section) {
prefix = "Ошибка загрузки биржевых валютных инструментов";
} else {//never
prefix = "Ошибка загрузки " + section + " инструментов";
log.error("No text for section={}", section);
}
}
case FILL_LIMITS -> prefix = "Ошибка выгрузки лимитов";

View file

@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.*;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.CommonRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.company.CompaniesRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.limit.LimitRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrListingsRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond.FondListingsRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.mkr.MMListingsRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.operations.OperationsRequest;
@ -20,6 +21,7 @@ import ru.spcex.clearing.gatewayapi.controller.inbound.response.CommonResponse;
import ru.spcex.clearing.gatewayapi.exception.GatewayException;
import ru.spcex.clearing.gatewayapi.service.OperationService;
import ru.spcex.clearing.gatewayapi.service.processor.CompanyProcessor;
import ru.spcex.clearing.gatewayapi.service.processor.ListingCurrProcessor;
import ru.spcex.clearing.gatewayapi.service.processor.ListingFondProcessor;
import ru.spcex.clearing.gatewayapi.service.processor.ListingMMProcessor;
import ru.spcex.platform.utils.enumeration.EnumMessage;
@ -40,6 +42,7 @@ public class GatewayController {
private final CompanyProcessor companiesProcessor;
private final ListingFondProcessor listingFondProcessor;
private final ListingMMProcessor listingMMProcessor;
private final ListingCurrProcessor listingCurrProcessor;
private final ExecutorService executor;
private final OperationService operationService;
@ -49,12 +52,14 @@ public class GatewayController {
CompanyProcessor companiesProcessor,
ListingFondProcessor listingFondProcessor,
ListingMMProcessor listingMMProcessor,
ListingCurrProcessor listingCurrProcessor,
@Qualifier("gatewayExecutor") ExecutorService executor,
OperationService operationService) {
this.messageResolver = messageResolver;
this.companiesProcessor = companiesProcessor;
this.listingFondProcessor = listingFondProcessor;
this.listingMMProcessor = listingMMProcessor;
this.listingCurrProcessor = listingCurrProcessor;
this.executor = executor;
this.operationService = operationService;
}
@ -98,6 +103,25 @@ public class GatewayController {
}
@ApiOperation(value = "Загрузка биржевого валютного инструмента в Клиринговую систему")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = CommonResponse.class),
@ApiResponse(code = 400, message = "Ошибка валидации", response = CommonResponse.class)
})
@RequestMapping(
path = "/listing_curr",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
@ResponseBody
public CommonResponse listingsCurr(@RequestBody CurrListingsRequest request) {
// request.validate(validTypes, List.of(Section.CURR));
executor.submit(() -> listingCurrProcessor.process(request));
return createResponse(request, true);
}
@ApiOperation(value = "Экспорт участников в клиринговую систему")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = CommonResponse.class),

View file

@ -0,0 +1,22 @@
package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.CommonRequest;
import java.util.ArrayList;
import java.util.List;
public class CurrListingsRequest extends CommonRequest {
@JsonProperty("currency_specification")
@ApiModelProperty(value = "Список инструментов")
private List<CurrencyInstrument> currencyInstrumentList = new ArrayList<>();
public List<CurrencyInstrument> getCurrencyInstrumentList() {
return currencyInstrumentList;
}
public void setCurrencyInstrumentList(List<CurrencyInstrument> currencyInstrumentList) {
this.currencyInstrumentList = currencyInstrumentList;
}
}

View file

@ -0,0 +1,342 @@
package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.gatewayapi.config.deserializers.LocalDateDeserializer;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.WithMapId;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;
public class CurrencyInstrument extends WithMapId {
@JsonProperty("id")
@ApiModelProperty(
value = "id",
example = "28406b73-7eab-4e21-9295-2ae8ee5c4eb5"
)
private UUID id;
@JsonProperty("ticker")
@ApiModelProperty(
value = "Код биржевого валютного инструмента",
example = "CNYRUB_TOD_N"
)
private String ticker;
@JsonProperty("name")
@ApiModelProperty(
value = "Наименование биржевого валютного инструмента",
example = "Спот-инструмент китайский юань с расчетами сегодня с клирингом в АО СПВБ"
)
private String name;
@JsonProperty("exchange_offexchange")
@ApiModelProperty(
value = """
Биржевой\\Внебиржевой
«EXCHANGE»\\«OFF_EXCHANGE»
""",
example = "EXCHANGE"
)
private String exchangeOffexchange;
@JsonProperty("min_step")
@ApiModelProperty(
value = "Шаг изменения цены, значение из listing.dir_price_min_step_precision.min_step",
example = "1"
)
private BigDecimal minStep;
@JsonProperty("precision")
@ApiModelProperty(
value = "Точность цены, значение из listing.dir_price_min_step_precision.precision, соответствующее значению из listing.dir_price_min_step_precision.min_step",
example = "2"
)
private BigDecimal precision;
@JsonProperty("settle_code")
@ApiModelProperty(
value = "Код (условия) расчетов: заполняется значением согласно справочнику «Код сектора в клиринговой системе»",
example = "T0"
)
private String settleCode;
@JsonProperty("value_date")
@ApiModelProperty(
value = "«Код (условия) расчетов» - заполняется значением системного справочника ",
example = "TOD"
)
private String valueDate;
@JsonProperty("symbol_trading_mode")
@ApiModelProperty(
value = """
Тип заявок (адресные/безадресные) - данные из системного справочника.
Y адресные
N безадресные
""",
example = "N"
)
private String symbolTradingMode;
@JsonProperty("lot_currency_letter_code")
@ApiModelProperty(
value = "Значение поля «Валюта лота»",
example = "CNY"
)
private String lotCurrencyLetterCode;
@JsonProperty("matched_currency_letter_code")
@ApiModelProperty(
value = "Значение поля «Сопряженная валюта»",
example = "RUB"
)
private String matchedCurrencyLetterCode;
@JsonProperty("trading_mode")
@ApiModelProperty(
value = "Доступные значения: из справочника «Режимы торгов Секция ДВР» - значение поля Спецификации «Режим торгов»",
example = "NVAD"
)
private String tradingMode;
@JsonProperty("lot_size")
@ApiModelProperty(
value = "Размер лота",
example = "1"
)
private BigDecimal lotSize;
@JsonProperty("clearing_organization")
@ApiModelProperty(
value = "Клиринговая организация",
example = "АО СПВБ"
)
private String clearingOrganization;
@JsonProperty("settlement_organization")
@ApiModelProperty(
value = "Расчетная организация",
example = "НКО АО ПРЦ"
)
private String settlementOrganization;
@JsonProperty("matched_settlement_organization")
@ApiModelProperty(
value = "Расчетная организация",
example = "НКО АО ПРЦ"
)
private String matchedSettlementOrganization;
@JsonProperty("number_of_lot_currency")
@ApiModelProperty(
value = "Размер лота",
example = "0"
)
private BigDecimal numberOfLotCurrency;
@JsonProperty("start_trading_date")
@JsonDeserialize(using = LocalDateDeserializer.class)
@ApiModelProperty(
value = "Дата начала торгов инструментом",
example = "21.02.2024"
)
private LocalDate startTradingDate;
@JsonProperty("specification_approval_date")
@JsonDeserialize(using = LocalDateDeserializer.class)
@ApiModelProperty(
value = "Дата принятия Решения об утверждении Спецификации биржевого инструмента",
example = "21.02.2024"
)
private LocalDate specificationApprovalDate;
@JsonProperty("specification_approval_number")
@ApiModelProperty(
value = "Номер принятия Решения об утверждении Спецификации биржевого инструмента",
example = "125"
)
private String specificationApprovalNumber;
@JsonProperty("workflow_status")
@ApiModelProperty(
value = """
«ACTV»|«BLKD»
""",
example = "ACTV"
)
private String workflowStatus;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getExchangeOffexchange() {
return exchangeOffexchange;
}
public void setExchangeOffexchange(String exchangeOffexchange) {
this.exchangeOffexchange = exchangeOffexchange;
}
public BigDecimal getMinStep() {
return minStep;
}
public void setMinStep(BigDecimal minStep) {
this.minStep = minStep;
}
public BigDecimal getPrecision() {
return precision;
}
public void setPrecision(BigDecimal precision) {
this.precision = precision;
}
public String getSettleCode() {
return settleCode;
}
public void setSettleCode(String settleCode) {
this.settleCode = settleCode;
}
public String getValueDate() {
return valueDate;
}
public void setValueDate(String valueDate) {
this.valueDate = valueDate;
}
public String getSymbolTradingMode() {
return symbolTradingMode;
}
public void setSymbolTradingMode(String symbolTradingMode) {
this.symbolTradingMode = symbolTradingMode;
}
public String getLotCurrencyLetterCode() {
return lotCurrencyLetterCode;
}
public void setLotCurrencyLetterCode(String lotCurrencyLetterCode) {
this.lotCurrencyLetterCode = lotCurrencyLetterCode;
}
public String getMatchedCurrencyLetterCode() {
return matchedCurrencyLetterCode;
}
public void setMatchedCurrencyLetterCode(String matchedCurrencyLetterCode) {
this.matchedCurrencyLetterCode = matchedCurrencyLetterCode;
}
public String getTradingMode() {
return tradingMode;
}
public void setTradingMode(String tradingMode) {
this.tradingMode = tradingMode;
}
public BigDecimal getLotSize() {
return lotSize;
}
public void setLotSize(BigDecimal lotSize) {
this.lotSize = lotSize;
}
public String getClearingOrganization() {
return clearingOrganization;
}
public void setClearingOrganization(String clearingOrganization) {
this.clearingOrganization = clearingOrganization;
}
public String getSettlementOrganization() {
return settlementOrganization;
}
public void setSettlementOrganization(String settlementOrganization) {
this.settlementOrganization = settlementOrganization;
}
public String getMatchedSettlementOrganization() {
return matchedSettlementOrganization;
}
public void setMatchedSettlementOrganization(String matchedSettlementOrganization) {
this.matchedSettlementOrganization = matchedSettlementOrganization;
}
public BigDecimal getNumberOfLotCurrency() {
return numberOfLotCurrency;
}
public void setNumberOfLotCurrency(BigDecimal numberOfLotCurrency) {
this.numberOfLotCurrency = numberOfLotCurrency;
}
public LocalDate getStartTradingDate() {
return startTradingDate;
}
public void setStartTradingDate(LocalDate startTradingDate) {
this.startTradingDate = startTradingDate;
}
public LocalDate getSpecificationApprovalDate() {
return specificationApprovalDate;
}
public void setSpecificationApprovalDate(LocalDate specificationApprovalDate) {
this.specificationApprovalDate = specificationApprovalDate;
}
public String getSpecificationApprovalNumber() {
return specificationApprovalNumber;
}
public void setSpecificationApprovalNumber(String specificationApprovalNumber) {
this.specificationApprovalNumber = specificationApprovalNumber;
}
public String getWorkflowStatus() {
return workflowStatus;
}
public void setWorkflowStatus(String workflowStatus) {
this.workflowStatus = workflowStatus;
}
}

View file

@ -148,20 +148,32 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
.type(OutboundRequestType.ON_DEMAND.getKey())
.build();
OutboundRequest outboundCurrRequest = OutboundRequestBuilder.builder()
.section(Section.CURR.getKey())
.type(OutboundRequestType.ON_DEMAND.getKey())
.build();
HttpEntity<OutboundRequest> requestFond = makeDefaultRequest(outboundFondRequest);
HttpEntity<OutboundRequest> requestMKR = makeDefaultRequest(outboundMkrRequest);
HttpEntity<OutboundRequest> requestCURR = makeDefaultRequest(outboundCurrRequest);
outboundRequestByUuid.put(outboundFondRequest.getId(), outboundFondRequest);
outboundRequestByUuid.put(outboundMkrRequest.getId(), outboundMkrRequest);
outboundRequestByUuid.put(outboundCurrRequest.getId(), outboundCurrRequest);
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, requestFond, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOSC task 1/2 complete (FOND section), success response: {}", bodyResponse);
log.debug("LOSC task 1/3 complete (FOND section), success response: {}", bodyResponse);
}
response = restTemplate.exchange(url, HttpMethod.POST, requestMKR, SuccessResponse.class);
bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOSC task 2/2 complete (MKR section), success response: {}", bodyResponse);
log.debug("LOSC task 2/3 complete (MKR section), success response: {}", bodyResponse);
}
response = restTemplate.exchange(url, HttpMethod.POST, requestCURR, SuccessResponse.class);
bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOSC task 3/3 complete (CURR section), success response: {}", bodyResponse);
}
}

View file

@ -0,0 +1,33 @@
package ru.spcex.clearing.gatewayapi.service.adapter;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrencyInstrument;
import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewGatewayRequest;
import ru.spcex.platform.enumeration.InstrumentType;
@Service
public class CurrencyPairSecurityRequestAdapter {
public CurrencyPairSecurityNewGatewayRequest toCurrencySecurityNewRequest(CurrencyInstrument currencyInstrument) {
CurrencyPairSecurityNewGatewayRequest req = new CurrencyPairSecurityNewGatewayRequest();
CurrencyPairSecurityNewRequest securityNewRequest = new CurrencyPairSecurityNewRequest();
securityNewRequest.setInstrumentType(InstrumentType.CRNC.getKey());
securityNewRequest.setSecuritySymbol(currencyInstrument.getTicker());
securityNewRequest.setFullName(currencyInstrument.getName());
securityNewRequest.setBaseUnitSize(currencyInstrument.getNumberOfLotCurrency());
securityNewRequest.setSettlementType(currencyInstrument.getSettleCode());
securityNewRequest.setClearingOrganization(currencyInstrument.getClearingOrganization());
securityNewRequest.setWorkflowStatus(currencyInstrument.getWorkflowStatus());
//to listing
securityNewRequest.setMinStep(currencyInstrument.getMinStep());
securityNewRequest.setPrecision(currencyInstrument.getPrecision());
securityNewRequest.setLotSize(currencyInstrument.getLotSize());
req.setCurrencySecurityNewRequest(securityNewRequest);
// req.setUuid(currencyInstrument.getInitiatorId() != null ? currencyInstrument.getInitiatorId().toString() : null);
return req;
}
}

View file

@ -0,0 +1,70 @@
package ru.spcex.clearing.gatewayapi.service.processor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrListingsRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrencyInstrument;
import ru.spcex.clearing.gatewayapi.service.CodeStatusComparator;
import ru.spcex.clearing.gatewayapi.service.adapter.CurrencyPairSecurityRequestAdapter;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewGatewayRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.utils.log.ExceptionUtils;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Service
public class ListingCurrProcessor {
private final Logger log = LoggerFactory.getLogger(getClass());
private final CurrencyPairSecurityRequestAdapter currencyPairSecurityRequestAdapter;
private final KafkaSender kafkaSender;
public ListingCurrProcessor(CurrencyPairSecurityRequestAdapter currencyPairSecurityRequestAdapter,
KafkaSender kafkaSender) {
this.currencyPairSecurityRequestAdapter = currencyPairSecurityRequestAdapter;
this.kafkaSender = kafkaSender;
}
public void process(CurrListingsRequest request) {
List<CurrencyInstrument> currencyInstrumentList = request.getCurrencyInstrumentList();
CodeStatusComparator<CurrencyInstrument> comparatorByCodeAndWorkflowStatus = CodeStatusComparator.create(
CurrencyInstrument::getTicker,
CurrencyInstrument::getWorkflowStatus);
currencyInstrumentList = currencyInstrumentList.stream()
.filter(ei -> {
if (StringUtils.isEmpty(ei.getTicker())) {
log.warn("CurrencyInstrument {}, ignore 1002: required field 'ticker' was empty", ei.getId());
return false;
}
if ("EXCHANGE".equalsIgnoreCase(StringUtils.trim(ei.getExchangeOffexchange()))) {
return true;
} else {
log.trace("CurrencyInstrument {} with ticker={} ignore: not allow exchange_offexchange={}",
ei.getId(), ei.getTicker(), ei.getExchangeOffexchange());
return false;
}
})
.sorted(comparatorByCodeAndWorkflowStatus).collect(Collectors.toList());
for (CurrencyInstrument currencyInstrument : currencyInstrumentList) {
UUID currencyInstrumentId = null;
try {
currencyInstrumentId = currencyInstrument.getId();
log.debug("Process currencyInstrumentId : {}", currencyInstrumentId);
// if (StringUtils.isEmpty(currencyInstrument.getCode()) || currencyInstrument.getCode().length() < 6) {
// log.warn("Incorrect code : {}, skip record", currencyInstrument.getCode());
// continue;
// }
CurrencyPairSecurityNewGatewayRequest currencySecurityNewRequest = currencyPairSecurityRequestAdapter
.toCurrencySecurityNewRequest(currencyInstrument);
kafkaSender.sendRequestToQueue(Consts.DESTINATION_GATEWAY_CURRENCY_PAIR_SECURITY, currencySecurityNewRequest);
} catch (Throwable e) {
log.error("currencyInstrumentId={}: {}", currencyInstrumentId, ExceptionUtils.getStackTrace(e));
}
}
}
}

View file

@ -1,14 +1,19 @@
package ru.spcex.clearing.gatewayapi.controller;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrListingsRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrencyInstrument;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond.FondListingsRequest;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond.FondSecurity;
import ru.spcex.clearing.gatewayapi.controller.inbound.response.CommonResponse;
import ru.spcex.clearing.test.json.JsonUtil;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -20,6 +25,7 @@ import static ru.spcex.clearing.test.json.JsonUtil.writeValue;
class GatewayControllerTest extends AbstractControllerTest{
public static final String LISTING_FOND_URL = "/listing_fond/";
public static final String LISTING_CURR_URL = "/listing_curr/";
@Test
void listingsFond() throws Exception {
@ -356,4 +362,95 @@ class GatewayControllerTest extends AbstractControllerTest{
"\t\t}\n" +
"\t]\n" +
"}";
@Test
void listingsCurr() throws Exception {
CommonResponse expected = new CommonResponse();
expected.setCode(0L);
expected.setMessage("success");
CurrListingsRequest request = new CurrListingsRequest();
List<CurrencyInstrument> instruments = new ArrayList<>();
CurrencyInstrument cInst = new CurrencyInstrument();
// cInst.setInstrumentType("CURR");
cInst.setId(UUID.fromString("28406b73-7eab-4e21-9295-2ae8ee5c4eb5"));
cInst.setTicker("CNYRUB_TOD_N");
cInst.setName("Спот-инструмент китайский юань с расчетами сегодня с клирингом в АО СПВБ");
cInst.setExchangeOffexchange("EXCHANGE");
cInst.setMinStep(BigDecimal.valueOf(1));
cInst.setPrecision(BigDecimal.valueOf(2));
cInst.setSettleCode("T0");
cInst.setValueDate("TOD");
cInst.setSymbolTradingMode("N");
cInst.setLotCurrencyLetterCode("CNY");
cInst.setMatchedCurrencyLetterCode("RUB");
cInst.setTradingMode("NVAD");
cInst.setLotSize(BigDecimal.valueOf(1));
cInst.setClearingOrganization("АО СПВБ");
cInst.setSettlementOrganization("НКО АО ПРЦ");
cInst.setMatchedSettlementOrganization("НКО АО ПРЦ");
cInst.setNumberOfLotCurrency(BigDecimal.valueOf(0));
cInst.setStartTradingDate(LocalDate.of(2024,2,21));
cInst.setSpecificationApprovalDate(LocalDate.of(2024,2,21));
cInst.setSpecificationApprovalNumber("125");
cInst.setWorkflowStatus("ACTV");
instruments.add(cInst);
request.setCurrencyInstrumentList(instruments);
String req1 = writeValue(request);
Assertions.assertEquals("{\"id\":null,\"type\":null,\"datetime\":null,\"section\":null,\"currency_specification\":[{\"id\":\"28406b73-7eab-4e21-9295-2ae8ee5c4eb5\",\"ticker\":\"CNYRUB_TOD_N\",\"name\":\"Спот-инструмент китайский юань с расчетами сегодня с клирингом в АО СПВБ\",\"exchange_offexchange\":\"EXCHANGE\",\"min_step\":1,\"precision\":2,\"settle_code\":\"T0\",\"value_date\":\"TOD\",\"symbol_trading_mode\":\"N\",\"lot_currency_letter_code\":\"CNY\",\"matched_currency_letter_code\":\"RUB\",\"trading_mode\":\"NVAD\",\"lot_size\":1,\"clearing_organization\":\"АО СПВБ\",\"settlement_organization\":\"НКО АО ПРЦ\",\"matched_settlement_organization\":\"НКО АО ПРЦ\",\"number_of_lot_currency\":0,\"start_trading_date\":\"2024-02-21\",\"specification_approval_date\":\"2024-02-21\",\"specification_approval_number\":\"125\",\"workflow_status\":\"ACTV\"}]}",
req1);
final String CURR_REQ = """
{
"id": "1126de52-59ba-4118-a055-a6ac9b214ccd",
"type": "DAY_START",
"section": "CURR",
"datetime": "29.02.2024 15:57:44:506",
"currency_specification":
[
{
"id": "28406b73-7eab-4e21-9295-2ae8ee5c4eb5",
"ticker": "CNYRUB_TOD_N",
"name": "Спот-инструмент китайский юань с расчетами сегодня с клирингом в АО СПВБ",
"exchange_offexchange": "EXCHANGE",
"min_step": 1,
"precision": 2,
"settle_code": "T0",
"value_date": "TOD",
"symbol_trading_mode": "N",
"lot_currency_letter_code": "CNY",
"matched_currency_letter_code": "RUB",
"trading_mode": "NVAD",
"lot_size": 1,
"clearing_organization": "АО СПВБ",
"settlement_organization": "НКО АО ПРЦ",
"matched_settlement_organization": "НКО АО ПРЦ",
"number_of_lot_currency": 0,
"start_trading_date": "21.02.2024",
"specification_approval_date": "21.02.2024",
"specification_approval_number": "125",
"workflow_status": "ACTV"
}
]
}
""";
//ACT
MvcResult mvcResult = perform(MockMvcRequestBuilders.post(LISTING_FOND_URL)
.contentType(MediaType.APPLICATION_JSON)
.content(CURR_REQ))
.andDo(print())//output to the log request and response
//ASSERT
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
//.andExpect(content().json(writeValue(expected)))
.andReturn();
String resp = mvcResult.getResponse().getContentAsString();
String expResp = "{\"id\":\"1126de52-59ba-4118-a055-a6ac9b214ccd\",\"type\":\"DAY_START\",\"datetime\":\"29.02.2024 15:57:44:506\",\"section\":\"CURR\",\"code\":0,\"message\":\"success\"}";
resp = resp.replaceAll("\"datetime\":\"[0-9\\\\.: ]+\",", "__DATE_TIME_");
expResp = expResp.replaceAll("\"datetime\":\"[0-9\\\\.: ]+\",", "__DATE_TIME_");
Assertions.assertEquals(expResp, resp);
// CudResponseTest cudResponseTest = JsonUtil.readValue(mvcResult.getResponse().getContentAsString(), CudResponseTest.class);
// expected.setPayload(new QueueSuccessResponse(ActionType.NEW, cudResponseTest.getPayload().getId()));
// CUD_RESPONSE_MATCHER.assertMatch(cudResponseTest, expected);
}
}

View file

@ -15,6 +15,7 @@ import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityUpdateRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewGatewayRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.securities.validation.ValidationProvider;
@ -73,6 +74,10 @@ public class CurrencyPairSecurityService extends QueueConsumer implements Initia
callback(CommonDeleteRequest.class)
.setFunction(this::deleteCurrencyPairSecurity)
.forDestination(Consts.DESTINATION_CURRENCY_PAIR_SECURITIES_DELETE, callbacks::put);
//todo DESTINATION_GATEWAY_CURRENCY_PAIR_SECURITY see CLS-612, CLS-663
// callback(CurrencyPairSecurityNewGatewayRequest.class)
// .setFunction(this::newCurrencyPairSecurity)
// .forDestination(Consts.DESTINATION_GATEWAY_CURRENCY_PAIR_SECURITY, callbacks::put);
imdgProvider.waitAvailable();
init();
}

View file

@ -187,6 +187,7 @@ public interface Consts {
String DESTINATION_TRADING_CLEARING_REGISTRY_ON_TCRLIST_NEW = "registry-on-trading_clearing_registry_list-new";
String DESTINATION_GATEWAY_CURRENCY_PAIR_SECURITY = "currency-pair-securities-gateway-new";
String DESTINATION_CURRENCY_PAIR_SECURITIES_NEW = "currency-pair-securities-new";
String DESTINATION_CURRENCY_PAIR_SECURITIES_UPDATE = "currency-pair-securities-update";
String DESTINATION_CURRENCY_PAIR_SECURITIES_DELETE = "currency-pair-securities-delete";

View file

@ -0,0 +1,26 @@
package ru.spcex.clearing.platform.messaging.domain.cud.security;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CurrencyPairSecurityNewGatewayRequest {
@JsonProperty
private String uuid;
@JsonProperty
private CurrencyPairSecurityNewRequest currencySecurityNewRequest;
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public CurrencyPairSecurityNewRequest getCurrencySecurityNewRequest() {
return currencySecurityNewRequest;
}
public void setCurrencySecurityNewRequest(CurrencyPairSecurityNewRequest currencySecurityNewRequest) {
this.currencySecurityNewRequest = currencySecurityNewRequest;
}
}

View file

@ -23,6 +23,8 @@ public class CurrencyPairSecurityNewRequest implements WithSecuritySymbol, WithI
@JsonProperty
private BigDecimal minStep;
@JsonProperty
private BigDecimal precision;
@JsonProperty
private BigDecimal baseUnitSize;
@JsonProperty
private String settlementType;
@ -89,6 +91,14 @@ public class CurrencyPairSecurityNewRequest implements WithSecuritySymbol, WithI
this.minStep = minStep;
}
public BigDecimal getPrecision() {
return precision;
}
public void setPrecision(BigDecimal precision) {
this.precision = precision;
}
public BigDecimal getBaseUnitSize() {
return baseUnitSize;
}