add endpoint listing_fond_dc

This commit is contained in:
etreschenkov 2025-05-26 15:26:10 +03:00
parent 6ac5dafa74
commit 52d3653bdd
6 changed files with 742 additions and 0 deletions

View file

@ -24,6 +24,7 @@ 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.FondDigitalListingsRequest;
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;
@ -35,6 +36,7 @@ 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.ListingCurrProcessor;
import ru.spcex.clearing.gatewayapi.service.processor.ListingDigitalFondProcessor;
import ru.spcex.clearing.gatewayapi.service.processor.ListingFondProcessor;
import ru.spcex.clearing.gatewayapi.service.processor.ListingMMProcessor;
import ru.spcex.platform.utils.enumeration.EnumMessage;
@ -49,6 +51,7 @@ public class GatewayController {
private final IMessageResolver messageResolver;
private final CompanyProcessor companiesProcessor;
private final ListingFondProcessor listingFondProcessor;
private final ListingDigitalFondProcessor listingDigitalFondProcessor;
private final ListingMMProcessor listingMMProcessor;
private final ListingCurrProcessor listingCurrProcessor;
private final ExecutorService executor;
@ -61,6 +64,7 @@ public class GatewayController {
public GatewayController(IMessageResolver messageResolver,
CompanyProcessor companiesProcessor,
ListingFondProcessor listingFondProcessor,
ListingDigitalFondProcessor listingDigitalFondProcessor,
ListingMMProcessor listingMMProcessor,
ListingCurrProcessor listingCurrProcessor,
@Qualifier("gatewayExecutor") ExecutorService executor,
@ -70,6 +74,7 @@ public class GatewayController {
this.messageResolver = messageResolver;
this.companiesProcessor = companiesProcessor;
this.listingFondProcessor = listingFondProcessor;
this.listingDigitalFondProcessor = listingDigitalFondProcessor;
this.listingMMProcessor = listingMMProcessor;
this.listingCurrProcessor = listingCurrProcessor;
this.executor = executor;
@ -103,6 +108,28 @@ public class GatewayController {
return createResponse(request, true);
}
@ApiOperation(value = "Экспорт ценных бумаг в Клиринговую систему")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = CommonResponse.class),
@ApiResponse(code = 400, message = "Ошибка валидации", response = CommonResponse.class)
})
@RequestMapping(
path = "/listing_fond_dc",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
@ResponseBody
public CommonResponse listingsFondDigital(@RequestBody FondDigitalListingsRequest request) {
executor.submit(() -> {
try {
listingDigitalFondProcessor.process(request);
} catch (Throwable e) {
log.error("At process /listing_fond has error: {}", ExceptionUtils.getStackTrace(e));
}
});
return createResponse(request, true);
}
@ApiOperation(value = "Экспорт спецификаций биржевых инструментов в Клиринговую систему")
@ApiResponses(value = {

View file

@ -0,0 +1,309 @@
package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.WithMapId;
@ApiModel("Цифровые свидетельства")
public class DigitalCertificate extends WithMapId {
@JsonProperty("id")
@ApiModelProperty(
value = "id (uuid)",
example = "ef47f76c-bcea-11ed-afa1-0242ac120004"
)
private UUID id;
@JsonProperty("depo_dc_id")
@ApiModelProperty(
value = """
«DC», если Общая информация
Вид ценной бумаги = «D Цифровые свидетельства»
""",
example = "BOND"
)
private String depoDcId;
@JsonProperty("instrument_type")
@ApiModelProperty(
value = """
«EQTY», если Общая информация\\Вид ценной бумаги = «E - Долевые ценные бумаги (акции)»
«BOND», если Общая информация\\Вид ценной бумаги = «B - Долговые ценные бумаги (облигации)»
""",
example = "BOND"
)
private String instrumentType;
@JsonProperty("issuer_id")
@ApiModelProperty(
value = "Ссылка на company",
example = "ef47f76c-bcea-11ed-afa1-0242ac120003"
)
private UUID issuerId;
@JsonProperty("short_name")
@ApiModelProperty(
value = "Основные сведения\\Сокращенное наименование на русском языке",
example = "Биржевые облигации ВТБ"
)
private String shortName;
@JsonProperty("full_name")
@ApiModelProperty(
value = "Основные сведения\\Полное наименование на русском языке",
example = """
Биржевые облигации документарные процентные неконвертируемые на предъявителя
с обязательным централизованным хранением серии 001P-06"
"""
)
private String fullName;
@JsonProperty("short_name_eng")
@ApiModelProperty(
value = "Основные сведения\\Сокращенное наименование на английском языке",
example = "VTB exchange-traded bonds"
)
private String shortNameEng;
@JsonProperty("full_name_eng")
@ApiModelProperty(
value = "Основные сведения\\Полное наименование на английском языке",
example = """
Exchange-traded interest-bearing non-convertible bearer bonds
with obligatory centralized storage of series 001P-06
"""
)
private String fullNameEng;
@JsonProperty("number_of_ucp")
@ApiModelProperty(
value = "Общая информация\\Количество УЦП в 1 ЦС",
example = """
1
"""
)
private BigDecimal numberOfUcp;
@JsonProperty("deltaPrice")
@ApiModelProperty(
value = "Общая информация\\Пределы изменения цены",
example = """
1.2
"""
)
private BigDecimal deltaPrice;
@JsonProperty("security_symbol")
@ApiModelProperty(
value = "Общая информация\\Код биржевого инструмента СПВБ",
example = "VTB_001P-06"
)
private String securitySymbol;
@JsonProperty("isin")
@ApiModelProperty(
value = "Общая информация\\ISIN",
example = "RU000A0ZYWY5"
)
private String isin;
@JsonProperty("workflow_status")
@ApiModelProperty(
value = """
«ACTV», если статус ценной бумаги:
Допущена к торгам в режиме размещения
Допущена к торгам в режиме обращения
«BLKD», если статус ценной бумаги:
Не допущена к торгам
Торги временно приостановлены
Выведена из обращения
""",
example = "ACTV"
)
private String workflowStatus;
@JsonProperty("type_code")
@ApiModelProperty(
value = """
«U», если Общая информация
Тип ЦС = «U ЦС на УЦП с фиксированным номиналом»
«X», если Общая информация
Тип ЦС = «X - ЦС на УЦП с индексируемым номиналом»
""",
example = "S"
)
private String typeCode;
@JsonProperty("settlement_organization")
@ApiModelProperty(
value = """
Общая информация\\Наименование раетной организации
""",
example = "S"
)
private String settlementOrganization;
@JsonProperty("settlement_depository")
@ApiModelProperty(
value = """
Общая информация\\Наименование раетного депозитария
""",
example = "S"
)
private String settlementDepository;
@JsonProperty("ucp")
@ApiModelProperty(value = "УЦП")
private DigitalRightsCertificate ucp;
@JsonProperty("nominal")
@ApiModelProperty(value = "Номинал УЦП")
private List<DigitalNominal> nominal;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getDepoDcId() {
return depoDcId;
}
public void setDepoDcId(String depoDcId) {
this.depoDcId = depoDcId;
}
public String getInstrumentType() {
return instrumentType;
}
public void setInstrumentType(String instrumentType) {
this.instrumentType = instrumentType;
}
public UUID getIssuerId() {
return issuerId;
}
public void setIssuerId(UUID issuerId) {
this.issuerId = issuerId;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getShortNameEng() {
return shortNameEng;
}
public void setShortNameEng(String shortNameEng) {
this.shortNameEng = shortNameEng;
}
public String getFullNameEng() {
return fullNameEng;
}
public void setFullNameEng(String fullNameEng) {
this.fullNameEng = fullNameEng;
}
public BigDecimal getNumberOfUcp() {
return numberOfUcp;
}
public void setNumberOfUcp(BigDecimal numberOfUcp) {
this.numberOfUcp = numberOfUcp;
}
public BigDecimal getDeltaPrice() {
return deltaPrice;
}
public void setDeltaPrice(BigDecimal deltaPrice) {
this.deltaPrice = deltaPrice;
}
public String getSecuritySymbol() {
return securitySymbol;
}
public void setSecuritySymbol(String securitySymbol) {
this.securitySymbol = securitySymbol;
}
public String getIsin() {
return isin;
}
public void setIsin(String isin) {
this.isin = isin;
}
public String getWorkflowStatus() {
return workflowStatus;
}
public void setWorkflowStatus(String workflowStatus) {
this.workflowStatus = workflowStatus;
}
public String getTypeCode() {
return typeCode;
}
public void setTypeCode(String typeCode) {
this.typeCode = typeCode;
}
public String getSettlementOrganization() {
return settlementOrganization;
}
public void setSettlementOrganization(String settlementOrganization) {
this.settlementOrganization = settlementOrganization;
}
public String getSettlementDepository() {
return settlementDepository;
}
public void setSettlementDepository(String settlementDepository) {
this.settlementDepository = settlementDepository;
}
public DigitalRightsCertificate getUcp() {
return ucp;
}
public void setUcp(DigitalRightsCertificate ucp) {
this.ucp = ucp;
}
public List<DigitalNominal> getNominal() {
return nominal;
}
public void setNominal(List<DigitalNominal> nominal) {
this.nominal = nominal;
}
}

View file

@ -0,0 +1,90 @@
package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import io.swagger.annotations.ApiModel;
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;
@ApiModel("Номинал УЦП")
public class DigitalNominal {
@JsonProperty("id")
@ApiModelProperty(
value = "Уникальный идентификатор номинала",
example = "3fa85f64-5717-4562-b3fc-2c963f66afa6"
)
private UUID id;
@JsonProperty("index_date")
@JsonDeserialize(using = LocalDateDeserializer.class)
@ApiModelProperty(
value = "Дата индексации номинала в формате ДД.ММ.ГГГГ",
example = "15.07.2023"
)
private LocalDate indexDate;
@JsonProperty("index_rate")
@ApiModelProperty(
value = "Ставка индексации",
example = "7.50"
)
private BigDecimal indexRate;
@JsonProperty("denomination_unit_for_date")
@ApiModelProperty(
value = "Индексируемый номинал на дату",
example = "1050.75"
)
private BigDecimal denominationUnitForDate;
@JsonProperty("index_fact")
@ApiModelProperty(
value = "Фактическая индексация: Y - да, N - нет",
allowableValues = "Y, N",
example = "Y"
)
private String indexFact;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public LocalDate getIndexDate() {
return indexDate;
}
public void setIndexDate(LocalDate indexDate) {
this.indexDate = indexDate;
}
public BigDecimal getIndexRate() {
return indexRate;
}
public void setIndexRate(BigDecimal indexRate) {
this.indexRate = indexRate;
}
public BigDecimal getDenominationUnitForDate() {
return denominationUnitForDate;
}
public void setDenominationUnitForDate(BigDecimal denominationUnitForDate) {
this.denominationUnitForDate = denominationUnitForDate;
}
public String getIndexFact() {
return indexFact;
}
public void setIndexFact(String indexFact) {
this.indexFact = indexFact;
}
}

View file

@ -0,0 +1,221 @@
package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.math.BigInteger;
@ApiModel("Учетные цифровые права (УЦП)")
public class DigitalRightsCertificate {
@JsonProperty("invest_ucp_id")
@ApiModelProperty(
value = "Уникальное условное обозначение УЦП, принадлежность которого удостоверяется ЦС",
example = "UCP-12345"
)
private String investUcpId;
@JsonProperty("company_name")
@ApiModelProperty(
value = "Наименование лица, обязанного по УЦП",
example = "ООО 'Ромашка'"
)
private String companyName;
@JsonProperty("company_inn")
@ApiModelProperty(
value = "ИНН лица, обязанного по УЦП",
example = "7701234567"
)
private String companyInn;
@JsonProperty("invest_company_name")
@ApiModelProperty(
value = "Наименование оператора инвестиционной платформы",
example = "ООО 'ИнвестПлатформа'"
)
private String investCompanyName;
@JsonProperty("invest_company_inn")
@ApiModelProperty(
value = "ИНН оператора инвестиционной платформы",
example = "7707654321"
)
private String investCompanyInn;
@JsonProperty("invest_company_web")
@ApiModelProperty(
value = "Адрес сайта в сети «Интернет» оператора инвестиционной платформы",
example = "https://investplatform.example.com"
)
private String investCompanyWeb;
@JsonProperty("contact_value_web")
@ApiModelProperty(
value = "Ссылка на описание условий инвестиционного предложения на сайте платформы",
example = "https://investplatform.example.com/offer/ucp-12345"
)
private String contactValueWeb;
@JsonProperty("base_activ")
@ApiModelProperty(
value = "Существо права требования (базовый актив)",
example = "Денежное требование по договору займа"
)
private String baseActiv;
@JsonProperty("denomination_unit_base")
@ApiModelProperty(
value = "Номинал на дату размещения инвестиционного предложения (исходный номинал)",
example = "1000.00"
)
private BigDecimal denominationUnitBase;
@JsonProperty("measurement_unit_type")
@ApiModelProperty(
value = "Единица измерения номинала УЦП",
example = "RUB"
)
private String measurementUnitType;
@JsonProperty("indexing_order")
@ApiModelProperty(
value = "Порядок определения номинала УЦП в случае индексации",
example = "Индексация по ставке ЦБ + 2%"
)
private String indexingOrder;
@JsonProperty("total_amount")
@ApiModelProperty(
value = "Общее количество УЦП в выпуске (шт.)",
example = "10000"
)
private BigInteger totalAmount;
@JsonProperty("invest_price")
@ApiModelProperty(
value = "Цена УЦП в инвестиционном предложении (руб.)",
example = "950.50"
)
private BigDecimal investPrice;
@JsonProperty("total_volume")
@ApiModelProperty(
value = "Общий объем выпуска (руб.)",
example = "10000000.00"
)
private BigDecimal totalVolume;
public String getInvestUcpId() {
return investUcpId;
}
public void setInvestUcpId(String investUcpId) {
this.investUcpId = investUcpId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getCompanyInn() {
return companyInn;
}
public void setCompanyInn(String companyInn) {
this.companyInn = companyInn;
}
public String getInvestCompanyName() {
return investCompanyName;
}
public void setInvestCompanyName(String investCompanyName) {
this.investCompanyName = investCompanyName;
}
public String getInvestCompanyInn() {
return investCompanyInn;
}
public void setInvestCompanyInn(String investCompanyInn) {
this.investCompanyInn = investCompanyInn;
}
public String getInvestCompanyWeb() {
return investCompanyWeb;
}
public void setInvestCompanyWeb(String investCompanyWeb) {
this.investCompanyWeb = investCompanyWeb;
}
public String getContactValueWeb() {
return contactValueWeb;
}
public void setContactValueWeb(String contactValueWeb) {
this.contactValueWeb = contactValueWeb;
}
public String getBaseActiv() {
return baseActiv;
}
public void setBaseActiv(String baseActiv) {
this.baseActiv = baseActiv;
}
public BigDecimal getDenominationUnitBase() {
return denominationUnitBase;
}
public void setDenominationUnitBase(BigDecimal denominationUnitBase) {
this.denominationUnitBase = denominationUnitBase;
}
public String getMeasurementUnitType() {
return measurementUnitType;
}
public void setMeasurementUnitType(String measurementUnitType) {
this.measurementUnitType = measurementUnitType;
}
public String getIndexingOrder() {
return indexingOrder;
}
public void setIndexingOrder(String indexingOrder) {
this.indexingOrder = indexingOrder;
}
public BigInteger getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(BigInteger totalAmount) {
this.totalAmount = totalAmount;
}
public BigDecimal getInvestPrice() {
return investPrice;
}
public void setInvestPrice(BigDecimal investPrice) {
this.investPrice = investPrice;
}
public BigDecimal getTotalVolume() {
return totalVolume;
}
public void setTotalVolume(BigDecimal totalVolume) {
this.totalVolume = totalVolume;
}
}

View file

@ -0,0 +1,77 @@
package ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond;
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 FondDigitalListingsRequest extends CommonRequest {
@JsonProperty("company")
@ApiModelProperty(value = "Список компаний эмитентов")
private List<IssuerCompany> issuerCompanyList = new ArrayList<>();
@JsonProperty("company_info")
@ApiModelProperty(value = "Список профилей компаний эмитентов")
private List<IssuerCompanyInfo> issuerCompanyInfoList = new ArrayList<>();
@JsonProperty("company_symbols")
@ApiModelProperty(value = "Список реквизитов компаний эмитентов")
private List<IssuerCompanySymbols> issuerCompanySymbolsList = new ArrayList<>();
@JsonProperty("contact")
@ApiModelProperty(value = "Список контактов компаний эмитентов")
private List<IssuerContact> issuerContactList = new ArrayList<>();
@JsonProperty("dc")
@ApiModelProperty(value = "Список контактов компаний эмитентов")
private List<DigitalCertificate> digitalCertificates = new ArrayList<>();
@JsonProperty("listing")
@ApiModelProperty(value = "Список режимов торгов")
private List<IncomeListing> listingList = new ArrayList<>();
public List<IssuerCompany> getIssuerCompanyList() {
return issuerCompanyList;
}
public void setIssuerCompanyList(List<IssuerCompany> issuerCompanyList) {
this.issuerCompanyList = issuerCompanyList;
}
public List<IssuerCompanyInfo> getIssuerCompanyInfoList() {
return issuerCompanyInfoList;
}
public void setIssuerCompanyInfoList(List<IssuerCompanyInfo> issuerCompanyInfoList) {
this.issuerCompanyInfoList = issuerCompanyInfoList;
}
public List<IssuerCompanySymbols> getIssuerCompanySymbolsList() {
return issuerCompanySymbolsList;
}
public void setIssuerCompanySymbolsList(List<IssuerCompanySymbols> issuerCompanySymbolsList) {
this.issuerCompanySymbolsList = issuerCompanySymbolsList;
}
public List<IssuerContact> getIssuerContactList() {
return issuerContactList;
}
public void setIssuerContactList(List<IssuerContact> issuerContactList) {
this.issuerContactList = issuerContactList;
}
public List<DigitalCertificate> getDigitalCertificates() {
return digitalCertificates;
}
public void setDigitalCertificates(List<DigitalCertificate> digitalCertificates) {
this.digitalCertificates = digitalCertificates;
}
public List<IncomeListing> getListingList() {
return listingList;
}
public void setListingList(List<IncomeListing> listingList) {
this.listingList = listingList;
}
}

View file

@ -0,0 +1,18 @@
package ru.spcex.clearing.gatewayapi.service.processor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.listing.fond.FondDigitalListingsRequest;
@Service
public class ListingDigitalFondProcessor {
private final Logger log = LoggerFactory.getLogger(getClass());
public ListingDigitalFondProcessor() {
}
public void process(FondDigitalListingsRequest request) {
log.debug("process FondListingsRequest done");
}
}