From b21aa5ef11b379431f2317a912ba28f7622ce026 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 12:07:58 +0300 Subject: [PATCH 01/11] http://jira.mfd.msk:8088/browse/CLS-969 --- .../request/cud/securities/SCrossRateNewAction.java | 6 ++++++ .../request/cud/securities/SCrossRateUpdateAction.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java index b257585cb..b107cebd8 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateNewAction.java @@ -1,14 +1,20 @@ package ru.spcex.clearing.backendapi.controller.request.cud.securities; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.math.BigDecimal; import java.time.LocalDate; import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateNewRequest; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; public class SCrossRateNewAction implements IAction { @JsonProperty + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) private LocalDate date; @JsonProperty private String currency; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java index 564ce5625..80d1c7fe2 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/SCrossRateUpdateAction.java @@ -1,16 +1,22 @@ package ru.spcex.clearing.backendapi.controller.request.cud.securities; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.math.BigDecimal; import java.time.LocalDate; import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.SCrossRateUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; public class SCrossRateUpdateAction implements IAction { @JsonProperty private Long id; @JsonProperty + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) private LocalDate date; @JsonProperty private String currency; From 914b379c608655b38fcb79028faeda7e3d91fbc0 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 12:08:26 +0300 Subject: [PATCH 02/11] http://jira.mfd.msk:8088/browse/CLS-969 --- .../domain/cud/securitites/SCrossRateNewRequest.java | 6 ++++++ .../domain/cud/securitites/SCrossRateUpdateRequest.java | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateNewRequest.java index 4b81c7eb7..b007366bc 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateNewRequest.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateNewRequest.java @@ -1,13 +1,19 @@ package ru.spcex.clearing.platform.messaging.domain.cud.securitites; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.math.BigDecimal; import java.time.LocalDate; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; public class SCrossRateNewRequest { @JsonProperty private String type; @JsonProperty + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) private LocalDate date; @JsonProperty private String currency; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java index ebe8f1e88..40dbfc125 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/SCrossRateUpdateRequest.java @@ -1,13 +1,19 @@ package ru.spcex.clearing.platform.messaging.domain.cud.securitites; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.math.BigDecimal; import java.time.LocalDate; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; public class SCrossRateUpdateRequest { @JsonProperty private Long id; @JsonProperty + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) private LocalDate date; @JsonProperty private String currency; From 5ea4fff504b6a43b2e4fed3b08cf7e3f18f6ccb5 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 12:12:04 +0300 Subject: [PATCH 03/11] http://jira.mfd.msk:8088/browse/CLS-950 --- .../backend-api/src/main/resources/meta/meta.json | 6 +++--- .../backend-api/src/main/resources/meta/meta.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.json b/clearing-parent/backend-api/src/main/resources/meta/meta.json index 08719a24e..59355b630 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.json +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.json @@ -1,6 +1,6 @@ { - "version": "3.23.295.156", + "version": "3.23.295.157", "enums": { @@ -11036,7 +11036,7 @@ "name": "Добавление параметров риска", - "confirmation": "value,settlementType,currencyPairId,status", + "confirmation": "value,quoteValue,settlementType,currencyPairId,status", "class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterNewAction", @@ -11067,7 +11067,7 @@ "name": "Изменение параметров риска", - "confirmation": "value,status", + "confirmation": "value,quoteValue,status", "class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterUpdateAction", diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.xml b/clearing-parent/backend-api/src/main/resources/meta/meta.xml index 976ad44a0..6d1473be5 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.xml @@ -1,6 +1,6 @@ - + @@ -2557,14 +2557,14 @@ - + - + From 2968cfb3d8c146cf8378cbc480be53e83bdaac7b Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 15:59:14 +0300 Subject: [PATCH 04/11] http://jira.mfd.msk:8088/browse/CLS-943 --- .../dflt/management/model/SwapContext.java | 13 -------- .../management/service/ImdgQueryService.java | 33 ++++++++++++++----- .../service/OrderCalculationService.java | 8 ++--- .../service/OrderTemplateBuilder.java | 2 ++ .../service/SpotOvernightOrderService.java | 8 +++-- .../service/SwapOvernightOrderService.java | 8 +++-- 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/model/SwapContext.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/model/SwapContext.java index 55f7a0cc6..28cfb35b1 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/model/SwapContext.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/model/SwapContext.java @@ -1,6 +1,5 @@ package ru.spcex.clearing.dflt.management.model; -import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.Market; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.security.RiskParameter; @@ -9,7 +8,6 @@ public class SwapContext { private final Registry registry; private final String orderCategory; private final Market market; - private final Listing listing; private final RiskParameter riskParameter; private final CounterpartyInfo categoryP; private final CounterpartyInfo clcc; @@ -19,7 +17,6 @@ public class SwapContext { this.registry = builder.registry; this.orderCategory = builder.orderCategory; this.market = builder.market; - this.listing = builder.listing; this.riskParameter = builder.riskParameter; this.categoryP = builder.categoryP; this.clcc = builder.clcc; @@ -38,10 +35,6 @@ public class SwapContext { return market; } - public Listing getListing() { - return listing; - } - public RiskParameter getRiskParameter() { return riskParameter; } @@ -66,7 +59,6 @@ public class SwapContext { private Registry registry; private String orderCategory; private Market market; - private Listing listing; private RiskParameter riskParameter; private CounterpartyInfo categoryP; private CounterpartyInfo clcc; @@ -87,11 +79,6 @@ public class SwapContext { return this; } - public Builder listing(Listing listing) { - this.listing = listing; - return this; - } - public Builder riskParameter(RiskParameter riskParameter) { this.riskParameter = riskParameter; return this; 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 a1f60d71a..76aed74df 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 @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.time.LocalDate; import java.util.Collection; import java.util.Optional; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.company.ClearingMemberCategory; import ru.clearing.classes.statics.data.company.Company; @@ -68,7 +69,8 @@ public class ImdgQueryService { ImdgPredicateBuilder builder = registryImdg.predicateBuilder(); ImdgPredicate registryPredicate = builder.and( builder.regex("registryCode", "^PM.*T"), - builder.not(builder.equals("registryStatus", RegistryStatus.OK.getKey())) + builder.not(builder.equals("registryStatus", RegistryStatus.OK.getKey())), + builder.equals("clearingDate", LocalDate.now()) ); return registryImdg.getCollectionIdsByPredicate(registryPredicate); @@ -159,8 +161,14 @@ public class ImdgQueryService { public Listing findListing(Registry registry, String marketCode) { return "RUB".equals(registry.getSecuritySymbol()) - ? findListingForRub(registry, marketCode) - : findListingForOtherCurrency(registry, marketCode); + ? findListingForRub(registry, marketCode, null) + : findListingForOtherCurrency(registry, marketCode, null); + } + + public Listing findListing(Registry registry, String marketCode, String settleCode) { + return "RUB".equals(registry.getSecuritySymbol()) + ? findListingForRub(registry, marketCode, settleCode) + : findListingForOtherCurrency(registry, marketCode, settleCode); } public RiskParameter findRiskParameter(Registry registry) { @@ -208,9 +216,8 @@ public class ImdgQueryService { return currencyPairDictionaryImdg.getSingleObjectByID(security.getCurrencyPairId()); } - private Listing findListingForRub(Registry registry, String marketCode) { + private Listing findListingForRub(Registry registry, String marketCode, String settleCode) { ImdgPredicateBuilder pb = currencyPairDictionaryImdg.predicateBuilder(); - CurrencyPairDictionary pair = currencyPairDictionaryImdg.getFirstObjectByPredicate( pb.and( pb.equals("baseCurrency", "CNY"), @@ -218,8 +225,13 @@ public class ImdgQueryService { ) ); + ImdgPredicate settlementTypeCondition = + StringUtils.isNotEmpty(settleCode) ? pb.equals("settlementType", settleCode) : pb.alwaysTrue(); Collection securityIds = currencyPairSecurityImdg.getCollectionIdsByPredicate( - pb.equals("currencyPairId", pair.getId()) + pb.and( + pb.equals("currencyPairId", pair.getId()), + settlementTypeCondition + ) ); return listingImdg.getSingleObjectByPredicate( @@ -230,7 +242,7 @@ public class ImdgQueryService { ); } - private Listing findListingForOtherCurrency(Registry registry, String marketCode) { + private Listing findListingForOtherCurrency(Registry registry, String marketCode, String settleCode) { ImdgPredicateBuilder pb = currencyPairDictionaryImdg.predicateBuilder(); CurrencyPairDictionary pair = currencyPairDictionaryImdg.getFirstObjectByPredicate( @@ -240,8 +252,13 @@ public class ImdgQueryService { ) ); + ImdgPredicate settlementTypeCondition = + StringUtils.isNotEmpty(settleCode) ? pb.equals("settlementType", settleCode) : pb.alwaysTrue(); Collection securityIds = currencyPairSecurityImdg.getCollectionIdsByPredicate( - pb.equals("currencyPairId", pair.getId()) + pb.and( + pb.equals("currencyPairId", pair.getId()), + settlementTypeCondition + ) ); return listingImdg.getSingleObjectByPredicate( diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java index a7b4b3c27..2c92b21a8 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java @@ -31,7 +31,7 @@ public class OrderCalculationService { public void calcAndEnrichSwap(OrderCurrency order, SwapContext context) { Registry registry = context.getRegistry(); - Listing listing = context.getListing(); + Listing listing = imdgQueryService.findListing(registry, context.getMarket().getCode(), order.getSettleCode()); CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryBySecurityId(listing.getSecurityId()); BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol()); @@ -51,7 +51,7 @@ public class OrderCalculationService { public void calcAndEnrichSpot(OrderCurrency order, SwapContext context) { Registry registry = context.getRegistry(); - Listing listing = context.getListing(); + Listing listing = imdgQueryService.findListing(registry, context.getMarket().getCode(), order.getSettleCode()); CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryBySecurityId(listing.getSecurityId()); BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol()); @@ -88,7 +88,7 @@ public class OrderCalculationService { BigDecimal rateValue = rates.getValue(); BigDecimal sum2 = planPositionRub.divide(rateValue, lotSize, RoundingMode.HALF_DOWN); - BigDecimal sum3 = sum1.setScale(0, RoundingMode.CEILING).min(sum2); + BigDecimal sum3 = sum1.setScale(lotSize, RoundingMode.CEILING); BigDecimal sum4 = sum3.multiply(rateValue, MC).negate(); BigDecimal sum5 = sum3.negate(); @@ -113,7 +113,7 @@ public class OrderCalculationService { BigDecimal planPositionCny = cnyRegistry.getBalance(); BigDecimal sum2 = planPositionCny.divide(rateValue, lotSize, RoundingMode.HALF_DOWN); - BigDecimal sum3 = sum1.setScale(0, RoundingMode.CEILING).min(sum2).negate(); + BigDecimal sum3 = sum1.setScale(lotSize, RoundingMode.CEILING).min(sum2).negate(); BigDecimal sum4 = sum3.multiply(rateValue, MC).negate(); BigDecimal sum5 = sum3.negate(); diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java index 827b20664..cee16a04c 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java @@ -1,5 +1,6 @@ package ru.spcex.clearing.dflt.management.service; +import java.time.Instant; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.Market; @@ -208,6 +209,7 @@ public class OrderTemplateBuilder { order.setStatus("CRET"); order.setComment(comment); order.setRegistryId(registry.getId()); + order.setCreated(Instant.now()); } private Side resolvePrimaryTransferSide(Registry registry, SettleCode settleCode) { diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SpotOvernightOrderService.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SpotOvernightOrderService.java index fe6e9fba2..03c2663c1 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SpotOvernightOrderService.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SpotOvernightOrderService.java @@ -3,7 +3,6 @@ package ru.spcex.clearing.dflt.management.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.Market; import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.registry.Registry; @@ -12,6 +11,7 @@ import ru.spcex.clearing.dflt.management.model.CounterpartyInfo; import ru.spcex.clearing.dflt.management.model.SwapContext; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.CompanyRole; +import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.enumeration.SettleCode; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -22,6 +22,7 @@ public class SpotOvernightOrderService { private final ImdgQueryService imdgQueryService; private final Imdg orderCurrencyImdg; + private final Imdg registryImdg; private final OrderTemplateBuilder templateBuilder; private final OrderCalculationService swapCalculationService; @@ -31,6 +32,7 @@ public class SpotOvernightOrderService { OrderCalculationService swapCalculationService) { this.imdgQueryService = imdgQueryService; this.orderCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OrderCurrency, OrderCurrency.class); + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.templateBuilder = templateBuilder; this.swapCalculationService = swapCalculationService; } @@ -39,7 +41,6 @@ public class SpotOvernightOrderService { String orderCategory = imdgQueryService.resolveOrderCategory(registry.getCompanyId()); Market market = imdgQueryService.getSpotMarket(); - Listing listing = imdgQueryService.findListing(registry, market.getCode()); RiskParameter riskParameter = imdgQueryService.findRiskParameter(registry); CounterpartyInfo categoryP = imdgQueryService.getCompanyByClearingCategory("P"); CounterpartyInfo clcc = imdgQueryService.getCompanyByRole(CompanyRole.CLCC); @@ -49,7 +50,6 @@ public class SpotOvernightOrderService { .registry(registry) .orderCategory(orderCategory) .market(market) - .listing(listing) .riskParameter(riskParameter) .categoryP(categoryP) .clcc(clcc) @@ -86,6 +86,8 @@ public class SpotOvernightOrderService { orderCurrencyImdg.insert(primaryBalancingT1); orderCurrencyImdg.insert(counterBalancingT1); + registry.setRegistryStatus(RegistryStatus.OK.getKey()); + registryImdg.update(registry); log.info("Spot orders created for registryId={}", registry.getId()); } diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SwapOvernightOrderService.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SwapOvernightOrderService.java index 3a7f457ce..3e4cab785 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SwapOvernightOrderService.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/SwapOvernightOrderService.java @@ -3,7 +3,6 @@ package ru.spcex.clearing.dflt.management.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.Market; import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.registry.Registry; @@ -12,6 +11,7 @@ import ru.spcex.clearing.dflt.management.model.CounterpartyInfo; import ru.spcex.clearing.dflt.management.model.SwapContext; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.CompanyRole; +import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.enumeration.SettleCode; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -22,6 +22,7 @@ public class SwapOvernightOrderService { private final ImdgQueryService imdgQueryService; private final Imdg orderCurrencyImdg; + private final Imdg registryImdg; private final OrderTemplateBuilder templateBuilder; private final OrderCalculationService swapCalculationService; @@ -31,6 +32,7 @@ public class SwapOvernightOrderService { OrderCalculationService swapCalculationService) { this.imdgQueryService = imdgQueryService; this.orderCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OrderCurrency, OrderCurrency.class); + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.templateBuilder = templateBuilder; this.swapCalculationService = swapCalculationService; } @@ -39,7 +41,6 @@ public class SwapOvernightOrderService { String orderCategory = imdgQueryService.resolveOrderCategory(registry.getCompanyId()); Market market = imdgQueryService.getSwapMarket(); - Listing listing = imdgQueryService.findListing(registry, market.getCode()); RiskParameter riskParameter = imdgQueryService.findRiskParameter(registry); CounterpartyInfo categoryP = imdgQueryService.getCompanyByClearingCategory("P"); CounterpartyInfo clcc = imdgQueryService.getCompanyByRole(CompanyRole.CLCC); @@ -49,7 +50,6 @@ public class SwapOvernightOrderService { .registry(registry) .orderCategory(orderCategory) .market(market) - .listing(listing) .riskParameter(riskParameter) .categoryP(categoryP) .clcc(clcc) @@ -71,6 +71,8 @@ public class SwapOvernightOrderService { orderCurrencyImdg.insert(primaryBalancing); orderCurrencyImdg.insert(counterBalancing); + registry.setRegistryStatus(RegistryStatus.OK.getKey()); + registryImdg.update(registry); log.info("Swap orders created for registryId={}", registry.getId()); } From 73faa53ee9d149ce1e0ace46db6027a3ea9b9a41 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 17:48:46 +0300 Subject: [PATCH 05/11] http://jira.mfd.msk:8088/browse/CLS-943 --- .../dflt/management/service/OrderTemplateBuilder.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java index cee16a04c..68dc766ea 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java @@ -15,6 +15,11 @@ import ru.spcex.platform.enumeration.Side; @Service public class OrderTemplateBuilder { + private final ImdgQueryService imdgQueryService; + + public OrderTemplateBuilder(ImdgQueryService imdgQueryService) { + this.imdgQueryService = imdgQueryService; + } public OrderCurrency buildPrimaryTransfer(SwapContext context, SettleCode settleCode) { OrderCurrency orderCurrency; @@ -193,9 +198,9 @@ public class OrderTemplateBuilder { String comment, SettleCode settleCode) { Registry registry = context.getRegistry(); - Listing listing = context.getListing(); Market market = context.getMarket(); RiskParameter riskParameter = context.getRiskParameter(); + Listing listing = imdgQueryService.findListing(registry, market.getCode(), settleCode.getKey()); order.setOvernightType("SWAP"); order.setMarket(market.getCode()); From 1a3aee9c28f00dea65decf30c5f9cdc1933d159e Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 17:55:49 +0300 Subject: [PATCH 06/11] http://jira.mfd.msk:8088/browse/CLS-943 --- .../clearing/dflt/management/service/ImdgQueryService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 76aed74df..ff9f839f2 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 @@ -200,7 +200,8 @@ public class ImdgQueryService { public BigDecimal defineTransferRate(Long currencyPairDictionaryId, String securitySymbol) { ImdgPredicateBuilder pb = riskParameterImdg.predicateBuilder(); - String baseCurrency = "RUB".equals(securitySymbol) ? "CNY" : securitySymbol; + boolean isRub = "RUB".equals(securitySymbol); + String baseCurrency = isRub ? "CNY" : securitySymbol; RiskParameter riskParameter = riskParameterImdg.getSingleObjectByPredicate( pb.and( @@ -208,7 +209,7 @@ public class ImdgQueryService { pb.equals("currencyPairId", currencyPairDictionaryId) ) ); - return riskParameter.getQuoteValue(); + return isRub ? riskParameter.getValue() : riskParameter.getQuoteValue(); } public CurrencyPairDictionary getCurrencyPairDictionaryBySecurityId(Long securityId) { From a88dd578579a481f7a87df82b6e7ecfc75f6a5d4 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Tue, 21 Apr 2026 18:00:55 +0300 Subject: [PATCH 07/11] http://jira.mfd.msk:8088/browse/CLS-943 --- .../dflt/management/service/OrderCalculationService.java | 1 + .../clearing/dflt/management/service/OrderTemplateBuilder.java | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java index 2c92b21a8..e871d7d65 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderCalculationService.java @@ -75,6 +75,7 @@ public class OrderCalculationService { order.setPrice(price); order.setQuantityLot(quantityLot); + order.setRate(s); } private CalculationResult calculationSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) { diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java index 68dc766ea..79bc9bb74 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/service/OrderTemplateBuilder.java @@ -208,7 +208,6 @@ public class OrderTemplateBuilder { order.setSecuritySymbol(listing.getSymbolCode()); order.setSecurityId(listing.getSecurityId()); order.setLotSize(listing.getLotSize()); - order.setRate(riskParameter.getQuoteValue()); order.setSide(side.getKey()); order.setSettleCode(settleCode.getKey()); order.setStatus("CRET"); From 63ec986491e6353f65b1233e020087499364659c Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 22 Apr 2026 12:05:05 +0300 Subject: [PATCH 08/11] http://jira.mfd.msk:8088/browse/CLS-943http://jira.mfd.msk:8088/browse/CLS-973 --- .../queue/account/AccountController.java | 46 +++++++++++++---- .../queue/company/CompanyController.java | 43 ++++++++++++---- .../TradingClearingRegistryController.java | 49 +++++++++++++++---- .../ru/spcex/platform/enumeration/Status.java | 1 + 4 files changed, 111 insertions(+), 28 deletions(-) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java index 1cebcb051..7eb62784d 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java @@ -4,10 +4,22 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.server.ResponseStatusException; import ru.clearing.classes.statics.data.account.Account; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; import ru.spcex.clearing.backendapi.controller.request.cud.account.AccountNewAction; @@ -20,30 +32,46 @@ import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; - -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ExecutionException; +import ru.spcex.platform.enumeration.Status; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; @Controller @RequestMapping("/accounting/accounts") public class AccountController extends AbstractQueueController { private final IStateLoader stateLoader; + private final ImdgPredicateBuilder predicateBuilder; @Autowired - public AccountController(IOperator operator, IStateLoader stateLoader) { + public AccountController(IOperator operator, + IStateLoader stateLoader, + ImdgProvider imdgProvider) { super(operator); this.stateLoader = stateLoader; + this.predicateBuilder = imdgProvider + .getImdg(IMDGDistributedNames.Map_Account, Account.class) + .predicateBuilder(); } @ApiOperation(value = "get all accounts.") @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)}) @RequestMapping(method = RequestMethod.GET) @ResponseBody - public CommonGetAllResponse getAll() { - Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_Account, Account.class); + public CommonGetAllResponse getAll(@RequestParam(name = "kind", required = false) String kind) { CommonGetAllResponse response = new CommonGetAllResponse(); - response.fromEntity(all); + if (StringUtils.isEmpty(kind)) { + Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_Account, Account.class); + response.fromEntity(all); + } else if (kind.equals("BLKD")) { + ImdgPredicate predicate = predicateBuilder.in("status", + Arrays.asList(Status.Blocked.getKey(), Status.Close.getKey()).toArray(new String[0])); + Collection> allByStatus = stateLoader.getAllMetaTransform( + IMDGDistributedNames.Map_Account, Account.class, predicate); + response.fromEntity(allByStatus); + } else { + throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Kind is not supported: " + kind); + } return response; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/CompanyController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/CompanyController.java index f75928320..aa2615fbd 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/CompanyController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/CompanyController.java @@ -4,10 +4,21 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.server.ResponseStatusException; import ru.clearing.classes.statics.data.company.Company; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; @@ -19,21 +30,26 @@ import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; - -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ExecutionException; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; @Controller @RequestMapping("/companies") public class CompanyController extends AbstractQueueController { private final IStateLoader stateLoader; + private final ImdgPredicateBuilder predicateBuilder; @Autowired public CompanyController(IOperator operator, - IStateLoader stateLoader) { + IStateLoader stateLoader, + ImdgProvider imdgProvider) { super(operator); this.stateLoader = stateLoader; + this.predicateBuilder = imdgProvider + .getImdg(IMDGDistributedNames.Map_Company, Company.class) + .predicateBuilder(); } @ApiOperation(value = "delete company.") @@ -51,10 +67,19 @@ public class CompanyController extends AbstractQueueController { @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)}) @RequestMapping(method = RequestMethod.GET) @ResponseBody - public CommonGetAllResponse getAll() { - Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_Company, Company.class); + public CommonGetAllResponse getAll(@RequestParam(name = "kind", required = false) String kind) { CommonGetAllResponse response = new CommonGetAllResponse(); - response.fromEntity(all); + if (StringUtils.isEmpty(kind)) { + Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_Company, Company.class); + response.fromEntity(all); + } else if (kind.equals("BLKD")){ + ImdgPredicate predicate = predicateBuilder.equals("workflowStatus", WorkflowStatus.Blocked.getKey()); + Collection> allByStatus = stateLoader.getAllMetaTransform( + IMDGDistributedNames.Map_Company, Company.class, predicate); + response.fromEntity(allByStatus); + } else { + throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Kind is not supported: " + kind); + } return response; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/registry/TradingClearingRegistryController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/registry/TradingClearingRegistryController.java index 50c5984ab..385ab50e6 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/registry/TradingClearingRegistryController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/registry/TradingClearingRegistryController.java @@ -4,10 +4,23 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.server.ResponseStatusException; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; @@ -21,21 +34,26 @@ import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; - -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.ExecutionException; +import ru.spcex.platform.enumeration.Status; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; @Controller @RequestMapping("/trading-clearing-registries") public class TradingClearingRegistryController extends AbstractQueueController { private final IStateLoader stateLoader; + private final ImdgPredicateBuilder predicateBuilder; @Autowired - public TradingClearingRegistryController(IOperator operator, IStateLoader stateLoader) { + public TradingClearingRegistryController(IOperator operator, + IStateLoader stateLoader, + ImdgProvider imdgProvider) { super(operator); this.stateLoader = stateLoader; + this.predicateBuilder = imdgProvider + .getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class) + .predicateBuilder(); } @ApiOperation(value = "create TradingClearingRegistry.") @@ -88,10 +106,21 @@ public class TradingClearingRegistryController extends AbstractQueueController { @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)}) @RequestMapping(method = RequestMethod.GET) @ResponseBody - public CommonGetAllResponse getAll() { - Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); + public CommonGetAllResponse getAll(@RequestParam(name = "kind", required = false) String kind) { CommonGetAllResponse response = new CommonGetAllResponse(); - response.fromEntity(all); + + if (StringUtils.isEmpty(kind)) { + Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); + response.fromEntity(all); + } else if (kind.equals("BLKD")) { + ImdgPredicate predicate = predicateBuilder.in("status", + Arrays.asList(Status.Blocked.getKey(), Status.Close.getKey()).toArray(new String[0])); + Collection> allByStatus = stateLoader.getAllMetaTransform( + IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class, predicate); + response.fromEntity(allByStatus); + } else { + throw new ResponseStatusException(HttpStatus.NOT_ACCEPTABLE, "Kind is not supported: " + kind); + } return response; } } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Status.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Status.java index 182a00fed..e1f60c20b 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Status.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Status.java @@ -5,6 +5,7 @@ import ru.spcex.platform.utils.enumeration.IEnumKey; public enum Status implements IEnumKey { Active("ACTV"), Blocked("BLKD"), + Close("CLOS"), Cancel("CNCL"); private final String key; From 4ad5a13710a60fa6fccc8252c7a23ea8ec694a6d Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 22 Apr 2026 12:24:40 +0300 Subject: [PATCH 09/11] http://jira.mfd.msk:8088/browse/CLS-958 [1 - send orders by fix protocol] --- .../management/listener/TaskListener.java | 2 +- .../clearing/fix/service/FixService.java | 197 ------------------ .../clearing/fix/service/FixTaskListener.java | 73 +++++++ 3 files changed, 74 insertions(+), 198 deletions(-) delete mode 100644 clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixService.java create mode 100644 clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixTaskListener.java 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 c289ed898..efe2792a0 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 @@ -114,7 +114,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean { } private void exportToTriAndSendToFix(BaseRequest req) { - + log.info("SDOR export and send command to fix, request={}", req); try { Collection orders = imdgQueryService.getClccOrderCurrencyIds(); String content = orderCurrencyTriExportService.exportToTri(orders); diff --git a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixService.java b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixService.java deleted file mode 100644 index 35437fb84..000000000 --- a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixService.java +++ /dev/null @@ -1,197 +0,0 @@ -package ru.spcex.clearing.fix.service; - -import org.apache.commons.lang3.StringUtils; -import org.apache.kafka.clients.consumer.Consumer; -import org.apache.kafka.clients.producer.Producer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import ru.clearing.classes.statics.data.company.Company; -import ru.clearing.classes.statics.data.company.CompanySymbols; -import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.platform.messaging.domain.ActionType; -import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanyNewRequest; -import ru.spcex.clearing.platform.messaging.service.QueueConsumer; -import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; -import ru.spcex.clearing.util.security.UserRoleVerification; -import ru.spcex.clearing.util.services.RequestHelper; -import ru.spcex.platform.enumeration.CompanySymbol; -import ru.spcex.platform.enumeration.UserRole; -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.ImdgTransaction; -import ru.spcex.platform.utils.error.ValidationException; - -import java.time.Instant; -import java.util.Objects; - -@Service -public class FixService extends QueueConsumer implements InitializingBean { - - private final Logger log = LoggerFactory.getLogger(getClass()); - private final RequestHelper requestHelper; - private final ImdgProvider imdgProvider; - private final ImdgId idSequence; - private final Imdg companyIMap; - protected UserRoleVerification userRoleVerification; -// protected CompanySymbolService companySymbolService; -// protected AccountNotificationHelper accountNotification; -// protected RelationService relationService; -// private final ValidationHelper validationHelper; -// private final Function companyNewRequestValidator; -// private final Function companyUpdateRequestValidator; -// private final Function companyDeleteRequestValidator; - - @Autowired - public FixService(Consumer kafkaQueue, Producer kafkaProducer, - ImdgProvider imdgProvider, - RequestHelper requestHelper, -// ValidationHelper validationHelper, - UserRoleVerification userRoleVerification -// @Qualifier("companyNewRequestValidator") -// Function companyNewRequestValidator, -// @Qualifier("companyUpdateRequestValidator") -// Function companyUpdateRequestValidator, -// @Qualifier("CompanyDeleteRequestValidator") -// Function companyDeleteRequestValidator, -// CompanySymbolService companySymbolService, -// AccountNotificationHelper accountNotification, - /*RelationService relationService*/) { - super(kafkaQueue, kafkaProducer); - this.imdgProvider = imdgProvider; - this.requestHelper = requestHelper.setLogger(log); - this.idSequence = imdgProvider.getImdgIdGenerator(); - this.userRoleVerification = userRoleVerification; - this.userRoleVerification.setRoleForVerification(UserRole.Admin); -// this.validationHelper = validationHelper; -// this.companyNewRequestValidator = companyNewRequestValidator; -// this.companyUpdateRequestValidator = companyUpdateRequestValidator; -// this.companyDeleteRequestValidator = companyDeleteRequestValidator; -// this.companySymbolService = companySymbolService; -// this.companySymbolService.setCompanyService(this); -// this.accountNotification = accountNotification; -// this.relationService = relationService; - - companyIMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); - } - - @Override - public void afterPropertiesSet() { -// callback(CommonDeleteRequest.class) -// .setFunction(request -> requestHelper.requestFunction(this::deleteCompany, request)) -// .forDestination(Consts.DESTINATION_COMPANY_DELETE, callbacks::put); -// callback(CommonDeleteRequest.class) -// .setFunction(request -> requestHelper.requestFunction(this::blockCompanyAfterDocument, request)) -// .forDestination(Consts.DESTINATION_COMPANY_BLOCK, callbacks::put); -// callback(CompanyNewRequest.class) -// .setFunction(request -> requestHelper.requestFunction(this::processBaseRequest, request)) -// .forDestination(Consts.DESTINATION_COMPANY_NEW, callbacks::put); -// callback(CompanyNewRequest.class) -// .setFunction(request -> requestHelper.requestFunction(this::processBaseRequest, request)) -// .forDestination(Consts.DESTINATION_COMPANY_UPDATE, callbacks::put); -// callback(AccountTerminationRequest.class) -// .setFunction(request -> requestHelper.requestFunction(this::finishCompanyTermination, request)) -// .forDestination(Consts.ACCOUNT_TERMINATION_STEP2, callbacks::put); - init(); - } - - private RequestInfoUpdate processBaseRequest(BaseRequest request) throws ValidationException { - // Валидация - RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(request); - if (requestInfoUpdate != null) return requestInfoUpdate; - ActionType actionType = request.getActionType(); - switch (actionType) { - case NEW -> { - CompanyNewRequest companyNewRequest = (CompanyNewRequest) request.getRequestPayload(); -// IValidator validator = companyNewRequestValidator.apply(companyNewRequest); -// Optional error = validator.tillFirstError(); -// if (error.isPresent()) { -// throw new ValidationException(error.get()); -// } -// create(companyNewRequest); - } - case UPDATE -> update((CompanyNewRequest) request.getRequestPayload(), true); - } - return requestInfoUpdate; - } - - public synchronized void update(CompanyNewRequest updateRequest, boolean validationIsEnable) throws ValidationException { -// if (validationIsEnable) { -// IValidator validator = companyUpdateRequestValidator.apply(updateRequest); -// Optional error = validator.tillFirstError(); -// if (error.isPresent()) { -// throw new ValidationException(error.get()); -// } -// } - ImdgTransaction transaction = imdgProvider.newTransaction(); - transaction.beginTransaction(); - boolean txOk = false; - try { - Imdg companyMap = transaction.getImdg(IMDGDistributedNames.Map_Company, Company.class); - Company company = companyMap.getSingleObjectByID(updateRequest.getId()); -// if (company == null) { -// log.trace("Company {} not found", updateRequest.getId()); -// throw new ValidationException(new EnumMessage(FixErrors.CompanyNotFound)); -// } -// if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) { -// log.trace("Company {} not active: {}", company.getId(), company.getWorkflowStatus()); -// return requestHelper.makeErrorResponse(companyUpdateRequestBaseRequest, CompanyErrors.CompanyDisabled, updateRequest.getId()); -// } - - company.setUpdated(Instant.now()); - if (StringUtils.isNotEmpty(updateRequest.getShortName())) - company.setShortName(updateRequest.getShortName()); - if (StringUtils.isNotEmpty(updateRequest.getFullName())) - company.setFullName(updateRequest.getFullName()); - - if (updateRequest.getCompanySymbol() != null || updateRequest.getCompanySymbolValue() != null) { - log.trace("Request field CompanySymbol, CompanySymbolValue ignore for update company request."); - } - - String prevStatus = company.getWorkflowStatus(); - if (updateRequest.getWorkflowStatus() != null) { - company.setWorkflowStatus(updateRequest.getWorkflowStatus()); - if (!Objects.equals(prevStatus, company.getWorkflowStatus())) { -// relationService.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus()); - } else { - log.trace("Status was not changed"); - } - } else { - log.trace("Null new WorkflowStatus"); - } - companyMap.update(company); - txOk = true; - } finally { - if (txOk) - transaction.commitTransaction(); - else - transaction.rollbackTransaction(); - } - } - - protected void updateCompanyBySymbol(Company company, CompanySymbols companySymbol, boolean shouldBeDeleted) { - assert company.getId().equals(companySymbol.getCompanyId()); - String companySymbolValue = companySymbol.getCompanySymbolValue(); - String setUpValue = shouldBeDeletedOrSet(companySymbolValue, shouldBeDeleted); - if (CompanySymbol.TRDC.equalsByKey(companySymbol.getCompanySymbol())) { - company.setTradingCode(setUpValue); - } - if (CompanySymbol.CLRC.equalsByKey(companySymbol.getCompanySymbol())) { - company.setClearingCode(setUpValue); - } - if (CompanySymbol.RGRC.equalsByKey(companySymbol.getCompanySymbol())) { - company.setRegistrationCode(setUpValue); - } - if (CompanySymbol.TAXN.equalsByKey(companySymbol.getCompanySymbol())) { - company.getProfile().setTaxNumber(setUpValue); - } - } - - private String shouldBeDeletedOrSet(String companySymbol, boolean shouldBeDeleted) { - return shouldBeDeleted ? "" : companySymbol; - } -} diff --git a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixTaskListener.java b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixTaskListener.java new file mode 100644 index 000000000..5cd243834 --- /dev/null +++ b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/service/FixTaskListener.java @@ -0,0 +1,73 @@ +package ru.spcex.clearing.fix.service; + +import java.util.Collection; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.company.CompanyRoleSet; +import ru.clearing.classes.statics.data.misc.OrderCurrency; +import ru.spcex.clearing.fix.quickfix.Application; +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.service.QueueConsumer; +import ru.spcex.platform.enumeration.CompanyRole; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; + +@Service +public class FixTaskListener extends QueueConsumer implements InitializingBean { + + private final Logger log = LoggerFactory.getLogger(getClass()); + private final ImdgProvider imdgProvider; + private final Application fixApplication; + private final Imdg companyRoleSetImdg; + private final Imdg orderCurrencyImdg; + + @Autowired + public FixTaskListener(Consumer kafkaQueue, + Producer kafkaProducer, + ImdgProvider imdgProvider, + Application fixApplication) { + super(kafkaQueue, kafkaProducer); + this.imdgProvider = imdgProvider; + this.fixApplication = fixApplication; + this.companyRoleSetImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanyRoleSet, CompanyRoleSet.class); + this.orderCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OrderCurrency, OrderCurrency.class); + } + + @Override + public void afterPropertiesSet() { + callback(LauncherCommandRequest.class) + .setConsumer(this::processSendOrders) + .forDestination(Consts.SDOR_FIX_TASK, callbacks::put); + init(); + } + + private void processSendOrders(BaseRequest request) { + log.info("SDOR[send order] started, request={}", request); + ImdgPredicateBuilder builder = orderCurrencyImdg.predicateBuilder(); + CompanyRoleSet companyRoleSet = companyRoleSetImdg.getFirstObjectByPredicate( + builder.equals("companyRole", CompanyRole.CLCC.getKey()) + ); + + ImdgPredicate clccOrderPredicate = builder.and( + builder.equals("status", "CRET"), + builder.or( + builder.equals("companyId", companyRoleSet.getCompanyId()), + builder.equals("counterPartyId", companyRoleSet.getCompanyId()) + ) + ); + Collection orderCurrencies = orderCurrencyImdg.getCollectionObjectsByPredicate(clccOrderPredicate); + orderCurrencies.forEach(fixApplication::sendOrder); + log.info("SDOR[send order] completed, count orders:{}", orderCurrencies.size()); + } + +} From 5b94202c1a32f628619b744efb8832a29d213eb6 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 22 Apr 2026 12:32:42 +0300 Subject: [PATCH 10/11] =?UTF-8?q?http://jira.mfd.msk:8088/browse/CLS-958?= =?UTF-8?q?=20[3=3F=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B0=20=D0=BE=D1=82=20?= =?UTF-8?q?=D0=A2=D0=A1=20=D0=B8=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=B0=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=81=D1=82=D0=B0=D1=82=D1=83=D1=81=D0=B0?= =?UTF-8?q?=20orderCurrency]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/fix/quickfix/Application.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java index 1e8585ddf..f2d81baf2 100644 --- a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java +++ b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java @@ -13,6 +13,9 @@ import quickfix.fix44.NewOrderSingle; import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.misc.SOrders; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.order.OrderCurrencyStatusUpdateRequest; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgTransaction; @@ -29,13 +32,20 @@ public class Application extends MessageCracker implements quickfix.Application, private final ImdgProvider imdgProvider; private final SocketInitiator initiator; + private final KafkaSender kafkaSender; private SessionID fixSessionID; private SessionID fdcSessionID; @Autowired - public Application(ImdgProvider imdgProvider, MessageStoreFactory storeFactory, SessionSettings settings, LogFactory logFactory, MessageFactory messageFactory) throws ConfigError { + public Application(ImdgProvider imdgProvider, + MessageStoreFactory storeFactory, + SessionSettings settings, + LogFactory logFactory, + MessageFactory messageFactory, + KafkaSender kafkaSender) throws ConfigError { this.imdgProvider = imdgProvider; + this.kafkaSender = kafkaSender; initiator = new SocketInitiator(this, storeFactory, settings, logFactory, messageFactory); } @@ -156,6 +166,11 @@ public class Application extends MessageCracker implements quickfix.Application, sOrdersImdg.update(sOrders); } + + //send message to df for update orderCurrency status + OrderCurrencyStatusUpdateRequest updateRequest = new OrderCurrencyStatusUpdateRequest(); + updateRequest.addId(sOrders.getId()); + kafkaSender.sendRequestToQueue(Consts.ORDER_CURRENCY_STATUS_UPDATE_FIX, updateRequest); } } transaction.commitTransaction(); From 145f4e97d6bd6049811e71a629fabe0075eb7a72 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 22 Apr 2026 13:20:54 +0300 Subject: [PATCH 11/11] http://jira.mfd.msk:8088/browse/CLS-958 --- .../dflt/management/listener/OrderCurrencyListener.java | 7 ++++++- .../java/ru/spcex/clearing/fix/quickfix/Application.java | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/OrderCurrencyListener.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/OrderCurrencyListener.java index bff55340b..53370a842 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/OrderCurrencyListener.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/OrderCurrencyListener.java @@ -358,19 +358,24 @@ public class OrderCurrencyListener extends QueueConsumer implements Initializing continue; } orderCurrency.setStatus(status.getKey()); + orderCurrency.setUpdated(Instant.now()); orderCurrencyImdg.update(orderCurrency); } } private void updateByFix(BaseRequest req) { OrderCurrencyStatusUpdateRequest payload = req.getRequestPayload(); for (Long orderId : payload.getIds()) { - SOrders sOrder = sOrdersImdg.getSingleObjectByID(orderId); + SOrders sOrder = sOrdersImdg.getSingleObjectByPredicate( + sOrdersImdg.predicateBuilder().equals("orderNum", orderId) + ); OrderCurrency orderCurrency = orderCurrencyImdg.getSingleObjectByID(orderId); OrderStatus status = resolveStatusByFixState(sOrder.getState()); if (status == null) { continue; } orderCurrency.setStatus(status.getKey()); + orderCurrency.setUpdated(Instant.now()); +// orderCurrency.setUpdated(sOrder.getTradeDate());//todo orderCurrencyImdg.update(orderCurrency); } } diff --git a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java index f2d81baf2..02445094e 100644 --- a/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java +++ b/clearing-parent/fix-service/src/main/java/ru/spcex/clearing/fix/quickfix/Application.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Service; import quickfix.*; import quickfix.field.*; import quickfix.fix44.ExecutionReport; +import quickfix.fix44.MessageCracker; import quickfix.fix44.NewOrderSingle; import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.misc.SOrders; @@ -105,9 +106,10 @@ public class Application extends MessageCracker implements quickfix.Application, @Override public void fromApp(Message message, SessionID sessionID) throws FieldNotFound, IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType { log.trace("fromApp {}, [{}]: {}", sessionID, message.getClass(), message); + crack(message, sessionID); } - public void onMessage(ExecutionReport executionReport) { + public void onMessage(ExecutionReport executionReport, SessionID sessionID) { ImdgTransaction transaction = imdgProvider.newTransaction(); transaction.beginTransaction(); try { @@ -149,6 +151,7 @@ public class Application extends MessageCracker implements quickfix.Application, sOrders.setAccount(account.getValue()); sOrders.setSettleCode(settlType.getValue()); sOrders.setPriceCurrency(currency.getValue()); + sOrders.setState(String.valueOf(ordStatus.getValue())); if (ordStatus.valueEquals(OrdStatus.NEW)) { sOrders.setOrderDateTime(transactTime.getValue().toInstant(ZoneOffset.UTC)); @@ -169,7 +172,7 @@ public class Application extends MessageCracker implements quickfix.Application, //send message to df for update orderCurrency status OrderCurrencyStatusUpdateRequest updateRequest = new OrderCurrencyStatusUpdateRequest(); - updateRequest.addId(sOrders.getId()); + updateRequest.addId(orderNum); kafkaSender.sendRequestToQueue(Consts.ORDER_CURRENCY_STATUS_UPDATE_FIX, updateRequest); } }