This commit is contained in:
akulikov 2023-05-31 14:09:22 +03:00
parent 9360387bd0
commit 93fb2eaa07
4 changed files with 500 additions and 5 deletions

View file

@ -117,7 +117,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
kafkaSender.sendRequestToQueue(Consts.DESTINATION_FIXED_INCOME_SECURITY_UPDATE, fixedIncomeSecurityUpdateRequest);
}
} else {
if (security.isAlreadyExist()) {
if (!security.isAlreadyExist()) {
EquitySecurityNewRequest equitySecurityNewRequest = new EquitySecurityNewRequest();
equitySecurityNewRequest.setSecuritySymbol(security.getSecuritySymbol());
equitySecurityNewRequest.setShortName(security.getShortName());
@ -129,7 +129,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
equitySecurityNewRequest.setFullNameEng(security.getFullNameEng());
equitySecurityNewRequest.setWorkflowStatus(security.getWorkflowStatus());
equitySecurityNewRequest.setInstrumentType(security.getInstrumentType());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_FIXED_INCOME_SECURITY_NEW, equitySecurityNewRequest);
kafkaSender.sendToQueueWaitForAnswer(Consts.DESTINATION_EQUITY_SECURITY_NEW, equitySecurityNewRequest);
} else {
EquitySecurityUpdateRequest equitySecurityUpdateRequest = new EquitySecurityUpdateRequest();
equitySecurityUpdateRequest.setId(security.getMapId());
@ -143,7 +143,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
equitySecurityUpdateRequest.setFullNameEng(security.getFullNameEng());
equitySecurityUpdateRequest.setWorkflowStatus(security.getWorkflowStatus());
equitySecurityUpdateRequest.setInstrumentType(security.getInstrumentType());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_FIXED_INCOME_SECURITY_UPDATE, equitySecurityUpdateRequest);
kafkaSender.sendRequestToQueue(Consts.DESTINATION_EQUITY_SECURITY_UPDATE, equitySecurityUpdateRequest);
}
}
@ -151,7 +151,6 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
Map<String, String> predicate = Map.of(
"instrumentType", security.getInstrumentType(),
"securitySymbol", security.getSecuritySymbol(),
"bondType", security.getBondType(),
"workflowStatus", security.getWorkflowStatus(),
"shortName", security.getShortName()
);
@ -163,7 +162,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
if (equitySecurity != null) security.setMapId(equitySecurity.getId());
}
if (security.getMapId() == null) {
log.warn("Can't insert security (UUID {}), skipped", security.getId());
log.warn("Can't insert security (id {}), skipped", security.getId());
security.setInvalidData(true);
continue;
}

View file

@ -0,0 +1,27 @@
package ru.spcex.clearing.gatewayapi.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.spcex.clearing.test.json.JsonUtil;
@Configuration
public class TestConfiguration {
@Bean("testObjectMapper")
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
return JsonUtil.JacksonObjectMapper.getMapper();
}
}

View file

