From 7641b2691c8e056c58c2729a97f5183ecdbefbbf Mon Sep 17 00:00:00 2001 From: ialbert Date: Wed, 22 Nov 2023 19:06:52 +0300 Subject: [PATCH] CS_BLKD --- .../builder/PaymentInstructionBuilderV2.java | 40 +++++++++- .../service/executors/Sdf57Executor.java | 77 +++++++++++++------ .../impl/FormingPaymentInstructionAssets.java | 4 +- 3 files changed, 93 insertions(+), 28 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java index 7a4a5211f..14f4c3792 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java @@ -14,6 +14,9 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.*; 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; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.time.TimeUtil; @@ -21,6 +24,7 @@ import java.math.BigDecimal; import java.time.Instant; import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.util.Collection; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; @@ -30,6 +34,7 @@ public class PaymentInstructionBuilderV2 { private ImdgProvider imdgProvider; private Imdg companyImdg; private Imdg companySymbolsImdg; + private Imdg rgsImdg; private final Imdg clearingCategoryImdg; private final Imdg cmpRoleImdg; private Long sessionId; @@ -44,6 +49,8 @@ public class PaymentInstructionBuilderV2 { private Long addresseeId; private boolean useCS_BLKD = false; + private Registry am_b; + public static PaymentInstructionBuilderV2 builder(ImdgProvider imdgProvider) { return new PaymentInstructionBuilderV2(imdgProvider); } @@ -52,12 +59,17 @@ public class PaymentInstructionBuilderV2 { this.imdgProvider = imdgProvider; this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); + this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.cmpRoleImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanyRoleSet, CompanyRoleSet.class); } - public PaymentInstructionBuilderV2 useCS_BLKD(boolean useCS_BLKD) { - this.useCS_BLKD = useCS_BLKD; + public PaymentInstructionBuilderV2 checkBLKD(Registry rgs) { + if (rgs == null) { + return this; + } + this.useCS_BLKD = true; + this.am_b = rgs; return this; } @@ -142,8 +154,8 @@ public class PaymentInstructionBuilderV2 { payment.setSettlementDate(LocalDate.now()); } - if (useCS_BLKD && categoryVInitiator(senderId) && companyRoleODEPPresent(senderId)) { - payment.setPaymentPurpose(SpecifFlag.CS_BLKD.getKey() + " " + purpose); + if (useCS_BLKD && checkAgent()) { + payment.setPaymentPurpose(SpecifFlag.CS_BLKD.getKey() + "_" + sessionId + " " + purpose); } else { payment.setPaymentPurpose(purpose); } @@ -212,6 +224,26 @@ public class PaymentInstructionBuilderV2 { } } + private boolean checkAgent() { + ImdgPredicateBuilder pb = rgsImdg.predicateBuilder(); + ImdgPredicate prdct = pb.and( + pb.equals("sessionId", sessionId), + pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.CM__).build()), + pb.equals("companyId", addresseeId), + pb.equals("accountId", am_b.getAccountId()) + ); + Collection claims = rgsImdg.getCollectionObjectsByPredicate(prdct); + boolean hasCounterPartyInitiator = false; + for (Registry claim : claims) { + Long counterPartyId = claim.getCounterPartyId(); + if (categoryVInitiator(counterPartyId) && companyRoleODEPPresent(counterPartyId)) { + hasCounterPartyInitiator = true; + break; + } + } + return hasCounterPartyInitiator; + } + public boolean categoryVInitiator(Long companyId) { ClearingMemberCategory category = clearingCategoryImdg.getFirstObjectByFieldValues( Map.of("companyId", companyId)); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java index c1638189a..9597c3734 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java @@ -48,6 +48,7 @@ import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; 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.log.ExceptionUtils; import ru.spcex.platform.utils.text.TextUtil; import ru.spcex.platform.utils.validation.IValidator; @@ -62,6 +63,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.function.Function; +import java.util.regex.Matcher; import java.util.regex.Pattern; import static ru.spcex.platform.enumeration.RegistryTradingParams.D__V; @@ -361,13 +363,13 @@ public class Sdf57Executor extends AbstractExecutor { if (TextUtil.isEmpty(asts.a__t().getTradingClearingRegistry())) { log.trace("stmt.id={} {}.id={} TCR is empty, skipping gateway request", stmt.getId(), asts.a__t().getRegistryCode(), asts.a__t().getId()); - } else if (TextUtil.isEmpty(sdf57.getSpecif()) - || !sdf57.getSpecif().contains(SpecifFlag.CS_BLKD.getKey())) { + } else { log.trace("sending gateway request for stmt.id={}", stmt.getId()); - kafka.sendRequestToQueue(Consts.ASSET_OPERATION, - gatewayRequest(stmt, - company.getTradingCode(), - asts.a__t().getTradingClearingRegistry())); + Optional gtwReq = gatewayRequest(stmt, + company, + account, + asts.a__t().getTradingClearingRegistry()); + gtwReq.ifPresent(r -> kafka.sendRequestToQueue(Consts.ASSET_OPERATION, r)); } } return Optional.of(asts); @@ -735,25 +737,56 @@ public class Sdf57Executor extends AbstractExecutor { R apply(T1 arg1, T2 arg2, T3 arg3); } - private AssetOperationListRequest gatewayRequest(Statement stmt, String tradingCode, String tcrCode) { + private static final Pattern csBlkd = Pattern.compile(SpecifFlag.CS_BLKD.getKey() + "_(\\d+).*"); + + private Optional gatewayRequest(Statement stmt, Company company, Account account, String tcrCode) { + if (AccountType.Anlt.equalsByKey(account.getAccountType())) { + return Optional.empty(); + } + String tradingCode = company.getTradingCode(); AssetOperationListRequest gatewayRequest = new AssetOperationListRequest(); AssetOperationRequest req = GatewayRequestCreator.from(stmt, tradingCode, tcrCode); - Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of( - "workflowStatus", SessionStatus.ACTV.getKey() - )); - if (existActiveSession != null) { - log.debug("active session.id={} type {}", existActiveSession.getId(), existActiveSession.getSessionType()); - List d__vs = assets.searchByParams(stmt.getAccount(), CurrencyCode.RUB.getKey(), stmt.getSenderId(), D__V) - .stream() - .filter(rgs -> existActiveSession.getId().equals(rgs.getSessionId())) - .toList(); - BigDecimal d__vSum = d__vs.stream() - .map(rgs -> safeBD(rgs.getBalance())) - .reduce(BigDecimal.ZERO, BigDecimal::add); - BigDecimal amount = req.getAmount(); - req.setAmount(safeBD(amount).subtract(d__vSum)); + String specif = stmt.getComment(); + + Matcher m; + if (!TextUtil.isEmpty(specif) && (m = csBlkd.matcher(specif)).find()) { + try { + Long sessionId = Long.valueOf(m.group(1)); + List d__vs = assets.searchByParams(account.getAccount(), CurrencyCode.RUB.getKey(), company.getId(), D__V) + .stream() + .filter(rgs -> sessionId.equals(rgs.getSessionId())) + .toList(); + BigDecimal d__vSum = d__vs.stream() + .map(rgs -> safeBD(rgs.getBalance())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal amount = req.getAmount(); + req.setAmount(safeBD(amount).subtract(d__vSum)); + } catch (NumberFormatException e) { + log.error("stmt.id={} failed to parse specif {} {}", + stmt.getId(), + specif, + ExceptionUtils.getStackTrace(e)); + } + } + //Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of( + // "workflowStatus", SessionStatus.ACTV.getKey() + //)); + //if (existActiveSession != null) { + // log.debug("active session.id={} type {}", existActiveSession.getId(), existActiveSession.getSessionType()); + // List d__vs = assets.searchByParams(stmt.getAccount(), CurrencyCode.RUB.getKey(), stmt.getSenderId(), D__V) + // .stream() + // .filter(rgs -> existActiveSession.getId().equals(rgs.getSessionId())) + // .toList(); + // BigDecimal d__vSum = d__vs.stream() + // .map(rgs -> safeBD(rgs.getBalance())) + // .reduce(BigDecimal.ZERO, BigDecimal::add); + // BigDecimal amount = req.getAmount(); + // req.setAmount(safeBD(amount).subtract(d__vSum)); + //} + if (req.getAmount().compareTo(BigDecimal.ZERO) == 0) { + return Optional.empty(); } gatewayRequest.setAssetOperationRequests(List.of(req)); - return gatewayRequest; + return Optional.of(gatewayRequest); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java index 30a2b7b47..31304592f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java @@ -215,7 +215,8 @@ public class FormingPaymentInstructionAssets implements ISessionStage { .creditLegAccount(creditLegAccount) .amount(amount) .sessionId(sessionId) - .useCS_BLKD(SessionType.FINL.equals(sessionType) || SessionType.MEDM.equals(sessionType)) + .checkBLKD((SessionType.FINL.equals(sessionType) || SessionType.MEDM.equals(sessionType)) + && !isPositiveBalance ? registry : null) .purpose(String.format("Перевод по итогу клиринга по ТКР %s", registry.getTradingClearingRegistry())); PaymentInstruction paymentInstruction = paymentInstructionBuilder.build(); log.debug("Created paymentInstruction by registry.id: {}", registry.getId()); @@ -282,7 +283,6 @@ public class FormingPaymentInstructionAssets implements ISessionStage { .sender(senderId) .addressee(addresseeId) .debitLegAccount(debitLegAccount) - .useCS_BLKD(SessionType.FINL.equals(sessionType) || SessionType.MEDM.equals(sessionType)) .creditLegAccount(creditLegAccount) .amount(amount) .sessionId(sessionId)