diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiImdgConfig.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiImdgConfig.java new file mode 100644 index 000000000..4e783c353 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/GatewayApiImdgConfig.java @@ -0,0 +1,44 @@ +package ru.spcex.clearing.gatewayapi.config; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; + +@Configuration +public class GatewayApiImdgConfig { + private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) { + ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor(); + if (maxPoolSz > 2) { + pool.setKeepAliveSeconds(60); + pool.setAllowCoreThreadTimeOut(true); + } + pool.setCorePoolSize(maxPoolSz); + pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion); + return pool; + } + + @Bean(name = "taskExecutorHazelcastClientInitializer") + public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() { + return createThreadPoolTaskExecutor(1, true); + } + + @Bean(name = "taskExecutorIdGeneratorAwaiter") + public ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter() { + return createThreadPoolTaskExecutor(1, false); + } + + @Bean + public ImdgProvider imdgProvider( + @Qualifier("taskExecutorHazelcastClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer, + @Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, + GatewayApiSettings settings + ) { + return new HazelcastService(taskExecutorHazelcastClientInitializer, + taskExecutorIdGeneratorAwaiter, + settings.getHazelcast()); + } + +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/PipelineConfiguration.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/PipelineConfiguration.java new file mode 100644 index 000000000..be359e1d7 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/config/PipelineConfiguration.java @@ -0,0 +1,24 @@ +package ru.spcex.clearing.gatewayapi.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.spcex.clearing.gatewayapi.logic.*; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +public class PipelineConfiguration { + + @Bean + public List> listingsRequestPipeline(ImdgProvider imdgProvider) { + List> pipeline = new ArrayList<>(); + pipeline.add(new GroupingSecurityParts()); + pipeline.add(new GroupingCompanyParts()); + pipeline.add(new ValidateIncomeSecurities()); + pipeline.add(new CheckSecurityExist(imdgProvider)); + return pipeline; + } + +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/CheckSecurityExist.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/CheckSecurityExist.java new file mode 100644 index 000000000..7f0e39b0a --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/CheckSecurityExist.java @@ -0,0 +1,59 @@ +package ru.spcex.clearing.gatewayapi.logic; + +import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity; +import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity; +import ru.spcex.clearing.gatewayapi.request.objects.IncomeSecurity; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.InstrumentType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class CheckSecurityExist extends Stage { + private final Imdg equitySecurityImdg; + private final Imdg fixedIncomeSecurityImdg; + + public CheckSecurityExist(ImdgProvider imdgProvider) { + equitySecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class); + fixedIncomeSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class); + } + + @Override + public ProcessResult process(ListingsRequestParam param) { + List securities = param.getSecurities(); + for (IncomeSecurity incomeSecurity : securities) { + String instrumentType = incomeSecurity.getInstrumentType(); + String securitySymbol = incomeSecurity.getSecuritySymbol(); + if (InstrumentType.BOND.equalsByKey(instrumentType)) { + Collection fixedIncomeSecurity = fixedIncomeSecurityImdg.getCollectionObjectsByFieldValues( + Map.of("securitySymbol", securitySymbol) + ); + if (!fixedIncomeSecurity.isEmpty()) { + incomeSecurity.setAlreadyExist(true); + incomeSecurity.setMapId(fixedIncomeSecurity.iterator().next().getId()); + } else { + incomeSecurity.setAlreadyExist(false); + } + } else if (InstrumentType.EQTY.equalsByKey(instrumentType)) { + Collection equitySecurity = equitySecurityImdg.getCollectionObjectsByFieldValues( + Map.of("securitySymbol", securitySymbol) + ); + if (!equitySecurity.isEmpty()) { + incomeSecurity.setAlreadyExist(true); + incomeSecurity.setMapId(equitySecurity.iterator().next().getId()); + } else { + incomeSecurity.setAlreadyExist(false); + } + } + + if (incomeSecurity.isAlreadyExist()) { + // todo after answer + } + + } + return null; + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingCompanyParts.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingCompanyParts.java index ab2edf92b..789389cc8 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingCompanyParts.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingCompanyParts.java @@ -1,28 +1,39 @@ package ru.spcex.clearing.gatewayapi.logic; -import ru.spcex.clearing.gatewayapi.request.ListingsRequest; -import ru.spcex.clearing.gatewayapi.request.objects.IssuerCompany; -import ru.spcex.clearing.gatewayapi.request.objects.IssuerCompanyInfo; -import ru.spcex.clearing.gatewayapi.request.objects.IssuerCompanySymbols; -import ru.spcex.clearing.gatewayapi.request.objects.IssuerContact; +import ru.spcex.clearing.gatewayapi.request.objects.*; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -public class GroupingCompanyParts extends Stage { +public class GroupingCompanyParts extends Stage { @Override - public ProcessResult process(ListingsRequest param) { - List companyList = param.getIssuerCompanyList(); + public ProcessResult process(ListingsRequestParam param) { + List issuerCompanyList = param.getListingsRequest().getIssuerCompanyList(); Map issuerCompanyMap = new HashMap<>(); - for (IssuerCompany issuerCompany : companyList) { + for (IssuerCompany issuerCompany : issuerCompanyList) { if (issuerCompanyMap.put(issuerCompany.getId(), issuerCompany) != null) { throw new IllegalStateException("Duplicate key"); } } - List issuerCompanyInfoList = param.getIssuerCompanyInfoList(); + for (IssuerCompany issuerCompany : issuerCompanyList) { + UUID issuerCompanyId = issuerCompany.getId(); + boolean securityFoundForCompany = false; + for (IncomeSecurity incomeSecurity : param.getSecurities()) { + if (incomeSecurity.getIssuerId().equals(issuerCompanyId)) { + incomeSecurity.getIssuerCompanyList().add(issuerCompany); + securityFoundForCompany = true; + break; + } + } + if (!securityFoundForCompany) { + // todo error: company without security + } + } + + List issuerCompanyInfoList = param.getListingsRequest().getIssuerCompanyInfoList(); for (IssuerCompanyInfo issuerCompanyInfo : issuerCompanyInfoList) { UUID issuerCompanyInfoUUID = issuerCompanyInfo.getCompanyId(); IssuerCompany issuerCompany = issuerCompanyMap.get(issuerCompanyInfoUUID); @@ -33,7 +44,7 @@ public class GroupingCompanyParts extends Stage { issuerCompany.getIssuerCompanyInfoList().add(issuerCompanyInfo); } - List issuerCompanySymbolsList = param.getIssuerCompanySymbolsList(); + List issuerCompanySymbolsList = param.getListingsRequest().getIssuerCompanySymbolsList(); for (IssuerCompanySymbols issuerCompanySymbols : issuerCompanySymbolsList) { UUID issuerCompanySymbolsUUID = issuerCompanySymbols.getCompanyId(); IssuerCompany issuerCompany = issuerCompanyMap.get(issuerCompanySymbolsUUID); @@ -44,7 +55,7 @@ public class GroupingCompanyParts extends Stage { issuerCompany.getIssuerCompanySymbolsList().add(issuerCompanySymbols); } - List issuerContactList = param.getIssuerContactList(); + List issuerContactList = param.getListingsRequest().getIssuerContactList(); for (IssuerContact issuerContact : issuerContactList) { UUID issuerContactUUID = issuerContact.getCompanyId(); IssuerCompany issuerCompany = issuerCompanyMap.get(issuerContactUUID); @@ -55,6 +66,7 @@ public class GroupingCompanyParts extends Stage { issuerCompany.getIssuerContactList().add(issuerContact); } + param.getIssuerCompanyList().addAll(issuerCompanyList); return null; } } diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingSecurityParts.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingSecurityParts.java index d90c60480..c64b4ab76 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingSecurityParts.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/GroupingSecurityParts.java @@ -1,6 +1,5 @@ package ru.spcex.clearing.gatewayapi.logic; -import ru.spcex.clearing.gatewayapi.request.ListingsRequest; import ru.spcex.clearing.gatewayapi.request.objects.*; import java.util.HashMap; @@ -8,57 +7,58 @@ import java.util.List; import java.util.Map; import java.util.UUID; -public class GroupingSecurityParts extends Stage { +public class GroupingSecurityParts extends Stage { @Override - public ProcessResult process(ListingsRequest param) { - List securities = param.getSecurities(); - Map securityMap = new HashMap<>(); - for (Security security : securities) { - if (securityMap.put(security.getId(), security) != null) { + public ProcessResult process(ListingsRequestParam param) { + List securities = param.getListingsRequest().getSecurities(); + Map securityMap = new HashMap<>(); + for (IncomeSecurity incomeSecurity : securities) { + if (securityMap.put(incomeSecurity.getId(), incomeSecurity) != null) { // todo error throw new IllegalStateException("Duplicate key"); } } - List couponSchedules = param.getCouponSchedules(); + List couponSchedules = param.getListingsRequest().getCouponSchedules(); for (CouponSchedule couponSchedule : couponSchedules) { UUID couponScheduleUUID = couponSchedule.getSecurityId(); - Security security = securityMap.get(couponScheduleUUID); - if (security == null) { + IncomeSecurity incomeSecurity = securityMap.get(couponScheduleUUID); + if (incomeSecurity == null) { // todo error continue; } - security.getCouponScheduleList().add(couponSchedule); + incomeSecurity.getCouponScheduleList().add(couponSchedule); } - List currencyList = param.getCurrencies(); + List currencyList = param.getListingsRequest().getCurrencies(); for (Currency currency : currencyList) { UUID currencyUUID = currency.getId(); // todo сделать после выяснения } - List listingList = param.getListingList(); + List listingList = param.getListingsRequest().getListingList(); for (Listing listing : listingList) { UUID listingUUID = listing.getSecurityId(); - Security security = securityMap.get(listingUUID); - if (security == null) { + IncomeSecurity incomeSecurity = securityMap.get(listingUUID); + if (incomeSecurity == null) { // todo error continue; } - security.getListingList().add(listing); + incomeSecurity.getListingList().add(listing); } - List nominalList = param.getNominalList(); + List nominalList = param.getListingsRequest().getNominalList(); for (Nominal nominal : nominalList) { UUID nominalUUID = nominal.getSecurityId(); - Security security = securityMap.get(nominalUUID); - if (security == null) { + IncomeSecurity incomeSecurity = securityMap.get(nominalUUID); + if (incomeSecurity == null) { // todo error continue; } - security.getNominalList().add(nominal); + incomeSecurity.getNominalList().add(nominal); } + param.getSecurities().addAll(securities); return null; } } diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/ListingsRequestParam.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/ListingsRequestParam.java new file mode 100644 index 000000000..935ccab54 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/ListingsRequestParam.java @@ -0,0 +1,31 @@ +package ru.spcex.clearing.gatewayapi.logic; + +import ru.spcex.clearing.gatewayapi.request.ListingsRequest; +import ru.spcex.clearing.gatewayapi.request.objects.IncomeSecurity; +import ru.spcex.clearing.gatewayapi.request.objects.IssuerCompany; + +import java.util.ArrayList; +import java.util.List; + +public class ListingsRequestParam { + private final ListingsRequest listingsRequest; + private final List securities = new ArrayList<>(); + private final List issuerCompanyList = new ArrayList<>(); + + public ListingsRequestParam(ListingsRequest listingsRequest) { + this.listingsRequest = listingsRequest; + } + + + public ListingsRequest getListingsRequest() { + return listingsRequest; + } + + public List getSecurities() { + return securities; + } + + public List getIssuerCompanyList() { + return issuerCompanyList; + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/ValidateIncomeSecurities.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/ValidateIncomeSecurities.java new file mode 100644 index 000000000..d47e15707 --- /dev/null +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/logic/ValidateIncomeSecurities.java @@ -0,0 +1,59 @@ +package ru.spcex.clearing.gatewayapi.logic; + +import ru.spcex.clearing.gatewayapi.request.objects.IncomeSecurity; +import ru.spcex.clearing.gatewayapi.request.objects.Listing; +import ru.spcex.platform.enumeration.BondType; +import ru.spcex.platform.enumeration.InstrumentType; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +import java.util.List; + +public class ValidateIncomeSecurities extends Stage { + + // todo collect errors for response + @Override + public ProcessResult process(ListingsRequestParam param) { + List securities = param.getSecurities(); + + for (IncomeSecurity incomeSecurity : securities) { + + String instrumentTypeStr = incomeSecurity.getInstrumentType(); + InstrumentType instrumentType = IEnumKey.getEnumByKey(InstrumentType.class, instrumentTypeStr); + if (instrumentType != InstrumentType.BOND && instrumentType != InstrumentType.EQTY) { + // todo collect error + continue; + } + + String workflowStatusStr = incomeSecurity.getWorkflowStatus(); + WorkflowStatus workflowStatus = IEnumKey.getEnumByKey(WorkflowStatus.class, workflowStatusStr); + if (workflowStatus == null) { + // todo collect error + continue; + } + + // todo check share_type + + String bondTypeStr = incomeSecurity.getBondType(); + BondType bondType = IEnumKey.getEnumByKey(BondType.class, bondTypeStr); + if (bondType == null) { + // todo collect error + continue; + } + + List listingList = incomeSecurity.getListingList(); + + for (Listing listing : listingList) { + workflowStatusStr = listing.getWorkflowStatus(); + workflowStatus = IEnumKey.getEnumByKey(WorkflowStatus.class, workflowStatusStr); + if (workflowStatus == null) { + // todo collect error + continue; + } + } + + } + + return null; + } +} diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/ListingsRequest.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/ListingsRequest.java index 719d57ebf..eaebabbb1 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/ListingsRequest.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/ListingsRequest.java @@ -46,7 +46,7 @@ public class ListingsRequest { @JsonProperty("security") @ApiModelProperty(value = "Список security") - private List securities; + private List securities; @JsonProperty("coupon_schedule") @ApiModelProperty(value = "Список coupon_schedule") @@ -113,11 +113,11 @@ public class ListingsRequest { this.section = section; } - public List getSecurities() { + public List getSecurities() { return securities; } - public void setSecurities(List securities) { + public void setSecurities(List securities) { this.securities = securities; } diff --git a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/objects/Security.java b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/objects/IncomeSecurity.java similarity index 96% rename from clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/objects/Security.java rename to clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/objects/IncomeSecurity.java index 9a27405e4..443230c06 100644 --- a/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/objects/Security.java +++ b/clearing-parent/gateway-api/src/main/java/ru/spcex/clearing/gatewayapi/request/objects/IncomeSecurity.java @@ -12,7 +12,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -public class Security { +public class IncomeSecurity { @JsonProperty("id") @ApiModelProperty( value = "id (uuid)", @@ -171,6 +171,8 @@ public class Security { ) private BigDecimal couponFrequency; + + @JsonIgnore private List listingList = new ArrayList<>(); @@ -183,6 +185,12 @@ public class Security { @JsonIgnore private List issuerCompanyList = new ArrayList<>(); + @JsonIgnore + private boolean alreadyExist = false; + + @JsonIgnore + private Long mapId; + public UUID getId() { return id; } @@ -358,4 +366,20 @@ public class Security { public void setIssuerCompanyList(List issuerCompanyList) { this.issuerCompanyList = issuerCompanyList; } + + public boolean isAlreadyExist() { + return alreadyExist; + } + + public void setAlreadyExist(boolean alreadyExist) { + this.alreadyExist = alreadyExist; + } + + public Long getMapId() { + return mapId; + } + + public void setMapId(Long mapId) { + this.mapId = mapId; + } } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/BondType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/BondType.java new file mode 100644 index 000000000..423e427aa --- /dev/null +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/BondType.java @@ -0,0 +1,25 @@ +package ru.spcex.platform.enumeration; + +import ru.spcex.platform.utils.enumeration.IEnumKey; + +public enum BondType implements IEnumKey { + Z("Z"), // Дисконтная облигация + F("F"), // Купонная облигация с постоянным купоном + V("V"), // Купонная облигация с переменным купоном + C("C"), // Купонная облигация банка России + E("E"), // Биржевая облигация + I("I"), // Облигация с индексированным номиналом + M("M"), // Облигация с амортизацией долга + ; + + private final String key; + + BondType(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java new file mode 100644 index 000000000..230ad817f --- /dev/null +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java @@ -0,0 +1,21 @@ +package ru.spcex.platform.enumeration; + +import ru.spcex.platform.utils.enumeration.IEnumKey; + +public enum InstrumentType implements IEnumKey { + BOND("BOND"), // Долевые ценные бумаги (акции) + EQTY("EQTY"), // Долговые ценные бумаги (облигации) + ; + + private final String key; + + InstrumentType(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } + +}