gateway-api http://jira.mfd.msk:8088/browse/CLS-663 CURR(currency-pair)
This commit is contained in:
parent
b004b9191a
commit
48c843e5c1
12 changed files with 650 additions and 3 deletions
|
|
@ -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 = "Ошибка выгрузки лимитов";
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue