From 19579ec0b0d2df08b8c7986e7d45548778fc2605 Mon Sep 17 00:00:00 2001 From: ialbert Date: Wed, 16 Aug 2023 19:47:52 +0300 Subject: [PATCH] =?UTF-8?q?SDF10=20*=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D0=B3=D1=80=D0=B0=D0=BD=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=20=D0=B0=D0=BA=D1=82=D0=B8?= =?UTF-8?q?=D0=B2=D0=BD=D1=83=D1=8E=20=D1=81=D0=B5=D1=81=D1=81=D0=B8=D1=8E?= =?UTF-8?q?=20*=20tradingTime?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/config/ValidationConfig.java | 1 + .../service/executors/Sdf10Executor.java | 83 ++++++++++++++++--- .../validation/Sdf10ValidationRule.java | 19 +++-- .../SecurityBySecurityCodeValidationRule.java | 1 + .../service/validation/ValidationStored.java | 4 +- .../platform/enumeration/TaskStatus.java | 23 +++++ 6 files changed, 113 insertions(+), 18 deletions(-) create mode 100644 platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TaskStatus.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index 1867d0160..64998ecd5 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -289,6 +289,7 @@ public class ValidationConfig { Sdf10ValidationRule.DepoAccountPresent, CompanyByTradingCodeValidationRule.instance(SDf10::getDepoCode), Sdf10ValidationRule.CompanyStatus, + Sdf06NewValidationRule.Session, Sdf10ValidationRule.TcrPresent, SecurityBySecurityCodeValidationRule.instance(SDf10::getSecurityCode), Sdf10ValidationRule.Balance diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf10Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf10Executor.java index 22d57e9e3..8ac290f9c 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf10Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf10Executor.java @@ -12,8 +12,10 @@ import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity; import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.clearing.classes.statics.data.scheduler.PlannerAllToday; import ru.clearing.classes.statics.data.sdf.SDf10; import ru.clearing.classes.statics.data.sdf.SDf11; +import ru.clearing.classes.statics.data.security.Security; import ru.clearing.classes.statics.data.statement.Statement; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -26,11 +28,14 @@ import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApp import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse; import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.RegistryManager; import ru.spcex.clearing.service.validation.ValidationStored; +import ru.spcex.clearing.session.stage.util.RegistryUtil; import ru.spcex.platform.enumeration.*; 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.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IEnumId; @@ -41,10 +46,8 @@ import ru.spcex.platform.utils.validation.IValidator; import java.math.BigDecimal; import java.time.Instant; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.Optional; +import java.time.LocalTime; +import java.util.*; import java.util.function.Function; @Service @@ -61,6 +64,8 @@ public class Sdf10Executor { private final Imdg companyImdg; private final Imdg sdf10Imdg; private final Imdg sdf11Imdg; + private final Imdg plannerAllTodayImdg; + private final RegistryManager rgsMng; private final ImdgId idGenerator; private final IMessageResolver messageResolver; private final Function sDf10Validator; @@ -75,6 +80,7 @@ public class Sdf10Executor { private final static String NOT_FOUND_SECURITY = "Не найден код ценной бумаги"; private final static String INVALID_SUM = "Недопустимая сумма списания"; private final static String PREVIOUS_REQUEST_NOT_PROCESSED = "Процесс обработки предыдущего SDF10 не завершен"; + private final static String SESSION_IS_ACTIVE = "Существует активная сессия"; private final static String GENERAL_ERROR = "Общая ошибка обработки SDF10"; private Long sdf10GroupId; @@ -82,7 +88,7 @@ public class Sdf10Executor { @Autowired public Sdf10Executor(ImdgProvider imdgProvider, - IMessageResolver messageResolver, + RegistryManager rgsMng, IMessageResolver messageResolver, @Qualifier("sdf10Validator") Function sDf10Validator, KafkaSender kafkaSender) { this.imdgProvider = imdgProvider; @@ -94,11 +100,13 @@ public class Sdf10Executor { this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.rgsMng = rgsMng; this.messageResolver = messageResolver; this.sDf10Validator = sDf10Validator; this.kafkaSender = kafkaSender; this.sdf10Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf10, SDf10.class); this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class); + this.plannerAllTodayImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PlannerAllToday, PlannerAllToday.class); } public void execute(BaseRequest systemRequest) { @@ -153,11 +161,12 @@ public class Sdf10Executor { Statement stmt = createStatementBySdf10(sDf10, company.getId(), account); statementImdg.insert(stmt); log.debug("Statement created: {}", stmt.getId()); - if (InOutDirection.in.getKey().equals(stmt.getInOutDirection())) { - processedApproved(stmt, sDf10, now, sdf11GroupId); - sdf11WasCreated = true; - } else { + if (InOutDirection.out.getKey().equals(stmt.getInOutDirection()) && isTradingTime()) { requests.add(requestFromStatement(stmt, company.getTradingCode(), tcr.getCode(), sDf10.getSecurityCode())); + } else { + SDf11 sDf11 = processedApproved(stmt, sDf10, now, sdf11GroupId); + createDs_t(tcr, company, validator.getStored(ValidationStored.SecurityBySecurityCode), stmt.getAmount(), sDf11.getOutDocument()); + sdf11WasCreated = true; } } if (requests.size() > 0) { @@ -171,11 +180,57 @@ public class Sdf10Executor { } } + //company, depoAccount, Security, Summ + private void createDs_t(TradingClearingRegistry tcr, Company company, Security security, BigDecimal summ, String outDocument) { + Optional as_t = rgsMng.findRelatedAsset(tcr.getId(), company.getId(), security.getSecuritySymbol(), RegistryTradingParams.AS_T); + if (as_t.isEmpty()) { + log.error("AS_T not found for tcr.id={} company.id={} security.symbol={}", tcr.getId(), company.getId(), security.getSecuritySymbol()); + return; + } + Registry rgsD = as_t.get().clone(); + rgsD.setRegistryDesignation(RegistryDesignation.D.getKey()); + rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD)); + rgsD.setBalance(summ); + rgsD.setDebit(BigDecimal.ZERO); + rgsD.setCredit(BigDecimal.ZERO); + rgsD.setDiffBalance(BigDecimal.ZERO); + rgsD.setCheckBalance(BigDecimal.ZERO); + rgsD.setRegistryStatus(RegistryStatus.PROC.getKey()); + rgsD.setContract(outDocument); + registryImdg.insert(rgsD); + log.debug("created DS*T.id={}", rgsD.getId()); + } + + private boolean isTradingTime() { + ImdgPredicateBuilder pb = plannerAllTodayImdg.predicateBuilder(); + Function> plannerByTask = task -> { + ImdgPredicate plannerPrdct = pb.and( + pb.equals("task", task.getKey()), + pb.equals("taskStatus", TaskStatus.Active.getKey()), + pb.equals("clearingDate", LocalDate.now()) + ); + return Optional.ofNullable(plannerAllTodayImdg.getFirstObjectByPredicate(plannerPrdct)); + }; + LocalTime startTradingTime = plannerByTask.apply(Task.createRegistry_STRS) + .map(PlannerAllToday::getTaskTime) + .orElse(null); + LocalTime endTradingTime = plannerByTask.apply(Task.createRegistry_ETRS) + .map(PlannerAllToday::getTaskTime) + .orElse(null); + if (startTradingTime == null || endTradingTime == null) { + log.warn("startTradingTime or endTradingTime is null"); + return false; + } + LocalTime now = LocalTime.now(); + log.debug("now: {}, startTradingTime: {}, endTradingTime: {}", now, startTradingTime, endTradingTime); + return !now.isBefore(startTradingTime) && !now.isAfter(endTradingTime); + } + private void processedApproved(Statement stmt, SDf10 sDf10, Instant time) { processedApproved(stmt, sDf10, time, sdf11GroupId); } - private void processedApproved(Statement stmt, SDf10 sDf10, Instant time, Long sdf11GenerationId) { + private SDf11 processedApproved(Statement stmt, SDf10 sDf10, Instant time, Long sdf11GenerationId) { log.trace("statement.id={}, sdf11.id={}, sdf10.id={} executed", stmt.getId(), sDf10.getGenerationId(), @@ -187,6 +242,7 @@ public class Sdf10Executor { stmt.setUpdated(time); stmt.setOutSDfId(sdf11.getId()); statementImdg.update(stmt); + return sdf11; } public void processGatewayResponse(BaseRequest req) { @@ -266,8 +322,8 @@ public class Sdf10Executor { private SDf11 createSdf11(SDf10 sdf10, Instant time, String result) { SDf11 sdf11 = new SDf11(); - sdf11.setOutDocument(sdf10.getOutDocument()); -// sdf11.setInDocument(); + sdf11.setOutDocument(UUID.randomUUID().toString()); + sdf11.setInDocument(sdf10.getOutDocument()); sdf11.setDepoCode(sdf10.getDepoCode()); sdf11.setQuantity(sdf10.getQuantity()); sdf11.setSecurityCode(sdf10.getSecurityCode()); @@ -334,6 +390,9 @@ public class Sdf10Executor { if (ClearingError.BalanceInsufficient.equals(err)) { return INVALID_SUM; } + if (ClearingError.ActiveSessionIsPresent.equals(err)) { + return SESSION_IS_ACTIVE; + } return GENERAL_ERROR; } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf10ValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf10ValidationRule.java index 27fa9469b..2f7ae158f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf10ValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf10ValidationRule.java @@ -10,6 +10,7 @@ import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.sdf.SDf10; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.enumeration.RegistryTradingParams; import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; @@ -29,7 +30,7 @@ import java.util.Optional; import java.util.function.Function; public enum Sdf10ValidationRule implements IValidationRule> { - DepoAccountPresent() { + DepoAccountPresent() { @Override public Optional validate(ImdgValidationContext context) { SDf10 sdf10 = context.getValidatedObject(); @@ -118,14 +119,22 @@ public enum Sdf10ValidationRule implements IValidationRule rgsDst = registryImdg.getCollectionObjectsByPredicate( + prdctBldr.and( + prdctBldr.equals("registryStatus", RegistryStatus.PROC.getKey()), + prdctByRegistryCode.apply(RegistryTradingParams.DS_T) + ) + ); + log.trace("validating sdf10 id={} account={} companyId={} found registries: AS*F.id={} DS*T.size={}", sdf10.getId(), account.getAccount(), company.getId(), rgsAsf == null ? null : rgsAsf.getId(), - rgsDst == null ? null : rgsDst.getId() + rgsDst.size() ); BigDecimal asfBalance = rgsAsf == null ? BigDecimal.ZERO : BigDecimalUtil.safeBD(rgsAsf.getBalance()); - BigDecimal dstBalance = rgsDst == null ? BigDecimal.ZERO : BigDecimalUtil.safeBD(rgsDst.getBalance()); + BigDecimal dstBalance = rgsDst.stream() + .map(rgs -> BigDecimalUtil.safeBD(rgs.getBalance())) + .filter(balance -> balance.compareTo(BigDecimal.ZERO) > 0) + .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal stmtAmount = BigDecimalUtil.safeBD(new BigDecimal(sdf10.getQuantity())); //fixme safe new BigDecimal if (asfBalance.subtract(dstBalance).compareTo(stmtAmount.abs()) < 0) { return of(ClearingError.BalanceInsufficient); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SecurityBySecurityCodeValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SecurityBySecurityCodeValidationRule.java index 68370effd..49fe1ef3c 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SecurityBySecurityCodeValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SecurityBySecurityCodeValidationRule.java @@ -42,6 +42,7 @@ public class SecurityBySecurityCodeValidationRule implements IValidationRule< if (security == null) { return of(ClearingError.SecurityNotFound, securitySymbol); } + context.storeObject(ValidationStored.SecurityBySecurityCode, security); return empty(); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java index 03a28834f..847b2603b 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java @@ -18,5 +18,7 @@ public enum ValidationStored { ReturnDepositDmx, - CompanyByTradingCode + CompanyByTradingCode, + + SecurityBySecurityCode } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TaskStatus.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TaskStatus.java new file mode 100644 index 000000000..8055a37ac --- /dev/null +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TaskStatus.java @@ -0,0 +1,23 @@ +package ru.spcex.platform.enumeration; + +import ru.spcex.platform.utils.enumeration.IEnumKey; + +public enum TaskStatus implements IEnumKey { + Active("ACTV"), + ; + + private final String key; + + TaskStatus(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } + + public String topic() { + return "launcher-" + getKey(); + } +}