diff --git a/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/AbstractControllerTest.java b/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/AbstractControllerTest.java index 367f97bff..e28e28add 100644 --- a/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/AbstractControllerTest.java +++ b/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/AbstractControllerTest.java @@ -26,7 +26,6 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.filter.CharacterEncodingFilter; -import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.user.User; import ru.spcex.clearing.backendapi.controller.config.*; import ru.spcex.clearing.backendapi.controller.queue.account.*; @@ -60,7 +59,6 @@ import ru.spcex.clearing.test.TestUtils; import ru.spcex.clearing.test.json.MatcherFactoryWithJson; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.imdg.api.Imdg; -import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; import ru.spcex.platform.utils.enumeration.IMessageResolver; @@ -158,6 +156,7 @@ import static ru.spcex.clearing.test.json.MatcherFactoryWithJson.usingIgnoringFi WebSecurityTestConfigurer.class, MessagesTestConfig.class, Jackson2HttpConverterTestConfig.class}) +//todo может быть указать пакедж а не список контроллеров @ExtendWith(SpringExtension.class) @WebMvcTest //@TestPropertySource(properties = "spring.config.location=D:/repo/mfd/clearing/clearing-parent/backend-api/src/main/resources/") diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/models/RegistryInfo.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/models/RegistryInfo.java deleted file mode 100644 index 1c618492f..000000000 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/models/RegistryInfo.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.spcex.clearing.models; - -import ru.spcex.platform.enumeration.RegistryCapacity; -import ru.spcex.platform.enumeration.RegistryDesignation; -import ru.spcex.platform.enumeration.RegistryInstrumentType; -import ru.spcex.platform.enumeration.RegistryUnit; - -public record RegistryInfo(RegistryDesignation registryDesignation, - RegistryInstrumentType registryInstrumentType, - RegistryCapacity registryCapacity, - RegistryUnit registryUnit) { - - public String buildSqlCondition(){ - return ""; - } -} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/models/RegistryTradingParams.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/models/RegistryTradingParams.java new file mode 100644 index 000000000..240ae96da --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/models/RegistryTradingParams.java @@ -0,0 +1,14 @@ +package ru.spcex.clearing.models; + +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryUnit; + +public record RegistryTradingParams(RegistryDesignation registryDesignation, + RegistryInstrumentType registryInstrumentType, + RegistryCapacity registryCapacity, + RegistryUnit registryUnit) { + + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java index f6ab3915f..c9b5e79cc 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java @@ -6,7 +6,7 @@ import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.models.RegistryInfo; +import ru.spcex.clearing.models.RegistryTradingParams; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.CreateRegistryRequest; import ru.spcex.platform.enumeration.*; import ru.spcex.platform.imdg.api.Imdg; @@ -42,7 +42,7 @@ public class RegistryService { log.trace("Found tradingClearingRegistry with id: {}", tcrByCompanyId.getId()); Registry registry = new Registry(); tcrByCompanyId.getTradingClearingRegistryType(); - RegistryInfo registryInfo = createRegistryInfoByType(tcrByCompanyId.getTradingClearingRegistryType()); + RegistryTradingParams registryInfo = createRegistryInfoByType(tcrByCompanyId.getTradingClearingRegistryType()); registry.setRegistryDesignation(registryInfo.registryDesignation().getKey()); registry.setRegistryInstrumentType(registryInfo.registryInstrumentType().getKey()); registry.setRegistryCapacity(registryInfo.registryCapacity().getKey()); @@ -55,20 +55,20 @@ public class RegistryService { } - private RegistryInfo createRegistryInfoByType(String type){ + private RegistryTradingParams createRegistryInfoByType(String type){ TradingClearingRegistryType registryType = IEnumKey.getEnumByKey(TradingClearingRegistryType.class, type); - RegistryInfo registryInfo = null; + RegistryTradingParams registryInfo = null; //todo спросить про дубль C и T switch (registryType){ - case Owner_A -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T); - case Client_B -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.T); - case Trustee_C, DepoOfShares_T -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.T); - case TrusteeManager_D -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.A); - case Issuer_E -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.E, RegistryUnit.R); - case ToThePlacementOrRedeem_Z -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.Z, RegistryUnit.R); - case DepoBond_H -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.R); - case DepoOfTrustedBond_N -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.R); - case DepoOfTrustedShares_S -> registryInfo = new RegistryInfo(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.T); + case Owner_A -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T); + case Client_B -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.T); + case Trustee_C, DepoOfShares_T -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.T); + case TrusteeManager_D -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.A); + case Issuer_E -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.E, RegistryUnit.R); + case ToThePlacementOrRedeem_Z -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.Z, RegistryUnit.R); + case DepoBond_H -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.R); + case DepoOfTrustedBond_N -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.R); + case DepoOfTrustedShares_S -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.T); } return registryInfo; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilder.java new file mode 100644 index 000000000..bf7fd8567 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilder.java @@ -0,0 +1,58 @@ +package ru.spcex.clearing.service.builder.sql; + +import ru.spcex.clearing.models.RegistryTradingParams; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class RegistryCodeSqlBuilder { + + private List registryTradingParams = new ArrayList<>(); + + public static RegistryCodeSqlBuilder getInstance(RegistryTradingParams... tradingParams) { + return new RegistryCodeSqlBuilder(Arrays.asList(tradingParams)); + } + + private RegistryCodeSqlBuilder(List tradingParams) { + this.registryTradingParams = tradingParams; + } + + public String build() { + List conditions = new ArrayList<>(); + for (RegistryTradingParams tradingParams : this.registryTradingParams) { + StringBuilder condition = new StringBuilder(); + boolean wasAddedCondition = false; + if (tradingParams.registryDesignation() != null) { + condition.append(String.format("registryDesignation = '%s'", tradingParams.registryDesignation().getKey())); + wasAddedCondition = true; + } + if (wasAddedCondition) { + condition.append(" and "); + wasAddedCondition = false; + } + if (tradingParams.registryInstrumentType() != null) { + condition.append(String.format("registryInstrumentType = '%s'", tradingParams.registryInstrumentType().getKey())); + wasAddedCondition = true; + } + if (wasAddedCondition) { + condition.append(" and "); + wasAddedCondition = false; + } + if (tradingParams.registryCapacity() != null) { + condition.append(String.format("registryCapacity = '%s'", tradingParams.registryCapacity().getKey())); + wasAddedCondition = true; + } + if (wasAddedCondition) { + condition.append(" and "); + wasAddedCondition = false; + } + if (tradingParams.registryUnit() != null) { + condition.append(String.format("registryUnit = '%s'", tradingParams.registryUnit().getKey())); + } + conditions.add(condition); + } + return conditions.stream().collect(Collectors.joining(") or (", "(", ")")); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java new file mode 100644 index 000000000..70b47b67f --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java @@ -0,0 +1,127 @@ +package ru.spcex.clearing.session.stage.impl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.error.ClearingError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.session.stage.ISessionStage; +import ru.spcex.clearing.session.stage.StageResult; +import ru.spcex.clearing.session.stage.Task; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumKey; +import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class FormingPaymentInstruction implements ISessionStage { + private final Logger log = LoggerFactory.getLogger(getClass()); + //todo remove (set all in single method setImdg(provider -> setImdg1();setIdGenerator();...) + private ImdgProvider imdgProvider; + private ImdgId idGenerator; + private Imdg registryImdg; + private Imdg paymentInstructionImdg; + private KafkaSender kafkaSender; + private final IMessageResolver msgResolver = new SimpleMessageResolver(); + + @Autowired + public FormingPaymentInstruction(ImdgProvider imdgProvider) { + this.imdgProvider = imdgProvider; + this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + } + + @Override + public StageResult submit(Task task) { + InspectionPoolPayload payload = (InspectionPoolPayload) task.getData(); + switch (task.getTaskType()) { + case InclusionToPool -> { + return inspectionPool(payload.getProcessedCompanyId()); + } + default -> { + throw new IllegalStateException("Unknown task type: " + task.getTaskType()); + } + } + } + + + private StageResult inspectionPool(Long processedCompanyId) { + String sqlCondition = String.format("registryDesignation in ('%s', '%s') and " + + "registryInstrumentType in ('%s', '%s') and " + + "registryUnit = '%s' and " + + "registryStatus = '%s' and " + + "settlementDate = '%s'", + RegistryDesignation.O.getKey(), RegistryDesignation.T.getKey(), + RegistryInstrumentType.S.getKey(), RegistryInstrumentType.M.getKey(), + RegistryUnit.T.getKey(), + "POOL"); + + Collection obligations = registryImdg.getCollectionObjectsBySQL(sqlCondition); + Map>> registryByGroupIdAndCompanyId = obligations.stream(). + collect(Collectors.groupingBy(Registry::getGroupId, Collectors.groupingBy(Registry::getCompanyId))); + + List insecurityGroups = new ArrayList<>(); + for (Registry currentRegistry : obligations) { + if (insecurityGroups.contains(currentRegistry.getGroupId())) { + log.debug("Skip insecurity groupId: {}", currentRegistry.getGroupId()); + continue; + } + if (IEnumKey.getEnumByKey(RegistryDesignation.class, currentRegistry.getRegistryDesignation()) == RegistryDesignation.A) { + String sqlCounterRegistryCondition = String.format("registryDesignation = '%s' and " + + "registryInstrumentType in ('%s', '%s') and " + + "registryUnit = '%s' and " + + "tradingClearingRegistryId = '%s' and " + + "companyId = '%s' and ", + RegistryDesignation.A, + RegistryInstrumentType.S.getKey(), RegistryInstrumentType.M.getKey(), + RegistryUnit.F.getKey(), + currentRegistry.getTradingClearingRegistryId(), + currentRegistry.getCompanyId()); + Registry counterRegistry = registryImdg.getSingleObjectBySQL(sqlCounterRegistryCondition); + if (currentRegistry.getBalance().compareTo(counterRegistry.getBalance()) > 0) { + log.warn("{}", msgResolver.resolve(new EnumMessage(ClearingError.InsecurityObligation, currentRegistry.getCompanyId()))); + insecurityGroups.add(currentRegistry.getGroupId()); + break; + } + currentRegistry.setRegistryStatus("OK"); + registryImdg.update(counterRegistry); + } + } + + for (Long insecuritiesGroupId : insecurityGroups) { + for (Map.Entry> entrySet : registryByGroupIdAndCompanyId.get(insecuritiesGroupId).entrySet()) { + if (entrySet.getKey().equals(processedCompanyId)) { + for (Registry registry : entrySet.getValue()) { + registry.setRegistryStatus("UNCV"); + registryImdg.update(registry); + } + } else { + for (Registry registry : entrySet.getValue()) { + registry.setRegistryStatus("FAIL"); + registryImdg.update(registry); + } + } + } + } + + return new StageResult(null, true); + } +} diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java new file mode 100644 index 000000000..ca1c7b68c --- /dev/null +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java @@ -0,0 +1,54 @@ +package ru.spcex.clearing.service.builder.sql; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import ru.spcex.clearing.models.RegistryTradingParams; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryUnit; + +public class RegistryCodeSqlBuilderTest { + + @Test + public void testBuildByOneObject() { + RegistryTradingParams registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); + RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); + String sql = registryCodeSqlBuilder.build(); + Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql); + + registryTradingParams = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); + registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); + sql = registryCodeSqlBuilder.build(); + Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql); + + registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R); + registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); + sql = registryCodeSqlBuilder.build(); + Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R')", sql); + } + + @Test + public void testBuildByFewObjects() { + RegistryTradingParams registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); + RegistryTradingParams registryTradingParams_second = new RegistryTradingParams(RegistryDesignation.O, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); + RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); + String sql = registryCodeSqlBuilder.build(); + Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')" + + " or (registryDesignation = 'O' and registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); + + registryTradingParams_first = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); + registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); + registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); + sql = registryCodeSqlBuilder.build(); + Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R') or " + + "(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); + + registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R); + registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); + registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); + sql = registryCodeSqlBuilder.build(); + Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R') or " + + "(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); + } +}