@ -0,0 +1,208 @@
package ru.spcex.clearing.gatewayapi.logic.listings_fond;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity;
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
import ru.spcex.clearing.gatewayapi.config.ProcessorConfiguration;
import ru.spcex.clearing.gatewayapi.config.TestConfiguration;
import ru.spcex.clearing.gatewayapi.logic.ProcessResult;
import ru.spcex.clearing.gatewayapi.logic.Processor;
import ru.spcex.clearing.gatewayapi.logic.Stage;
import ru.spcex.clearing.gatewayapi.request.FondListingsRequest;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanyNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.EquitySecurityNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeSecurityNewRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.test.config.ImdgTestConfig;
import ru.spcex.clearing.test.config.KafkaTestConfig;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.enumeration.InstrumentType;
import ru.spcex.platform.enumeration.WorkflowStatus;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// Суть теста: прогоняем через pipeline запрос и в mockSender ловим переданные company и security сервисам запросы
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {
ProcessorConfiguration.class,
TestConfiguration.class,
ImdgTestConfig.class,
KafkaTestConfig.class})
class ListingFondRequestTest implements InitializingBean {
// В этот объект будут помещаться отправленные сообщения
final Map<String, List<Object>> sentMessages = new HashMap<>();
@Autowired
@Qualifier("testObjectMapper")
ObjectMapper objectMapper;
@Autowired
Processor<FondListingsRequestParam> processor;
@Autowired
ImdgProvider imdgProvider;
KafkaSender mockSender = Mockito.mock(KafkaSender.class);
Imdg<Company> companyImdg;
Imdg<CompanySymbols> companySymbolsImdg;
Imdg<FixedIncomeSecurity> fixedIncomeSecurityImdg;
Imdg<EquitySecurity> equitySecurityImdg;
@Test
public void test() throws IOException {
File requestFile = new File(getClass().getClassLoader().getResource("requests/testFondSecuritiesRequest_1.json").getFile());
FondListingsRequest fondListingsRequest = objectMapper.readValue(requestFile, FondListingsRequest.class);
FondListingsRequestParam param = new FondListingsRequestParam(fondListingsRequest);
ProcessResult result = processor.process(param);
// Проверяем только количество запросов, поскольку выполнение этих запросов зависит от security и company модулей
Assertions.assertNull(result.getError());
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_COMPANY_NEW).size(), 2);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_COMPANY_UPDATE).size(), 2);
Assertions.assertEquals(sentMessages.get(Consts.LISTING_NEW).size(), 4);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_COUPON_PERIOD_NEW).size(), 1);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_COMPANY_SYMBOL_NEW).size(), 4);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_CONTACT_NEW).size(), 2);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_FIXED_INCOME_SECURITY_NEW).size(), 1);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_FIXED_INCOME_SECURITY_UPDATE).size(), 1);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_EQUITY_SECURITY_NEW).size(), 1);
Assertions.assertEquals(sentMessages.get(Consts.DESTINATION_EQUITY_SECURITY_UPDATE).size(), 1);
}
@Override
public void afterPropertiesSet() throws Exception {
companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
fixedIncomeSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class);
equitySecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class);
Company existCompany1 = new Company();
CompanySymbols existCompany1Symbols = new CompanySymbols();
Long company1Id = companyImdg.insert(existCompany1);
existCompany1Symbols.setCompanySymbol(CompanySymbol.UUID.getKey());
existCompany1Symbols.setCompanySymbolValue("ef47f76c-bcea-11ed-afa1-0242ac120000");
existCompany1Symbols.setCompanyId(company1Id);
companySymbolsImdg.insert(existCompany1Symbols);
Company existCompany2 = new Company();
CompanySymbols existCompany2Symbols = new CompanySymbols();
Long company2Id = companyImdg.insert(existCompany2);
existCompany2Symbols.setCompanySymbol(CompanySymbol.UUID.getKey());
existCompany2Symbols.setCompanySymbolValue("ef47f76c-bcea-11ed-afa1-0242ac120001");
existCompany2Symbols.setCompanyId(company2Id);
companySymbolsImdg.insert(existCompany2Symbols);
/*
"instrumentType", security.getInstrumentType(),
"securitySymbol", security.getSecuritySymbol(),
"workflowStatus", security.getWorkflowStatus(),
"shortName", security.getShortName()
*/
FixedIncomeSecurity fixedIncomeSecurity_1 = new FixedIncomeSecurity();
fixedIncomeSecurity_1.setInstrumentType(InstrumentType.BOND.getKey());
fixedIncomeSecurity_1.setSecuritySymbol("VTB_001P-06 TEST 3");
fixedIncomeSecurity_1.setWorkflowStatus(WorkflowStatus.Active.getKey());
fixedIncomeSecurity_1.setShortName("Биржевые облигации ВТБ TEST 3");
fixedIncomeSecurityImdg.insert(fixedIncomeSecurity_1);
EquitySecurity equitySecurity_1 = new EquitySecurity();
equitySecurity_1.setInstrumentType(InstrumentType.EQTY.getKey());
equitySecurity_1.setSecuritySymbol("VTB_001P-06 TEST 4");
equitySecurity_1.setWorkflowStatus(WorkflowStatus.Active.getKey());
equitySecurity_1.setShortName("Биржевые облигации ВТБ TEST 4");
equitySecurityImdg.insert(equitySecurity_1);
// мок kafkaSender, чтобы он лишь сохранял в мапу переданные аргументы
Mockito
.when(mockSender.sendRequestToQueue(Mockito.any(), Mockito.any()))
.thenAnswer(
invocation -> {
String destination = invocation.getArgument(0);
Object message = invocation.getArgument(1);
List<Object> currentMessageList = sentMessages.computeIfAbsent(destination, k -> new ArrayList<>());
currentMessageList.add(message);
if (message instanceof CompanyNewRequest companyNewRequest) {
Company company = new Company();
company.setFullName(companyNewRequest.getFullName());
company.setShortName(companyNewRequest.getShortName());
company.setWorkflowStatus(companyNewRequest.getWorkflowStatus());
Long companyId = companyImdg.insert(company);
return companyId;
}
return 0L;
}
);
Mockito
.when(mockSender.sendToQueueWaitForAnswer(Mockito.any(), Mockito.any()))
.thenAnswer(
invocation -> {
String destination = invocation.getArgument(0);
Object invocationArgument = invocation.getArgument(1);
if (invocationArgument instanceof CompanyNewRequest newRequest) {
Company company = new Company();
company.setShortName(newRequest.getShortName());
company.setFullName(newRequest.getFullName());
company.setWorkflowStatus(newRequest.getWorkflowStatus());
companyImdg.insert(company);
}
if (invocationArgument instanceof FixedIncomeSecurityNewRequest newRequest) {
FixedIncomeSecurity fixedIncomeSecurity = new FixedIncomeSecurity();
fixedIncomeSecurity.setInstrumentType(newRequest.getInstrumentType());
fixedIncomeSecurity.setSecuritySymbol(newRequest.getSecuritySymbol());
fixedIncomeSecurity.setWorkflowStatus(newRequest.getWorkflowStatus());
fixedIncomeSecurity.setShortName(newRequest.getShortName());
fixedIncomeSecurityImdg.insert(fixedIncomeSecurity);
}
if (invocationArgument instanceof EquitySecurityNewRequest newRequest) {
EquitySecurity equitySecurity = new EquitySecurity();
equitySecurity.setInstrumentType(newRequest.getInstrumentType());
equitySecurity.setSecuritySymbol(newRequest.getSecuritySymbol());
equitySecurity.setWorkflowStatus(newRequest.getWorkflowStatus());
equitySecurity.setShortName(newRequest.getShortName());
equitySecurityImdg.insert(equitySecurity);
}
List<Object> currentMessageList = sentMessages.computeIfAbsent(destination, k -> new ArrayList<>());
currentMessageList.add(invocationArgument);
return "ok";
}
);
// в pipeline для processor заменяем стадии с отправкой сообщений
List<Stage<FondListingsRequestParam>> pipeline = processor.getPipeline();
for (Stage<FondListingsRequestParam> stage : pipeline) {
if (stage instanceof SendMessageToSecurityServiceWithFondSecurities) {
int index = pipeline.indexOf(stage);
Stage<FondListingsRequestParam> mockedStage = new SendMessageToSecurityServiceWithFondSecurities(mockSender, imdgProvider);
pipeline.set(index, mockedStage);
}
if (stage instanceof SendMessageToCompanyServiceWithIssuerCompanies) {
int index = pipeline.indexOf(stage);
Stage<FondListingsRequestParam> mockedStage = new SendMessageToCompanyServiceWithIssuerCompanies(mockSender, imdgProvider);
pipeline.set(index, mockedStage);
}
}
}
}

