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 ee580c27d..d4c44da16 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 @@ -207,11 +207,13 @@ public class ValidationConfig { context.addImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, imdgMoneyMarketSecurity); context.addImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, fixedIncomeSecurityImdg); context.addImdg(IMDGDistributedNames.Map_EquitySecurity, equitySecurityImdg); + context.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry); context.setLogPrefix(LogPrefixId.INSTANCE); return new ValidatorImpl<>(context, CompanyByTradingCodeValidationRule.instance(SDf21::getDepoCodeCl), Sdf21ValidationRule.AccountPresent, - SecurityBySecurityCodeValidationRule.instance(SDf21::getSecurityCode) + SecurityBySecurityCodeValidationRule.instance(SDf21::getSecurityCode), + Sdf21ValidationRule.TransactionNumberProcessed ); }; } @@ -352,12 +354,15 @@ public class ValidationConfig { ctx.addImdg(IMDGDistributedNames.Map_Account, imdgAccount); ctx.addImdg(IMDGDistributedNames.Map_TradingClearingRegistry, imdgTradingClearingRegistry); ctx.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry); + ctx.addImdg(IMDGDistributedNames.Map_FixedIncomeSecurity , fixedIncomeSecurityImdg); + ctx.addImdg(IMDGDistributedNames.Map_MoneyMarketSecurity , imdgMoneyMarketSecurity); + ctx.addImdg(IMDGDistributedNames.Map_EquitySecurity , equitySecurityImdg); return new ValidatorImpl<>(ctx, Sdf20ValidationRule.AccountPresent, Sdf20ValidationRule.CompanyPresent, + Sdf20ValidationRule.SecurityPresent, Sdf20ValidationRule.TCRPresent, - Sdf20ValidationRule.DS_TFound, - Sdf20ValidationRule.AS_TFound); + Sdf20ValidationRule.AssetsPresent); }; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java index 49e05c2cd..01dbb950e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java @@ -20,6 +20,7 @@ public enum ClearingError implements IErrorEnumId { AccountNotActive(5415L), SecurityNotFound(5416L), AccountNotPresent(5417L), + SuchRecordAlreadyExists(5405L), TradingClearingRegistryNotFound(5418L), TradingClearingRegistryNotActive(5419L), ClearingUnavailableForCompany(5421L), diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTBFProcessing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTBFProcessing.java index b3a775a73..7aad750c1 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTBFProcessing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTBFProcessing.java @@ -3,11 +3,12 @@ package ru.spcex.clearing.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.platform.enumeration.CurrencyCode; -import ru.spcex.platform.enumeration.RegistryTradingParams; -import ru.spcex.platform.enumeration.RegistryUnit; +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.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -50,6 +51,18 @@ public class AssetTBFProcessing { rgsImdg.update(am_f); } + public void processWithoutChangingB(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) { + safeWrapField(am_t::getBalance, am_t::setBalance); + safeWrapField(am_b::getBalance, am_b::setBalance); + safeWrapField(am_f::getBalance, am_f::setBalance); + Instant now = Instant.now(); + + am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance())); + am_f.setUpdated(now); + + rgsImdg.update(am_f); + } + public void processByAm_b(Registry am_b, BigDecimal sum) { Optional am_f = rgsMng.findRegByUnit(am_b.getCompanyId(), am_b.getAccountId(), @@ -66,6 +79,46 @@ public class AssetTBFProcessing { } } + public AssetTrio createSAssets(Account acc, + String securitySymbol, + Long securityId, + String tcrType, + Long tcrId, + String tcr, + Company company) { + Registry ast = new Registry(); + ast.setCreated(Instant.now()); + ast.setSecuritySymbol(securitySymbol); + ast.setSecurityId(securityId); + ast.setAccountId(acc.getId()); + ast.setAccount(acc.getAccount()); + ast.setAccountType(acc.getAccountType()); + ast.setRegistryDesignation(RegistryDesignation.A.getKey()); + ast.setRegistryInstrumentType(RegistryInstrumentType.S.getKey()); + ast.setRegistryCapacity(tcrType); + ast.setRegistryUnit(RegistryUnit.T.getKey()); + ast.setRegistryCode(RegistryUtil.clearingCode(ast)); + ast.setClearingCode(company.getClearingCode()); + ast.setTradingCode(company.getClearingCode()); + ast.setCompanyId(company.getId()); + ast.setShortName(company.getShortName()); + ast.setFullName(company.getFullName()); + ast.setTradingClearingRegistryId(tcrId); + ast.setTradingClearingRegistry(tcr); + ast.setRegistryStatus(RegistryStatus.OK.getKey()); + ast.setBalanceDimension(BalanceDimension.PICS.getKey()); + RegistryManager.zeroState(ast); + Registry asf = ast.clone(); + asf.setRegistryUnit(RegistryUnit.F.getKey()); + asf.setRegistryCode(RegistryUtil.clearingCode(asf)); + RegistryManager.zeroState(asf); + Registry asb = ast.clone(); + asb.setRegistryUnit(RegistryUnit.B.getKey()); + asb.setRegistryCode(RegistryUtil.clearingCode(asb)); + RegistryManager.zeroState(asb); + return new AssetTrio(asf, asb, ast); + } + public Optional searchMoneyByAccAndCompany(Long companyId, Long accountId) { ImdgPredicateBuilder pb = rgsImdg.predicateBuilder(); Function prdct = rgsCode -> pb.and( diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTrio.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTrio.java index 6045b2ebe..7881223e3 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTrio.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/AssetTrio.java @@ -2,5 +2,5 @@ package ru.spcex.clearing.service; import ru.clearing.classes.statics.data.registry.Registry; -public record AssetTrio(Registry am_f, Registry am_b, Registry am_t) { +public record AssetTrio(Registry a__f, Registry a__b, Registry a__t) { } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryManager.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryManager.java index f0b201770..fc230848d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryManager.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryManager.java @@ -15,6 +15,7 @@ import ru.spcex.platform.imdg.api.predicate.specific.RegistryDm_tClrnPredicate; import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.text.TextUtil; +import java.math.BigDecimal; import java.util.Optional; import static ru.spcex.platform.enumeration.RegistryTradingParams.DM_T; @@ -108,6 +109,23 @@ public class RegistryManager { ); } + public Optional searchByAccSec(Long accountId, String securitySymbol, RegistryTradingParams rgsCde) { + if (TextUtil.isEmpty(securitySymbol) + || accountId == null + || rgsCde == null) + return Optional.empty(); + ImdgPredicateBuilder pb = rgsImdg.predicateBuilder(); + return Optional.ofNullable( + rgsImdg.getSingleObjectByPredicate( + pb.and( + pb.sql(RegistryCodeSqlBuilder.getInstance(rgsCde).build()), + pb.equals("accountId", accountId), + pb.equals("securitySymbol", securitySymbol) + ) + ) + ); + } + public Optional searchDmtClrn(Registry rgs) { ImdgPredicate dmtClrnPrdct = RegistryDm_tClrnPredicate .instance(rgs.getCompanyId(), rgs.getCounterPartyId()) @@ -144,6 +162,14 @@ public class RegistryManager { return Optional.ofNullable(rgsImdg.getSingleObjectByPredicate(prdct)); } + public static void zeroState(Registry rgs) { + rgs.setBalance(BigDecimal.ZERO); + rgs.setDebit(BigDecimal.ZERO); + rgs.setCredit(BigDecimal.ZERO); + rgs.setDiffBalance(BigDecimal.ZERO); + rgs.setCheckBalance(BigDecimal.ZERO); + } + public static boolean equalsByCode(RegistryTradingParams code, Registry rgs) { return code.equalByRegistry( 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 83e4419b1..341910cc0 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 @@ -206,8 +206,7 @@ public class Sdf10Executor { Function> plannerByTask = task -> { ImdgPredicate plannerPrdct = pb.and( pb.equals("task", task.getKey()), - pb.equals("taskStatus", TaskStatus.Active.getKey()), - pb.equals("clearingDate", LocalDate.now()) + pb.equals("taskStatus", TaskStatus.Active.getKey()) ); return Optional.ofNullable(plannerAllTodayImdg.getFirstObjectByPredicate(plannerPrdct)); }; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf20Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf20Executor.java index d3a55b0d0..aa29c8994 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf20Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf20Executor.java @@ -5,10 +5,13 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.sdf.SDf20; +import ru.clearing.classes.statics.data.security.Security; +import ru.clearing.classes.statics.data.statement.Statement; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; @@ -16,10 +19,12 @@ import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationListRequest; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationRequest; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.AssetTBFProcessing; +import ru.spcex.clearing.service.AssetTrio; import ru.spcex.clearing.service.RegistryManager; import ru.spcex.clearing.service.validation.ValidationStored; -import ru.spcex.platform.enumeration.InOutDirection; -import ru.spcex.platform.enumeration.RegistryStatus; +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.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -29,31 +34,38 @@ 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.Optional; import java.util.function.Function; +import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; + @Service public class Sdf20Executor { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg sDf20Imdg; private final Imdg rgsImdg; + private final Imdg stmtImdg; private final Function validation; private final IMessageResolver msgRslv; private final KafkaSender kafka; + private final AssetTBFProcessing assetsMng; @Autowired public Sdf20Executor(ImdgProvider imdgProvider, Function validation, IMessageResolver msgRslv, RegistryManager rgsMng, - @Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafka) { + @Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafka, AssetTBFProcessing assetsMng) { this.sDf20Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf20, SDf20.class); this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.stmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.validation = validation; this.msgRslv = msgRslv; this.kafka = kafka; + this.assetsMng = assetsMng; } public void execute(BaseRequest systemRequest) { @@ -71,36 +83,71 @@ public class Sdf20Executor { log.error("sdf20.id={} error {}", sDf20.getId(), msgRslv.resolve(err.get())); return; } + BigDecimal quantity = safeBD(BigDecimalUtil.parseLeadingZeroes(sDf20.getQuantity())); + if ("ADDFREE".equalsIgnoreCase(sDf20.getOperationCode())) { + quantity = quantity; + } else if ("DELFREE".equals(sDf20.getOperationCode())) { + quantity = quantity.negate(); + } Registry ds_t = validator.getStored(ValidationStored.Sdf20Dst); - Registry as_t = validator.getStored(ValidationStored.Sdf20Ast); - Company company = validator.getStored(ValidationStored.Sdf20Company); + AssetTrio assets = validator.getStored(ValidationStored.Sdf20Ast); + Company cmp = validator.getStored(ValidationStored.Sdf20Company); + Account acc = validator.getStored(ValidationStored.Sdf20Account); + Security security = validator.getStored(ValidationStored.Sdf20Security); TradingClearingRegistry tcr = validator.getStored(ValidationStored.Sdf20Tcr); - log.debug("sdf20.id={}, found as_t.id={}, ds_t.id={}", sDf20.getId(), as_t.getId(), ds_t.getId()); + + if (assets == null) { + log.debug("assets were not found for sdf20.id={} creating", sDf20.getId()); + assets = assetsMng.createSAssets( + acc, + sDf20.getSecurity(), + security.getId(), + tcr.getTradingClearingRegistryType(), + tcr.getId(), + tcr.getCode(), + cmp + ); + rgsImdg.insert(assets.a__t()); + rgsImdg.insert(assets.a__f()); + rgsImdg.insert(assets.a__b()); + } + if (ds_t == null) { + log.debug("DS*T were not found for sdf20.id={} creating", sDf20.getId()); + ds_t = assets.a__t().clone(); + ds_t.setRegistryDesignation(RegistryDesignation.D.getKey()); + ds_t.setRegistryCode(RegistryUtil.clearingCode(ds_t)); + rgsImdg.insert(ds_t); + } + Registry as_t = assets.a__t(); ds_t.setComment(sDf20.getTransactionNumber()); + ds_t.setContract(sDf20.getInDocument()); ds_t.setRegistryStatus(RegistryStatus.OK.getKey()); ds_t.setUpdated(now); - - BigDecimal quantity = BigDecimalUtil.parseLeadingZeroes(sDf20.getQuantity()); - BigDecimal balance = BigDecimalUtil.safeBD(as_t.getBalance()); - if ("ADDFREE".equalsIgnoreCase(sDf20.getOperationCode())) { - as_t.setBalance(balance.add(quantity)); - } else if ("DELFREE".equals(sDf20.getOperationCode())) { - as_t.setBalance(balance.subtract(quantity)); - } + ds_t.setBalance(safeBD(ds_t.getBalance()).add(quantity)); + as_t.setBalance(safeBD(as_t.getBalance()).add(quantity)); as_t.setCheckBalance(BigDecimalUtil.parseLeadingZeroes(sDf20.getCloseBalance())); as_t.setUpdated(now); - - rgsImdg.update(ds_t); rgsImdg.update(as_t); + rgsImdg.update(ds_t); + assetsMng.process(assets.a__b(), assets.a__t(), assets.a__f(), BigDecimal.ZERO); + //statement recfree in + //statement delfree out + Statement statement = createStatement(cmp.getId(), acc, quantity, sDf20.getId(), sDf20.getTransactionNumber(), security.getId()); + stmtImdg.insert(statement); + log.debug("sdf20.id={}, processing as_t.id={}, as_f.id={}, as_b.id={}, ds_t.id={}. statement.id={}", + sDf20.getId(), + assets.a__t().getId(), assets.a__f().getId(), assets.a__b().getId(), + ds_t.getId(), + statement.getId()); //send gateway { Collection requests = new ArrayList<>(); AssetOperationRequest req = requestFromStatement( - quantity, + BigDecimalUtil.parseLeadingZeroes(sDf20.getQuantity()), sDf20.getSecurity(), - company.getTradingCode(), + cmp.getTradingCode(), tcr.getCode() ); requests.add(req); @@ -125,4 +172,33 @@ public class Sdf20Executor { req.setDirection(InOutDirection.in.getKey()); return req; } + + private Statement createStatement(Long companyId, + Account account, + BigDecimal quantity, + Long sdf20Id, + String transactionNumber, + Long securityId) { + Statement stmt = new Statement(); + stmt.setAddresseeId(companyId); + stmt.setSenderId(Sender.Prc.getId()); + stmt.setStatementType(StatementType.incr.getKey()); + //fixme stmt.setComment(sdf10.()); + stmt.setAccountId(account.getId()); + stmt.setAccount(account.getAccount()); + stmt.setSecurityId(securityId); + if (quantity.compareTo(BigDecimal.ZERO) >= 0) { + stmt.setInOutDirection(InOutDirection.in.getKey()); + } else { + stmt.setInOutDirection(InOutDirection.out.getKey()); + } + stmt.setAmount(quantity.abs()); + stmt.setOperationStatus(OperationStatus.Executed.getKey()); + stmt.setInSDfId(sdf20Id); + stmt.setInOutSDfType(InOutSDfType.type20.getKey()); + stmt.setClearingDate(LocalDate.now()); + stmt.setComment(transactionNumber); + stmt.setCreated(Instant.now()); + return stmt; + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf21Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf21Executor.java index 280109394..98a02d682 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf21Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf21Executor.java @@ -142,7 +142,7 @@ public class Sdf21Executor extends AbstractExecutor { IValidator validator = sDf21Validator.apply(sdf21); Optional error = validator.tillFirstError(); if (error.isPresent()) { - log.error("error while validating sdf21.id={} - {}", sdf21.getId(), messageResolver.resolve(error.get())); + log.info("skipping after validating sdf21.id={} - {}", sdf21.getId(), messageResolver.resolve(error.get())); continue; } Company company = validator.getStored(ValidationStored.CompanyByTradingCode); 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 144ecbf53..9797cb61d 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 @@ -136,17 +136,17 @@ public class PaymentInstructionOutboundService { pmtImdg.insert(pmt); log.debug("new PaymentInstruction.id: {}", pmt.getId()); Optional assets = assetsMng.searchMoneyByAccAndCompany(addressee.getId(), accCred.getId()); - if (assets.isEmpty() || assetsMng.insufficientBalance(assets.get().am_f(), amount)) { + if (assets.isEmpty() || assetsMng.insufficientBalance(assets.get().a__f(), amount)) { pmt.setTransactionStatus(TransactionStatus.cher.getKey()); pmt.setUpdated(now); pmtImdg.update(pmt); log.debug("insufficient balance, pmt.id: {}, am*f.balance={}", - pmt.getId(), assets.map(AssetTrio::am_f).map(Registry::getBalance).orElse(null)); + pmt.getId(), assets.map(AssetTrio::a__f).map(Registry::getBalance).orElse(null)); return error(req.getId(), ClearingError.BalanceInsufficient); } log.debug("assets found and balance is ok. am*b.id={}, am*t.id={}, am*f.id={}", - assets.get().am_b().getId(), assets.get().am_t().getId(), assets.get().am_f().getId()); - assetsMng.process(assets.get().am_b(), assets.get().am_t(), assets.get().am_f(), amount.negate()); + assets.get().a__b().getId(), assets.get().a__t().getId(), assets.get().a__f().getId()); + assetsMng.process(assets.get().a__b(), assets.get().a__t(), assets.get().a__f(), amount.negate()); SDf54 sDf54 = sdf54Creator.create(pmt); sDf54.setId(idGenerator.nextId()); sDf54.setGenerationId(pmt.getId()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf20ValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf20ValidationRule.java index 8c9234457..427576ab7 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf20ValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf20ValidationRule.java @@ -7,11 +7,14 @@ import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.sdf.SDf20; +import ru.clearing.classes.statics.data.security.Security; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.AssetTrio; import ru.spcex.clearing.service.RegistryManager; import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.text.TextUtil; @@ -20,8 +23,7 @@ import ru.spcex.platform.utils.validation.IValidationRule; import java.util.Map; import java.util.Optional; -import static ru.spcex.platform.enumeration.RegistryTradingParams.AS_T; -import static ru.spcex.platform.enumeration.RegistryTradingParams.DS_T; +import static ru.spcex.platform.enumeration.RegistryTradingParams.*; public enum Sdf20ValidationRule implements IValidationRule> { AccountPresent() { @@ -34,7 +36,7 @@ public enum Sdf20ValidationRule implements IValidationRule accImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); Account acc = accImdg.getFirstObjectBySQL("account = '%s' and accountType = '%s'" - .formatted(depoCodeCl, AccountType.Clrn.getKey())); + .formatted(depoCodeCl, AccountType.Depo.getKey())); if (acc == null) { return of(ClearingError.AccountNotFoundB, depoCodeCl); } @@ -60,6 +62,26 @@ public enum Sdf20ValidationRule implements IValidationRule validate(ImdgValidationContext context) { + SDf20 sDf20 = context.getValidatedObject(); + String security = sDf20.getSecurity(); + if (TextUtil.isEmpty(security)) { + return of(ClearingError.SecurityNotFound, security); + } + SecuritySelector slctr = new SecuritySelector<>( + context.obtainMap(IMDGDistributedNames.Map_FixedIncomeSecurity, Security.class), + context.obtainMap(IMDGDistributedNames.Map_MoneyMarketSecurity, Security.class), + context.obtainMap(IMDGDistributedNames.Map_EquitySecurity, Security.class) + ); + Security securityFound = slctr.selectSecurityBySymbol(security); + if (securityFound == null) { + return of(ClearingError.SecurityNotFound, security); + } + context.storeObject(ValidationStored.Sdf20Security, securityFound); + return empty(); + } }, TCRPresent() { @Override @@ -79,7 +101,7 @@ public enum Sdf20ValidationRule implements IValidationRule validate(ImdgValidationContext context) { SDf20 sDf20 = context.getValidatedObject(); @@ -92,14 +114,11 @@ public enum Sdf20ValidationRule implements IValidationRule rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class); RegistryManager rgsMng = new RegistryManager(rgsImdg); Optional ds_t = rgsMng.searchByAccSecContract(acc.getId(), security, inDocument, DS_T); - if (ds_t.isEmpty()) { - return of(ClearingError.RecordNotFound, "DS*T"); - } - context.storeObject(ValidationStored.Sdf20Dst, ds_t.get()); + ds_t.ifPresent(registry -> context.storeObject(ValidationStored.Sdf20Dst, registry)); return empty(); } }, - AS_TFound() { + AssetsPresent() { @Override public Optional validate(ImdgValidationContext context) { SDf20 sDf20 = context.getValidatedObject(); @@ -107,15 +126,20 @@ public enum Sdf20ValidationRule implements IValidationRule rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class); RegistryManager rgsMng = new RegistryManager(rgsImdg); - Optional as_t = rgsMng.searchByAccSecContract(acc.getId(), security, inDocument, AS_T); - if (as_t.isEmpty()) { - return of(ClearingError.RecordNotFound, "AS*T"); + Optional as_t = rgsMng.searchByAccSec(acc.getId(), security, AS_T); + Optional as_f = rgsMng.searchByAccSec(acc.getId(), security, AS_F); + Optional as_b = rgsMng.searchByAccSec(acc.getId(), security, AS_B); + if (as_t.isPresent() && as_f.isPresent() && as_b.isPresent()) { + context.storeObject(ValidationStored.Sdf20Ast, new AssetTrio(as_f.get(), as_b.get(), as_t.get())); + return empty(); + } + if (as_t.isPresent() || as_f.isPresent() || as_b.isPresent()) { + return of(ClearingError.RecordNotFound, "AS*T/AS*F/AS*B"); } - context.storeObject(ValidationStored.Sdf20Ast, as_t.get()); return empty(); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf21ValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf21ValidationRule.java index e8cc5ae92..55319d349 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf21ValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf21ValidationRule.java @@ -1,11 +1,15 @@ package ru.spcex.clearing.service.validation; import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.sdf.SDf21; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.RegistryTradingParams; import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.text.TextUtil; @@ -33,6 +37,24 @@ public enum Sdf21ValidationRule implements IValidationRule validate(ImdgValidationContext context) { + SDf21 sdf21 = context.getValidatedObject(); + Imdg rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class); + ImdgPredicateBuilder pb = rgsImdg.predicateBuilder(); + Registry ds_t = rgsImdg.getFirstObjectByPredicate( + pb.and( + pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.DS_T).build()), + pb.equals("comment", sdf21.getTransactionNumber()) + ) + ); + if (ds_t != null) { + return of(ClearingError.SuchRecordAlreadyExists); + } + return empty(); + } }; @Override 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 2ba109dc3..79938a220 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 @@ -22,7 +22,7 @@ public enum ValidationStored { CompanyByTradingCode, - Sdf20Account, Sdf20Company, Sdf20Tcr, Sdf20Dst, Sdf20Ast, + Sdf20Account, Sdf20Company, Sdf20Tcr, Sdf20Dst, Sdf20Ast, Sdf20Security, SecurityBySecurityCode } diff --git a/clearing-parent/swt-importer/src/main/java/ru/spcex/clearing/swt/importer/logic/data/tables/SDf20Table.java b/clearing-parent/swt-importer/src/main/java/ru/spcex/clearing/swt/importer/logic/data/tables/SDf20Table.java index 9b62a4b7e..db31c1b63 100644 --- a/clearing-parent/swt-importer/src/main/java/ru/spcex/clearing/swt/importer/logic/data/tables/SDf20Table.java +++ b/clearing-parent/swt-importer/src/main/java/ru/spcex/clearing/swt/importer/logic/data/tables/SDf20Table.java @@ -30,6 +30,7 @@ public class SDf20Table extends AbstractTable { result.setDepoCodeCorr(record.getValFor87DTag()); result.setOperationDate(record.getValFor30Tag()); result.setCloseBalance(record.getValFor62ATag()); + result.setTransactionNumber(record.getValFor23Tag()); result.setFileName(filename); result.setGenerationTime(Instant.now()); result.setGenerationId(fileId); diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutSDfType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutSDfType.java index 825614851..52c65dc25 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutSDfType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutSDfType.java @@ -10,6 +10,7 @@ public enum InOutSDfType implements IEnumKey { type57("57"), type08("0809"), type10("1011"), + type20("20"), type21("21"), ;