From d06ec59deaff13de540cebf25b54ab993573adbc Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 3 Feb 2026 08:39:59 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-924 --- .../gatewayapi/config/GatewayApiSettings.java | 10 + .../CurrencySpecificationFormatConverter.java | 21 ++ .../controller/GatewayController.java | 32 ++- .../curr/mkr/CurrListingsMassiveRequest.java | 33 +++ .../request/listing/curr/mkr/TradingMode.java | 260 ++++++++++++++++++ .../enums/CurrencySpecificationFormat.java | 22 ++ .../CurrencyPairSecurityRequestAdapter.java | 30 ++ .../ListingCurrMassiveProcessor.java | 80 ++++++ .../processor/ListingCurrProcessor.java | 9 +- .../src/main/resources/application.properties | 1 + 10 files changed, 489 insertions(+), 9 deletions(-) create mode 100644 clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/deserializers/CurrencySpecificationFormatConverter.java create mode 100644 clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/CurrListingsMassiveRequest.java create mode 100644 clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/TradingMode.java create mode 100644 clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/CurrencySpecificationFormat.java create mode 100644 clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrMassiveProcessor.java diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiSettings.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiSettings.java index 04c9c7e3a..d0a0ecabc 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiSettings.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiSettings.java @@ -3,6 +3,7 @@ package ru.spcex.clearing.gatewayapi.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; +import ru.spcex.clearing.gatewayapi.enums.CurrencySpecificationFormat; import ru.spcex.clearing.platform.messaging.config.element.KafkaConsumerSettings; import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings; import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams; @@ -17,6 +18,7 @@ public class GatewayApiSettings { private InboundServerSettings inboundServer; private InboundExternalServerSettings inboundExternalServer; private String clearingSystem; + private CurrencySpecificationFormat loadCurrencySpecificationFormat; public HazelcastClientParams getHazelcast() { return hazelcast; @@ -65,4 +67,12 @@ public class GatewayApiSettings { public void setClearingSystem(String clearingSystem) { this.clearingSystem = clearingSystem; } + + public CurrencySpecificationFormat getLoadCurrencySpecificationFormat() { + return loadCurrencySpecificationFormat; + } + + public void setLoadCurrencySpecificationFormat(CurrencySpecificationFormat loadCurrencySpecificationFormat) { + this.loadCurrencySpecificationFormat = loadCurrencySpecificationFormat; + } } diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/deserializers/CurrencySpecificationFormatConverter.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/deserializers/CurrencySpecificationFormatConverter.java new file mode 100644 index 000000000..e0a55b487 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/deserializers/CurrencySpecificationFormatConverter.java @@ -0,0 +1,21 @@ +package ru.spcex.clearing.gatewayapi.config.deserializers; + +import java.util.Arrays; +import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; +import ru.spcex.clearing.gatewayapi.enums.CurrencySpecificationFormat; + +@Component +@ConfigurationPropertiesBinding +public class CurrencySpecificationFormatConverter implements Converter { + @Override + public CurrencySpecificationFormat convert(String source) { + String normalized = source.trim(); + + return Arrays.stream(CurrencySpecificationFormat.values()) + .filter(v -> v.name().equalsIgnoreCase(normalized)) + .findFirst() + .orElse(CurrencySpecificationFormat.Massive); + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/GatewayController.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/GatewayController.java index 33690569c..9122ef3e2 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/GatewayController.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/GatewayController.java @@ -1,5 +1,8 @@ package ru.spcex.clearing.gatewayapi.controller; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; @@ -20,9 +23,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; +import ru.spcex.clearing.gatewayapi.config.GatewayApiSettings; 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.CurrListingsMassiveRequest; import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrListingsRequest; import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond.FondDigitalListingsRequest; import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond.FondListingsRequest; @@ -30,11 +35,13 @@ import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.mkr.MMLis import ru.spcex.clearing.gatewayapi.controller.inbound.request.operations.OperationsRequest; import ru.spcex.clearing.gatewayapi.controller.inbound.request.tkr.request.TkrRequest; import ru.spcex.clearing.gatewayapi.controller.inbound.response.CommonResponse; +import ru.spcex.clearing.gatewayapi.enums.CurrencySpecificationFormat; import ru.spcex.clearing.gatewayapi.exception.GatewayException; import ru.spcex.clearing.gatewayapi.service.NotificationService; import ru.spcex.clearing.gatewayapi.service.OperationService; import ru.spcex.clearing.gatewayapi.service.TkrService; import ru.spcex.clearing.gatewayapi.service.processor.CompanyProcessor; +import ru.spcex.clearing.gatewayapi.service.processor.ListingCurrMassiveProcessor; import ru.spcex.clearing.gatewayapi.service.processor.ListingCurrProcessor; import ru.spcex.clearing.gatewayapi.service.processor.ListingDigitalFondProcessor; import ru.spcex.clearing.gatewayapi.service.processor.ListingFondProcessor; @@ -54,10 +61,13 @@ public class GatewayController { private final ListingDigitalFondProcessor listingDigitalFondProcessor; private final ListingMMProcessor listingMMProcessor; private final ListingCurrProcessor listingCurrProcessor; + private final ListingCurrMassiveProcessor listingCurrMassiveProcessor; private final ExecutorService executor; private final OperationService operationService; private final NotificationService notificationService; private final TkrService tkrService; + private final GatewayApiSettings gatewayApiSettings; + private final ObjectMapper objectMapper; private List validTypes = Arrays.asList("DAY_START", "ON_DEMAND"); @@ -67,20 +77,26 @@ public class GatewayController { ListingDigitalFondProcessor listingDigitalFondProcessor, ListingMMProcessor listingMMProcessor, ListingCurrProcessor listingCurrProcessor, + ListingCurrMassiveProcessor listingCurrMassiveProcessor, @Qualifier("gatewayExecutor") ExecutorService executor, OperationService operationService, NotificationService notificationService, - TkrService tkrService) { + TkrService tkrService, + GatewayApiSettings gatewayApiSettings, + ObjectMapper objectMapper) { this.messageResolver = messageResolver; this.companiesProcessor = companiesProcessor; this.listingFondProcessor = listingFondProcessor; this.listingDigitalFondProcessor = listingDigitalFondProcessor; this.listingMMProcessor = listingMMProcessor; this.listingCurrProcessor = listingCurrProcessor; + this.listingCurrMassiveProcessor = listingCurrMassiveProcessor; this.executor = executor; this.operationService = operationService; this.notificationService = notificationService; this.tkrService = tkrService; + this.gatewayApiSettings = gatewayApiSettings; + this.objectMapper = objectMapper; } @@ -168,11 +184,19 @@ public class GatewayController { produces = MediaType.APPLICATION_JSON_VALUE ) @ResponseBody - public CommonResponse listingsCurr(@RequestBody CurrListingsRequest request) { -// request.validate(validTypes, List.of(Section.CURR)); + public CommonResponse listingsCurr(@RequestBody JsonNode jsonRequest) throws JsonProcessingException { + CommonRequest request; + Runnable task; + if (CurrencySpecificationFormat.Massive == gatewayApiSettings.getLoadCurrencySpecificationFormat()) { + request = objectMapper.treeToValue(jsonRequest, CurrListingsMassiveRequest.class); + task = () -> listingCurrMassiveProcessor.process((CurrListingsMassiveRequest) request); + } else { + request = objectMapper.treeToValue(jsonRequest, CurrListingsRequest.class); + task = () -> listingCurrProcessor.process((CurrListingsRequest) request); + } executor.submit(() -> { try { - listingCurrProcessor.process(request); + task.run(); } catch (Throwable e) { log.error("At process /listing_curr has error: {}", ExceptionUtils.getStackTrace(e)); } diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/CurrListingsMassiveRequest.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/CurrListingsMassiveRequest.java new file mode 100644 index 000000000..3145d01f1 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/CurrListingsMassiveRequest.java @@ -0,0 +1,33 @@ +package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import java.util.ArrayList; +import java.util.List; +import ru.spcex.clearing.gatewayapi.controller.inbound.request.CommonRequest; + +public class CurrListingsMassiveRequest extends CommonRequest { + @JsonProperty("currency_specification") + @ApiModelProperty(value = "Список инструментов") + private List currencyInstrumentList = new ArrayList<>(); + + @JsonProperty("trading_mode") + @ApiModelProperty(value = "Список инструментов") + private List tradingModeList = new ArrayList<>(); + + public List getCurrencyInstrumentList() { + return currencyInstrumentList; + } + + public void setCurrencyInstrumentList(List currencyInstrumentList) { + this.currencyInstrumentList = currencyInstrumentList; + } + + public List getTradingModeList() { + return tradingModeList; + } + + public void setTradingModeList(List tradingModeList) { + this.tradingModeList = tradingModeList; + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/TradingMode.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/TradingMode.java new file mode 100644 index 000000000..c750dba6a --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/controller/inbound/request/listing/curr/mkr/TradingMode.java @@ -0,0 +1,260 @@ +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 java.math.BigDecimal; +import java.time.LocalDate; +import java.util.UUID; +import ru.spcex.clearing.gatewayapi.config.deserializers.LocalDateDeserializer; +import ru.spcex.clearing.gatewayapi.controller.inbound.request.WithMapId; + +public class TradingMode extends WithMapId { + @JsonProperty("id") + @ApiModelProperty( + value = "id", + example = "28406b73-7eab-4e21-9295-2ae8ee5c4eb5" + ) + private UUID id; + + @JsonProperty("currency_spec_id") + @ApiModelProperty( + value = "currency_spec_id", + example = "28406b73-7eab-4e21-9295-2ae8ee5c4eb5" + ) + private UUID currencySpecId; + + @JsonProperty("symbol_code") + @ApiModelProperty( + value = "symbol_code", + example = "CNYRUB_TOD_N" + ) + private String symbolCode; + + @JsonProperty("trading_code") + @ApiModelProperty( + value = "symbol_code", + example = "NVAD" + ) + private String tradingCode; + + @JsonProperty("trading_name") + @ApiModelProperty( + value = "trading_name", + example = "Режим адресных сделок без клиринга" + ) + private String tradingName; + + @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("symbol_trading_mode") + @ApiModelProperty( + value = """ + Тип заявок (адресные/безадресные) - данные из системного справочника. + Y – адресные + N – безадресные + """, + example = "N" + ) + private String symbolTradingMode; + + @JsonProperty("settle_code") + @ApiModelProperty( + value = "Код (условия) расчетов: заполняется значением согласно справочнику «Код сектора в клиринговой системе»", + example = "T0" + ) + private String settleCode; + + @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("lot_size") + @ApiModelProperty( + value = "Размер лота", + example = "1" + ) + private BigDecimal lotSize; + + @JsonProperty("number_of_lot_currency") + @ApiModelProperty( + value = "Размер лота", + example = "0" + ) + private BigDecimal numberOfLotCurrency; + + + @JsonProperty("sector") + @ApiModelProperty( + value = "Сектор", + example = "CURR" + ) + private String sector; + + @JsonProperty("start_date") + @JsonDeserialize(using = LocalDateDeserializer.class) + @ApiModelProperty( + value = "Дата начала торгов инструментом", + example = "21.02.2024" + ) + private LocalDate startDate; + + @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 UUID getCurrencySpecId() { + return currencySpecId; + } + + public void setCurrencySpecId(UUID currencySpecId) { + this.currencySpecId = currencySpecId; + } + + public String getSymbolCode() { + return symbolCode; + } + + public void setSymbolCode(String symbolCode) { + this.symbolCode = symbolCode; + } + + public String getTradingCode() { + return tradingCode; + } + + public void setTradingCode(String tradingCode) { + this.tradingCode = tradingCode; + } + + public String getTradingName() { + return tradingName; + } + + public void setTradingName(String tradingName) { + this.tradingName = tradingName; + } + + 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 getSymbolTradingMode() { + return symbolTradingMode; + } + + public void setSymbolTradingMode(String symbolTradingMode) { + this.symbolTradingMode = symbolTradingMode; + } + + public String getSettleCode() { + return settleCode; + } + + public void setSettleCode(String settleCode) { + this.settleCode = settleCode; + } + + 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 BigDecimal getLotSize() { + return lotSize; + } + + public void setLotSize(BigDecimal lotSize) { + this.lotSize = lotSize; + } + + public BigDecimal getNumberOfLotCurrency() { + return numberOfLotCurrency; + } + + public void setNumberOfLotCurrency(BigDecimal numberOfLotCurrency) { + this.numberOfLotCurrency = numberOfLotCurrency; + } + + public String getSector() { + return sector; + } + + public void setSector(String sector) { + this.sector = sector; + } + + public LocalDate getStartDate() { + return startDate; + } + + public void setStartDate(LocalDate startDate) { + this.startDate = startDate; + } + + public String getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } +} \ No newline at end of file diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/CurrencySpecificationFormat.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/CurrencySpecificationFormat.java new file mode 100644 index 000000000..46d942080 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/enums/CurrencySpecificationFormat.java @@ -0,0 +1,22 @@ +package ru.spcex.clearing.gatewayapi.enums; + +import ru.spcex.platform.utils.enumeration.IEnumKey; + +public enum CurrencySpecificationFormat implements IEnumKey { + Single("single"), + Massive("massive"); + + private final String name; + CurrencySpecificationFormat(final String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String getKey() { + return name; + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/adapter/CurrencyPairSecurityRequestAdapter.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/adapter/CurrencyPairSecurityRequestAdapter.java index 1782a637b..4c1bde555 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/adapter/CurrencyPairSecurityRequestAdapter.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/adapter/CurrencyPairSecurityRequestAdapter.java @@ -2,6 +2,7 @@ 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.gatewayapi.controller.inbound.request.listing.curr.mkr.TradingMode; 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; @@ -36,4 +37,33 @@ public class CurrencyPairSecurityRequestAdapter { // req.setUuid(currencyInstrument.getInitiatorId() != null ? currencyInstrument.getInitiatorId().toString() : null); return req; } + + public CurrencyPairSecurityNewGatewayRequest toCurrencySecurityNewRequest(CurrencyInstrument currencyInstrument, + TradingMode tradingMode) { + CurrencyPairSecurityNewGatewayRequest req = new CurrencyPairSecurityNewGatewayRequest(); + + CurrencyPairSecurityNewRequest securityNewRequest = new CurrencyPairSecurityNewRequest(); + securityNewRequest.setInstrumentType(InstrumentType.CRNC.getKey()); + securityNewRequest.setSecuritySymbol(currencyInstrument.getTicker()); + securityNewRequest.setShortName(currencyInstrument.getTicker()); + securityNewRequest.setFullName(currencyInstrument.getName()); + securityNewRequest.setBaseUnitSize(tradingMode.getNumberOfLotCurrency()); + securityNewRequest.setSettlementType(currencyInstrument.getSettleCode()); + securityNewRequest.setClearingOrganization(currencyInstrument.getClearingOrganization()); + securityNewRequest.setWorkflowStatus(currencyInstrument.getWorkflowStatus()); + + // Для listing + securityNewRequest.setMinStep(tradingMode.getMinStep()); + securityNewRequest.setPrecision(tradingMode.getPrecision()); + securityNewRequest.setLotSize(tradingMode.getLotSize()); + req.setTradeMode(tradingMode.getTradingCode()); + + // для currencyPairId + req.setLotCurrencyLetterCode(tradingMode.getLotCurrencyLetterCode()); + req.setMatchedCurrencyLetterCode(tradingMode.getMatchedCurrencyLetterCode()); + + req.setCurrencySecurityNewRequest(securityNewRequest); +// req.setUuid(currencyInstrument.getInitiatorId() != null ? currencyInstrument.getInitiatorId().toString() : null); + return req; + } } diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrMassiveProcessor.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrMassiveProcessor.java new file mode 100644 index 000000000..794d2e056 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrMassiveProcessor.java @@ -0,0 +1,80 @@ +package ru.spcex.clearing.gatewayapi.service.processor; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +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.CurrListingsMassiveRequest; +import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.CurrencyInstrument; +import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.curr.mkr.TradingMode; +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; + +@Service +public class ListingCurrMassiveProcessor { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final CurrencyPairSecurityRequestAdapter currencyPairSecurityRequestAdapter; + private final KafkaSender kafkaSender; + + public ListingCurrMassiveProcessor(CurrencyPairSecurityRequestAdapter currencyPairSecurityRequestAdapter, + KafkaSender kafkaSender) { + this.currencyPairSecurityRequestAdapter = currencyPairSecurityRequestAdapter; + this.kafkaSender = kafkaSender; + } + + public void process(CurrListingsMassiveRequest request) { + List currencyInstrumentList = request.getCurrencyInstrumentList(); + CodeStatusComparator 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); + UUID finalCurrencyInstrumentId = currencyInstrumentId; + Optional tradingMode = request.getTradingModeList().stream() + .filter(tm -> tm.getCurrencySpecId().equals(finalCurrencyInstrumentId)) + .findFirst(); + if (tradingMode.isEmpty()) { + log.warn("Trading mode not found for instrument {}", finalCurrencyInstrumentId); + continue; + } +// if (StringUtils.isEmpty(currencyInstrument.getCode()) || currencyInstrument.getCode().length() < 6) { +// log.warn("Incorrect code : {}, skip record", currencyInstrument.getCode()); +// continue; +// } + CurrencyPairSecurityNewGatewayRequest currencySecurityNewRequest = currencyPairSecurityRequestAdapter + .toCurrencySecurityNewRequest(currencyInstrument, tradingMode.get()); + kafkaSender.sendRequestToQueue(Consts.DESTINATION_GATEWAY_CURRENCY_PAIR_SECURITY, currencySecurityNewRequest); + } catch (Throwable e) { + log.error("currencyInstrumentId={}: {}", currencyInstrumentId, ExceptionUtils.getStackTrace(e)); + } + } + log.debug("process CurrListingsRequest done"); + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrProcessor.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrProcessor.java index 5d50064f2..6aaa4ced4 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrProcessor.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/service/processor/ListingCurrProcessor.java @@ -1,5 +1,8 @@ package ru.spcex.clearing.gatewayapi.service.processor; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,10 +16,6 @@ import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecu 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()); @@ -27,7 +26,7 @@ public class ListingCurrProcessor { public ListingCurrProcessor(CurrencyPairSecurityRequestAdapter currencyPairSecurityRequestAdapter, KafkaSender kafkaSender) { this.currencyPairSecurityRequestAdapter = currencyPairSecurityRequestAdapter; - this.kafkaSender = kafkaSender; + this.kafkaSender = kafkaSender;; } public void process(CurrListingsRequest request) { diff --git a/clearing-parent/gateway-api/src/main/resources/application.properties b/clearing-parent/gateway-api/src/main/resources/application.properties index 3b2df0ad6..72ed80a8e 100644 --- a/clearing-parent/gateway-api/src/main/resources/application.properties +++ b/clearing-parent/gateway-api/src/main/resources/application.properties @@ -26,6 +26,7 @@ gateway-api.kafka-consumer.linger-ms=1 gateway-api.kafka-consumer.buffer-memory=33554432 gateway-api.clearing-system=LCC +gateway-api.load-currency-specification-format=Massive gateway-api.inbound-server.enable-ssl=false gateway-api.inbound-server.host=10.200.200.183