From 30cb352377536b601cb7831a14d530aa73752541 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 22 Apr 2026 18:19:29 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-970 --- .../management/listener/TaskListener.java | 60 +++++++++++++++++++ .../management/service/ImdgQueryService.java | 8 +++ .../platform/enumeration/CurrencyCode.java | 2 +- .../platform/enumeration/OrderStatus.java | 3 +- 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java index 290276f65..eefc4421b 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java @@ -1,12 +1,18 @@ package ru.spcex.clearing.dflt.management.listener; import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; import java.util.Optional; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.producer.Producer; @@ -17,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.misc.OvernightSettings; +import ru.clearing.classes.statics.data.misc.SCrossRate; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.dflt.management.config.settings.DefaultManagementSettings; import ru.spcex.clearing.dflt.management.service.ImdgQueryService; @@ -27,9 +34,13 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.utilities.NotificationNewRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.enumeration.CurrencyCode; +import ru.spcex.platform.enumeration.ObjectType; import ru.spcex.platform.enumeration.OvernightType; +import ru.spcex.platform.enumeration.Priority; import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -114,6 +125,26 @@ public class TaskListener extends QueueConsumer implements InitializingBean { } private void exportToTriAndSendToFix(BaseRequest req) { + log.info("SDOR check balance and send notification, request={}", req); + Collection cretOrderCurrencies = imdgQueryService.getCRETOrderCurrencies(); + HashSet seen = new HashSet<>(); + Collection withRegistryIdUnique = cretOrderCurrencies.stream() + .filter(orderCurrency -> seen.add(orderCurrency.getRegistryId())) + .toList(); + + List messages = withRegistryIdUnique.stream() + .map(this::checkBalance) + .filter(Objects::nonNull) + .toList(); + + String comment = "После проведения первой части сделок переноса будет получен отрицательный баланс по RUB:\n" + + String.join("\n", messages); + NotificationNewRequest newReq = new NotificationNewRequest(); + newReq.setObjectType(ObjectType.rgst.getKey()); + newReq.setPriority(Priority.HIGH.getKey()); + newReq.setComment(comment); + kafkaSender.sendRequestToQueue(Consts.NOTIFICATION_NEW, req.getRequestPayload()); + log.info("SDOR export and send command to fix, request={}", req); try { Collection orders = imdgQueryService.getClccOrderCurrencyIds(); @@ -127,6 +158,35 @@ public class TaskListener extends QueueConsumer implements InitializingBean { } } + private String checkBalance(OrderCurrency orderCurrency) { + Registry pmtRegistry = imdgQueryService.getRegistryById(orderCurrency.getRegistryId()); + Registry amtRegistry = imdgQueryService.findAmtRegistry(pmtRegistry, CurrencyCode.RUB.getKey()); + String currency = pmtRegistry.getSecuritySymbol().equals(CurrencyCode.RUB.getKey()) + ? CurrencyCode.CNY.getKey() : pmtRegistry.getSecuritySymbol(); + SCrossRate sCrossRate = imdgQueryService.getSCrossRates(currency, LocalDate.now()); + BigDecimal val = orderCurrency.getQuantityLot() + .multiply(orderCurrency.getLotSize()) + .multiply(sCrossRate.getUnitRate()); + BigDecimal diff; + int compareRes = amtRegistry.getBalance().compareTo(BigDecimal.ZERO); + if (compareRes < 0) { + diff = amtRegistry.getBalance().add(val); + } else { + diff = amtRegistry.getBalance().subtract(val); + } + + if (diff.compareTo(BigDecimal.ZERO) < 0) { + NotificationNewRequest request = new NotificationNewRequest(); + request.setObjectType(ObjectType.rgst.getKey()); + request.setPriority(Priority.HIGH.getKey()); + + return String.format("Для ТКР %s компании %s: баланс %s RUB;", + amtRegistry.getTradingClearingRegistry(), amtRegistry.getShortName(), + diff.setScale(2, RoundingMode.HALF_UP)); + } + return null; + } + private OvernightType resolveOvernightType(Registry registry) { Optional settingsOpt = imdgQueryService.findOvernightSettingsByCompany(registry.getCompanyId()); diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/ImdgQueryService.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/ImdgQueryService.java index ff9f839f2..8f891adeb 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/ImdgQueryService.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/ImdgQueryService.java @@ -24,6 +24,7 @@ import ru.spcex.clearing.dflt.management.model.CounterpartyInfo; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.CompanyRole; import ru.spcex.platform.enumeration.MarketType; +import ru.spcex.platform.enumeration.OrderStatus; import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; @@ -93,6 +94,13 @@ public class ImdgQueryService { return orderCurrencyImdg.getCollectionObjectsByPredicate(clccOrderPredicate); } + public Collection getCRETOrderCurrencies() { + ImdgPredicateBuilder builder = orderCurrencyImdg.predicateBuilder(); + return orderCurrencyImdg.getCollectionObjectsByPredicate( + builder.equals("status", OrderStatus.CREATED.getKey()) + ); + } + public Optional findOvernightSettingsByCompany(Long companyId) { ImdgPredicateBuilder builder = overnightSettingsImdg.predicateBuilder(); ImdgPredicate predicate = builder.and( diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/CurrencyCode.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/CurrencyCode.java index f8d564186..00e7dc886 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/CurrencyCode.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/CurrencyCode.java @@ -7,7 +7,7 @@ public enum CurrencyCode implements IEnumKey { RUB("RUB"), RUR("RUR"),//fixme may be remove to separate enum SUR("SUR"), - + CNY("CNY"), ; public static boolean isRub(String currencyCode) { diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/OrderStatus.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/OrderStatus.java index b9d10a614..38c8a7ccf 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/OrderStatus.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/OrderStatus.java @@ -3,7 +3,8 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum OrderStatus implements IEnumKey { - NEW("NEW"), PTFL("PTFL"), FILL("FILL"), CNCL("CNCL"), REPL("REPL"), REJECTED("RJCT"); + NEW("NEW"), PTFL("PTFL"), FILL("FILL"), CNCL("CNCL"), REPL("REPL"), REJECTED("RJCT"), + CREATED("CRET"); private final String key;