View file

@ -0,0 +1,261 @@
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"type": "DAY_START",
"section": "FOND",
"datetime": "07.03.2023 18:24:36:123",
"company": [
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"short_name": "ТК1",
"full_name": "Тестовая компания 1",
"workflow_status": "ACTV"
},
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"short_name": "ТК2",
"full_name": "Тестовая компания 2",
"workflow_status": "ACTV"
}
],
"company_info": [
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"country_code": "RUS",
"legal_kind": "JURD",
"organization_type": "CRED",
"residence": "RUS",
"short_name_eng": "VTB Bank (PJSC)",
"full_name_eng": "TEST COMPANY 1"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"country_code": "RUS",
"legal_kind": "JURD",
"organization_type": "CRED",
"residence": "RUS",
"short_name_eng": "VTB Bank (PJSC)",
"full_name_eng": "TEST COMPANY 2"
}
],
"company_symbols": [
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"company_symbol": "INN",
"company_symbol_value": "7702070139"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"company_symbol": "INN",
"company_symbol_value": "7702070132"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"company_symbol": "OGRN",
"company_symbol_value": "7702070139"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"company_symbol": "OGRN",
"company_symbol_value": "7702070132"
}
],
"contact": [
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"contact_type": "ADRS",
"contact_value": "191144, Дегтярный переулок, д.11, лит. А, г. Санкт-Петербург,"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"contact_type": "POST",
"contact_value": "109147, Ул. Воронцовская, д. 43, стр.1, г. Москва, Россия"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"contact_type": "ADRS",
"contact_value": "191144, Дегтярный переулок, д.11, лит. А, г. Санкт-Петербург,"
},
{
"company_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"contact_type": "POST",
"contact_value": "109147, Ул. Воронцовская, д. 43, стр.1, г. Москва, Россия"
}
],
"security": [
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120004",
"instrument_type": "BOND",
"issuer_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"short_name": "Биржевые облигации ВТБ TEST 1",
"full_name": "Биржевые облигации документарные процентные неконвертируемые на предъявителя с обязательным централизованным хранением серии 001P-06 TEST 1",
"short_name_eng": "VTB exchange-traded bonds TEST 1",
"full_name_eng": "Exchange-traded interest-bearing non-convertible bearer bonds with obligatory centralized storage of series 001P-06 TEST 1",
"security_symbol": "VTB_001P-06 TEST 1",
"isin": "RU000A0ZYWY5",
"workflow_status": "ACTV",
"bond_type": "F",
"maturity_date": "12.08.2023",
"nominal_value": 1000,
"nominal_for_date": 1100,
"nominal_currency": "RUB",
"coupon_type": "FIX",
"coupon_frequency": 4
},
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"instrument_type": "EQTY",
"issuer_id": "ef47f76c-bcea-11ed-afa1-0242ac120002",
"short_name": "Биржевые облигации ВТБ TEST 2",
"share_type": "S",
"full_name": "Биржевые облигации документарные процентные неконвертируемые на предъявителя с обязательным централизованным хранением серии 001P-06 TEST 2",
"short_name_eng": "VTB exchange-traded bonds TEST 2",
"full_name_eng": "Exchange-traded interest-bearing non-convertible bearer bonds with obligatory centralized storage of series 001P-06 TEST 2",
"security_symbol": "VTB_001P-06 TEST 2",
"isin": "RU000A0ZYWY5",
"workflow_status": "ACTV",
"bond_type": "F",
"maturity_date": "12.08.2023",
"nominal_value": 1000,
"nominal_for_date": 1100,
"nominal_currency": "RUB",
"coupon_type": "FIX",
"coupon_frequency": 4
},
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120001",
"instrument_type": "BOND",
"issuer_id": "ef47f76c-bcea-11ed-afa1-0242ac120001",
"short_name": "Биржевые облигации ВТБ TEST 3",
"full_name": "Биржевые облигации документарные процентные неконвертируемые на предъявителя с обязательным централизованным хранением серии 001P-06 TEST 3",
"short_name_eng": "VTB exchange-traded bonds TEST 3",
"full_name_eng": "Exchange-traded interest-bearing non-convertible bearer bonds with obligatory centralized storage of series 001P-06 TEST 3",
"security_symbol": "VTB_001P-06 TEST 3",
"isin": "RU000A0ZYWY5",
"workflow_status": "ACTV",
"bond_type": "F",
"maturity_date": "12.08.2023",
"nominal_value": 1000,
"nominal_for_date": 1100,
"nominal_currency": "RUB",
"coupon_type": "FIX",
"coupon_frequency": 4
},
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120000",
"instrument_type": "EQTY",
"share_type": "P",
"issuer_id": "ef47f76c-bcea-11ed-afa1-0242ac120000",
"short_name": "Биржевые облигации ВТБ TEST 4",
"full_name": "Биржевые облигации документарные процентные неконвертируемые на предъявителя с обязательным централизованным хранением серии 001P-06 TEST 4",
"short_name_eng": "VTB exchange-traded bonds TEST 4",
"full_name_eng": "Exchange-traded interest-bearing non-convertible bearer bonds with obligatory centralized storage of series 001P-06 TEST 4",
"security_symbol": "VTB_001P-06 TEST 4",
"isin": "RU000A0ZYWY5",
"workflow_status": "ACTV",
"bond_type": "F",
"maturity_date": "12.08.2023",
"nominal_value": 1000,
"nominal_for_date": 1100,
"nominal_currency": "RUB",
"coupon_type": "FIX",
"coupon_frequency": 4
}
],
"coupon_schedule": [
{
"security_id": "ef47f76c-bcea-11ed-afa1-0242ac120004",
"period_start_date": "30.08.2023",
"period_end_date": "28.02.2024",
"coupon_rate": 7.25,
"coupon_number": 12,
"coupon_currency": "RUB",
"accrued_coupon": 36.15,
"is_deleted": false
}
],
"currency": [
{
"id": "ef47f76c-bcea-11ed-afa1-0242ac120005",
"currency_code": "RUB",
"currency_code_numeric": "643"
}
],
"listing": [
{
"security_id": "ef47f76c-bcea-11ed-afa1-0242ac120004",
"lot_size": 10,
"symbol_code": "VTB_001P-06",
"symbol_name": "Биржевые облигации ВТБ",
"trading_currency": "RUB",
"workflow_status": "ACTV",
"precision": 1,
"min_step": 6,
"settle_code": "T0",
"settle_days": 0,
"name": "Обл. с ПК - Торги ",
"code": "UBVC",
"sector": "FOND",
"start_date": "01.03.2023",
"end_date": "01.03.2029"
},
{
"security_id": "ef47f76c-bcea-11ed-afa1-0242ac120003",
"lot_size": 10,
"symbol_code": "VTB_001P-06",
"symbol_name": "Биржевые облигации ВТБ",
"trading_currency": "RUB",
"workflow_status": "ACTV",
"precision": 1,
"min_step": 6,
"settle_code": "T0",
"settle_days": 0,
"name": "Обл. с ПК - Торги ",
"code": "UBVC",
"sector": "FOND",
"start_date": "01.03.2023",
"end_date": "01.03.2029"
},
{
"security_id": "ef47f76c-bcea-11ed-afa1-0242ac120001",
"lot_size": 10,
"symbol_code": "VTB_001P-06",
"symbol_name": "Биржевые облигации ВТБ",
"trading_currency": "RUB",
"workflow_status": "ACTV",
"precision": 1,
"min_step": 6,
"settle_code": "T0",
"settle_days": 0,
"name": "Обл. с ПК - Торги ",
"code": "UBVC",
"sector": "FOND",
"start_date": "01.03.2023",
"end_date": "01.03.2029"
},
{
"security_id": "ef47f76c-bcea-11ed-afa1-0242ac120000",
"lot_size": 10,
"symbol_code": "VTB_001P-06",
"symbol_name": "Биржевые облигации ВТБ",
"trading_currency": "RUB",
"workflow_status": "ACTV",
"precision": 1,
"min_step": 6,
"settle_code": "T0",
"settle_days": 0,
"name": "Обл. с ПК - Торги ",
"code": "UBVC",
"sector": "FOND",
"start_date": "01.03.2023",
"end_date": "01.03.2029"
}
],
"nominal": [
{
"security_id": "ef47f76c-bcea-11ed-afa1-0242ac120004",
"nominal": 1000,
"date": "09.03.2023",
"is_deleted": false
}
]
}