diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java index a79b3bab1..c31f96bc3 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java @@ -183,9 +183,9 @@ public class PaymentInstructionOutboundService { log.debug("PIClearingOutbondActionNewRequest.id={} a__f asset id={}", req.getId(), assets.map(AssetTrio::a__f).map(Registry::getId).orElse(null)); - if (assets.isEmpty() || balanceChecker.insufficientBalance(assets.get().a__f(), + if (assets.isEmpty() || balanceChecker.insufficientBalance2(assets.get().a__f(), tcr.getId(), //never null because validation - accCred.getCurrency(), + currency, amount)) { pmt.setTransactionStatus(TransactionStatus.cher.getKey()); pmt.setUpdated(now); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/BalanceChecker.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/BalanceChecker.java index c94b95059..6e1438c97 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/BalanceChecker.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/BalanceChecker.java @@ -12,6 +12,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.misc.Currency; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.security.CurrencyPairSecurity; import ru.clearing.classes.statics.data.security.Rates; @@ -21,7 +22,9 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames; import static ru.spcex.clearing.util.NumberUtils.safeCast; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryTradingParams; import static ru.spcex.platform.enumeration.RegistryTradingParams.OM_T; +import static ru.spcex.platform.enumeration.RegistryTradingParams.TM_T; import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -53,6 +56,73 @@ public class BalanceChecker { this.balanceCheckOmts = settings.isBalanceCheckOmt(); } + public boolean insufficientBalance2(Registry a__f, + Long tcrId, + Currency currency, + BigDecimal amount) { + if (!balanceCheckOmts || currency == null) { + if (currency == null) { + log.error("{}#id={}#balance={} check for amount {}; currency is null", + a__f.getRegistryCode(), a__f.getId(), a__f.getBalance(), amount); + return false; + } else { + log.info("{}#id={}#balance={}#currency={} check for amount {}; OM*T/TM*T checks disabled", + a__f.getRegistryCode(), a__f.getId(), a__f.getBalance(), currency.getCurrencyCode(), amount); + } + return safeBD(a__f.getBalance()).compareTo(safeBD(amount)) < 0; + } + log.info("{}#id={}#balance={}#currency={} check for amount {}; OM*T/TM*T checks enabled", + a__f.getRegistryCode(), a__f.getId(), a__f.getBalance(), currency.getCurrencyCode(), amount); + LocalDate today = LocalDate.now(); + ImdgPredicateBuilder rgsPb = rgsImdg.predicateBuilder(); + + //для поиска ОМ*Т по tcrId, статусу И предикату + BiFunction rgsAnd = (p, rgsCde) -> rgsPb.and( + rgsPb.sql(RegistryCodeSqlBuilder.getInstance(rgsCde).build()), + rgsPb.equals("tradingClearingRegistryId", tcrId), + rgsPb.or( + rgsPb.equals("registryStatus", RegistryStatus.PROC.getKey()), + rgsPb.equals("registryStatus", RegistryStatus.MNG.getKey()) + ), + rgsPb.equals("securityId", currency.getId()), + p + ); + + Collection tmtToday; + { + ImdgPredicate tmtPrdct = rgsAnd.apply( + rgsPb.equals("settlementDate", today), TM_T + ); + log.debug("searching tmt registries: {}", tmtPrdct); + tmtToday = rgsImdg.getCollectionObjectsByPredicate(tmtPrdct); + } + Collection omtsNotToday; + { + ImdgPredicate omtPrdct = rgsAnd.apply( + rgsPb.not(rgsPb.equals("settlementDate", today)), OM_T + ); + log.debug("searching omt registries: {}", omtPrdct); + omtsNotToday = rgsImdg.getCollectionObjectsByPredicate(omtPrdct); + } + log.debug("a__f.id={} balance checking; tmt today: {}, omt !today: {}", + a__f.getId(), tmtToday.size(), omtsNotToday.size()); + + BigDecimal tmtSum = tmtToday + .stream() + .map(tmt -> safeBD(tmt.getBalance())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal omtSum = omtsNotToday + .stream() + .map(omt -> safeBD(omt.getBalance())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal a__fBalance = safeBD(a__f.getBalance()); + BigDecimal compareValue = tmtSum.subtract(omtSum).add(a__fBalance).max(a__fBalance); + log.info("{}#id={}#balance={} check; tmt sum: {}; omt sum {}; withdrawal amount: {}; check amount: {}", + a__f.getRegistryCode(), a__f.getId(), a__f.getBalance(), tmtSum, omtSum, amount, compareValue + ); + return safeBD(amount).compareTo(compareValue) <= 0; + } + public boolean insufficientBalance(Registry a__f, Long tcrId, String accCurrency,