Compare commits

...
Sign in to create a new pull request.

4 commits

20 changed files with 491 additions and 93 deletions

View file

@ -204,10 +204,16 @@ public class Registry extends BusinessObject implements Cloneable {
} }
public BigDecimal getBalance() { public BigDecimal getBalance() {
if (balance == null) {
balance = BigDecimal.ZERO;
}
return balance; return balance;
} }
public void setBalance(BigDecimal balance) { public void setBalance(BigDecimal balance) {
if (balance == null) {
balance = BigDecimal.ZERO;
}
this.balance = balance; this.balance = balance;
} }

View file

@ -0,0 +1,15 @@
package ru.spcex.clearing.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
@Configuration
public class RequestHelperConfiguration {
@Bean
public RequestHelper reqHelper(IMessageResolver msgRslv) {
return new RequestHelper(msgRslv, ClearingError.GeneralError);
}
}

View file

@ -13,6 +13,7 @@ import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity;
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity; import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
import ru.clearing.classes.statics.data.misc.STrades; import ru.clearing.classes.statics.data.misc.STrades;
import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.misc.Session;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.sdf.*; import ru.clearing.classes.statics.data.sdf.*;
@ -23,8 +24,10 @@ import ru.clearing.platform.dictionary.InOutDirectionDictionary;
import ru.clearing.platform.dictionary.SectionDictionary; import ru.clearing.platform.dictionary.SectionDictionary;
import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
import ru.spcex.clearing.service.validation.*; import ru.spcex.clearing.service.validation.*;
@ -65,6 +68,9 @@ public class ValidationConfig {
Imdg<SectionDictionary> imdgSectionDictionary; Imdg<SectionDictionary> imdgSectionDictionary;
Imdg<Statement> imdgStatement; Imdg<Statement> imdgStatement;
Imdg<InOutDirectionDictionary> imdgInOutDirection; Imdg<InOutDirectionDictionary> imdgInOutDirection;
Imdg<SDf55> sDf55Imdg;
Imdg<SDf54> sDf54Imdg;
Imdg<PaymentInstruction> pmtImdg;
ImdgProvider imdgProvider; ImdgProvider imdgProvider;
public ValidationConfig(ImdgProvider imdgProvider) { public ValidationConfig(ImdgProvider imdgProvider) {
@ -84,6 +90,9 @@ public class ValidationConfig {
this.imdgStatement = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.imdgStatement = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.imdgDepoAccount = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); this.imdgDepoAccount = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class);
this.imdgInOutDirection = imdgProvider.getImdg(IMDGDistributedNames.Map_InOutDirectionDictionary, InOutDirectionDictionary.class); this.imdgInOutDirection = imdgProvider.getImdg(IMDGDistributedNames.Map_InOutDirectionDictionary, InOutDirectionDictionary.class);
this.sDf55Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf55, SDf55.class);
this.sDf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class);
this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
} }
@ -343,6 +352,22 @@ public class ValidationConfig {
}; };
} }
@Bean("statusExtractValidator")
public Function<RegistryChangeStatusExtractRequest, IValidator> statusExtractValidator() {
return statusExtractRequest -> {
ImdgValidationContext<RegistryChangeStatusExtractRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(statusExtractRequest);
context.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry);
context.setLogPrefix(LogPrefixId.INSTANCE);
return new ValidatorImpl<>(context,
StatusExtractValidationRule.Fields,
new PresentById(IMDGDistributedNames.Map_Registry, ClearingError.RecordNotFound, true),
StatusExtractValidationRule.ContractCheck,
StatusExtractValidationRule.RegistryStatusValid
);
};
}
@Bean("splitDepositValidator") @Bean("splitDepositValidator")
public Function<RegistrySplitDepositActionRequest, IValidator> splitDepositValidator() { public Function<RegistrySplitDepositActionRequest, IValidator> splitDepositValidator() {
return refundDateRequest -> { return refundDateRequest -> {
@ -415,6 +440,26 @@ public class ValidationConfig {
}; };
} }
@Bean
public Function<StatementRequest, IValidator> sdf55ExecutorValidation() {
return req -> {
ImdgValidationContext<StatementRequest> ctx = new ImdgValidationContext<>();
ctx.setValidatedObject(req);
ctx.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry);
ctx.addImdg(IMDGDistributedNames.Map_SDf55, sDf55Imdg);
ctx.addImdg(IMDGDistributedNames.Map_SDf54, sDf54Imdg);
ctx.addImdg(IMDGDistributedNames.Map_PaymentInstruction, pmtImdg);
ctx.addImdg(IMDGDistributedNames.Map_TradingClearingRegistry, imdgTradingClearingRegistry);
return new ValidatorImpl<>(ctx,
Sdf55ValidationRule.Fields,
Sdf55ValidationRule.GenerationIdFound,
Sdf55ValidationRule.Sdf54Present,
Sdf55ValidationRule.PaymentInstructionPresent,
Sdf55ValidationRule.TcrPresent,
Sdf55ValidationRule.AssetsPresent);
};
}
@Bean("userRoleVerification") @Bean("userRoleVerification")
public UserRoleVerification userRoleVerification(ImdgProvider imdgProvider, IMessageResolver msgs) { public UserRoleVerification userRoleVerification(ImdgProvider imdgProvider, IMessageResolver msgs) {
return new UserRoleVerification(imdgProvider, msgs, ClearingError.UserVerifyDenial); return new UserRoleVerification(imdgProvider, msgs, ClearingError.UserVerifyDenial);

View file

@ -0,0 +1,20 @@
package ru.spcex.clearing.error;
import ru.spcex.platform.utils.enumeration.IErrorEnumId;
public enum RgsError implements IErrorEnumId {
A__tNotFound(5700L)
;
private final Long id;
RgsError(Long id) {
this.id = id;
}
@Override
public Long getId() {
return id;
}
}

View file

@ -6,10 +6,12 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.CreateRegistryRequest; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.CreateRegistryRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
@ -17,6 +19,7 @@ import ru.spcex.clearing.platform.messaging.service.Status;
import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.clearing.session.stage.util.RegistryUtil; import ru.spcex.clearing.session.stage.util.RegistryUtil;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.platform.enumeration.*; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
@ -46,24 +49,29 @@ public class RegistryService {
private final Imdg<Registry> registryImdg; private final Imdg<Registry> registryImdg;
private final Function<RegistryReturnDepositRequest, IValidator> returnDepositVal; private final Function<RegistryReturnDepositRequest, IValidator> returnDepositVal;
private final Function<RegistryChangeRefundDateRequest, IValidator> refundDateVal; private final Function<RegistryChangeRefundDateRequest, IValidator> refundDateVal;
private final Function<RegistryChangeStatusExtractRequest, IValidator> statusExtractVal;
private final Function<RegistrySplitDepositActionRequest, IValidator> splitDepositActionVal; private final Function<RegistrySplitDepositActionRequest, IValidator> splitDepositActionVal;
private final IMessageResolver msgResolver; private final IMessageResolver msgResolver;
private final RequestHelper reqHelp;
private final UserRoleVerification rights; private final UserRoleVerification rights;
public RegistryService(ImdgProvider imdgProvider, public RegistryService(ImdgProvider imdgProvider,
@Qualifier("returnDepositValidator") Function<RegistryReturnDepositRequest, IValidator> returnDepositVal, @Qualifier("returnDepositValidator") Function<RegistryReturnDepositRequest, IValidator> returnDepositVal,
@Qualifier("refundDateValidator") Function<RegistryChangeRefundDateRequest, IValidator> refundDateVal, @Qualifier("refundDateValidator") Function<RegistryChangeRefundDateRequest, IValidator> refundDateVal,
@Qualifier("splitDepositValidator") Function<RegistrySplitDepositActionRequest, IValidator> splitDepositActionVal, @Qualifier("splitDepositValidator") Function<RegistrySplitDepositActionRequest, IValidator> splitDepositActionVal,
@Qualifier("statusExtractValidator") Function<RegistryChangeStatusExtractRequest, IValidator> statusExtractVal,
IMessageResolver msgResolver, IMessageResolver msgResolver,
UserRoleVerification rights) { RequestHelper reqHelp, UserRoleVerification rights) {
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.returnDepositVal = returnDepositVal; this.returnDepositVal = returnDepositVal;
this.refundDateVal = refundDateVal; this.refundDateVal = refundDateVal;
this.splitDepositActionVal = splitDepositActionVal; this.splitDepositActionVal = splitDepositActionVal;
this.statusExtractVal = statusExtractVal;
this.msgResolver = msgResolver; this.msgResolver = msgResolver;
this.reqHelp = reqHelp;
this.rights = rights; this.rights = rights;
rights.setRoleForVerification(UserRole.Admin); rights.setRoleForVerification(UserRole.Admin);
} }
@ -156,6 +164,26 @@ public class RegistryService {
return new RequestInfoUpdate(req.getId(), Status.Success, null); return new RequestInfoUpdate(req.getId(), Status.Success, null);
} }
public RequestInfoUpdate changeStatusExtract(BaseRequest<RegistryChangeStatusExtractRequest> req) {
if (!rights.userHasRole(req.getUserId(), UserRole.Admin)) {
return reqHelp.error(req.getId(), ClearingError.UserVerifyDenial);
}
RegistryChangeStatusExtractRequest payload = req.getRequestPayload();
IValidator validator = statusExtractVal.apply(payload);
Optional<EnumMessage> err = validator.tillFirstError();
if (err.isPresent()) {
log.error("RegistryChangeStatusExtractRequest.id={} validation error: {}",
req.getId(),
msgResolver.resolve(err.get()));
return reqHelp.error(req.getId(), err.get());
}
Registry registry = validator.getStored(Stored.PresentById);
registry.setRegistryStatus(payload.getRegistryStatus());
log.debug("changing registry.id={} status to {}", registry.getId(), payload.getRegistryStatus());
registryImdg.update(registry);
return reqHelp.success(req.getId());
}
public RequestInfoUpdate changeRefundDate(BaseRequest<RegistryChangeRefundDateRequest> req) { public RequestInfoUpdate changeRefundDate(BaseRequest<RegistryChangeRefundDateRequest> req) {
RegistryChangeRefundDateRequest requestPayload = req.getRequestPayload(); RegistryChangeRefundDateRequest requestPayload = req.getRequestPayload();
IValidator validator = refundDateVal.apply(requestPayload); IValidator validator = refundDateVal.apply(requestPayload);

View file

@ -159,7 +159,7 @@ public class Sdf06Executor {
dmiService.setProc(tcr.getId(), dmiService.setProc(tcr.getId(),
CurrencyCode.RUB.getKey(), CurrencyCode.RUB.getKey(),
safeBD(sDf06.getSum()), safeBD(sDf06.getSum()),
sDf06.getNumber()); sDf06.getNumber().toString());
} }
sdf07WasCreated = true; sdf07WasCreated = true;
} }
@ -266,7 +266,7 @@ public class Sdf06Executor {
dmiService.setProc(searchTcrOnGatewayResponse(sdf06).map(SpcexObjectBase::getId).orElse(null), dmiService.setProc(searchTcrOnGatewayResponse(sdf06).map(SpcexObjectBase::getId).orElse(null),
CurrencyCode.RUB.getKey(), CurrencyCode.RUB.getKey(),
safeBD(sdf06.getSum()), safeBD(sdf06.getSum()),
sdf06.getNumber() sdf06.getNumber().toString()
); );
} else { } else {
log.trace("statement.id={}, sdf07.id={}, sdf06.id={} rejected (by gateway answer)", log.trace("statement.id={}, sdf07.id={}, sdf06.id={} rejected (by gateway answer)",

View file

@ -2,18 +2,31 @@ package ru.spcex.clearing.service.executors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.sdf.SDf54; import ru.clearing.classes.statics.data.sdf.SDf54;
import ru.clearing.classes.statics.data.sdf.SDf55; import ru.clearing.classes.statics.data.sdf.SDf55;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.service.AssetTrio;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.registry.DmiService;
import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.platform.enumeration.CurrencyCode;
import ru.spcex.platform.enumeration.TransactionStatus; import ru.spcex.platform.enumeration.TransactionStatus;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
import java.util.Optional;
import java.util.function.Function;
@Service @Service
public class Sdf55Executor { public class Sdf55Executor {
@ -21,35 +34,46 @@ public class Sdf55Executor {
private final Imdg<SDf54> sDf54Imdg; private final Imdg<SDf54> sDf54Imdg;
private final Imdg<SDf55> sDf55Imdg; private final Imdg<SDf55> sDf55Imdg;
private final Imdg<PaymentInstruction> pmtImdg; private final Imdg<PaymentInstruction> pmtImdg;
private final Function<StatementRequest, IValidator> validation;
private final IMessageResolver msgRslv;
private final DmiService dmiService;
private final AssetTBFProcessing assets;
public Sdf55Executor(ImdgProvider imdgProvider,
public Sdf55Executor(ImdgProvider imdgProvider) { @Qualifier("sdf55ExecutorValidation") Function<StatementRequest, IValidator> validation, IMessageResolver msgRslv, DmiService dmiService, AssetTBFProcessing assets) {
this.sDf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class); this.sDf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class);
this.sDf55Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf55, SDf55.class); this.sDf55Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf55, SDf55.class);
this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
this.validation = validation;
this.msgRslv = msgRslv;
this.dmiService = dmiService;
this.assets = assets;
} }
public void execute(BaseRequest<StatementRequest> systemRequest) { public void execute(BaseRequest<StatementRequest> systemRequest) {
StatementRequest payload = systemRequest.getRequestPayload(); StatementRequest payload = systemRequest.getRequestPayload();
log.debug("executing {}.generationId={}", payload.getTable(), payload.getGroupId()); log.debug("executing {}.generationId={}", payload.getTable(), payload.getGroupId());
SDf55 sDf55 = sDf55Imdg.getFirstObjectBySQL("generationId = %d".formatted(payload.getGroupId())); IValidator validator = validation.apply(payload);
if (sDf55 == null) { Optional<EnumMessage> err = validator.tillFirstError();
log.error("sDf55 not found for generationId={}", payload.getGroupId()); if (err.isPresent()) {
return; log.error(msgRslv.resolve(err.get()));
}
SDf54 sDf54 = sDf54Imdg.getFirstObjectBySQL("docnm_ref = '%s'".formatted(sDf55.getDocnm_ref()));
if (sDf54 == null) {
log.error("sDf54 not found for sDf55.id={} docnm_ref={}", sDf55.getId(), sDf55.getDocnm_ref());
return;
}
PaymentInstruction pmt = pmtImdg.getSingleObjectByID(sDf54.getGenerationId());
if (pmt == null) {
log.error("pmt not found for sDf54.id={} generationId={}", sDf54.getId(), sDf54.getGenerationId());
return; return;
} }
SDf55 sDf55 = validator.getStored(ValidationStored.Sdf55ByGroupId);
SDf54 sDf54 = validator.getStored(ValidationStored.Sdf55Sdf54ByDocnmRef);
PaymentInstruction pmt = validator.getStored(ValidationStored.Sdf55PaymentInstruction);
TradingClearingRegistry tcr = validator.getStored(ValidationStored.Sdf55Tcr);
AssetTrio assetTrio = validator.getStored(ValidationStored.Sdf55Assets);
log.debug("sdf55.id={}, found sdf54.id={}, PaymentInstruction.id={}", sDf55.getId(), sDf54.getId(), pmt.getId()); log.debug("sdf55.id={}, found sdf54.id={}, PaymentInstruction.id={}", sDf55.getId(), sDf54.getId(), pmt.getId());
pmt.setTransactionStatus(TransactionStatus.ok.getKey()); pmt.setTransactionStatus(TransactionStatus.ok.getKey());
pmt.setUpdated(Instant.now()); pmt.setUpdated(Instant.now());
pmtImdg.update(pmt); pmtImdg.update(pmt);
if (tcr != null) {
dmiService.setOk(tcr.getId(), CurrencyCode.RUB.getKey(), sDf54.getDocnm_ref());
assets.process(assetTrio.a__b(),
assetTrio.a__t(),
assetTrio.a__f(),
BigDecimal.ZERO);
}
} }
} }

View file

@ -25,6 +25,7 @@ import ru.spcex.clearing.service.AssetTrio;
import ru.spcex.clearing.service.Sdf54Creator; import ru.spcex.clearing.service.Sdf54Creator;
import ru.spcex.clearing.service.builder.PaymentInstructionBuilderV2; import ru.spcex.clearing.service.builder.PaymentInstructionBuilderV2;
import ru.spcex.clearing.service.registry.AssetTBFProcessing; import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.registry.DmiService;
import ru.spcex.clearing.service.registry.RegistryManager; import ru.spcex.clearing.service.registry.RegistryManager;
import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.security.UserRoleVerification;
@ -37,7 +38,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId; import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.number.BigDecimalUtil;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -45,6 +45,8 @@ import java.time.Instant;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
@Service @Service
public class PaymentInstructionOutboundService { public class PaymentInstructionOutboundService {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
@ -64,12 +66,13 @@ public class PaymentInstructionOutboundService {
private final Sdf54Creator sdf54Creator; private final Sdf54Creator sdf54Creator;
private final KafkaSender kafkaSender; private final KafkaSender kafkaSender;
private final AssetTBFProcessing assetsMng; private final AssetTBFProcessing assetsMng;
private final DmiService dmiService;
@Autowired @Autowired
public PaymentInstructionOutboundService(UserRoleVerification rights, public PaymentInstructionOutboundService(UserRoleVerification rights,
IMessageResolver msgs, IMessageResolver msgs,
ImdgProvider imdgProvider, ImdgProvider imdgProvider,
Function<PIClearingOutbondActionNewRequest, IValidator> validation, RegistryManager rgsMng, KafkaSender kafkaSender, AssetTBFProcessing assetsMng) { Function<PIClearingOutbondActionNewRequest, IValidator> validation, RegistryManager rgsMng, KafkaSender kafkaSender, AssetTBFProcessing assetsMng, DmiService dmiService) {
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.rights = rights; this.rights = rights;
this.msgs = msgs; this.msgs = msgs;
@ -86,6 +89,7 @@ public class PaymentInstructionOutboundService {
this.rgsMng = rgsMng; this.rgsMng = rgsMng;
this.kafkaSender = kafkaSender; this.kafkaSender = kafkaSender;
this.assetsMng = assetsMng; this.assetsMng = assetsMng;
this.dmiService = dmiService;
} }
public RequestInfoUpdate sendOutBoundPayment(BaseRequest<PIClearingOutbondActionNewRequest> req) { public RequestInfoUpdate sendOutBoundPayment(BaseRequest<PIClearingOutbondActionNewRequest> req) {
@ -104,7 +108,7 @@ public class PaymentInstructionOutboundService {
Account accDeb = validator.getStored(ValidationStored.PIOutboundAccountDeb); Account accDeb = validator.getStored(ValidationStored.PIOutboundAccountDeb);
Company addressee = cmpImdg.getSingleObjectByID(payload.getAddresseeId()); Company addressee = cmpImdg.getSingleObjectByID(payload.getAddresseeId());
Company sender = cmpImdg.getSingleObjectByID(payload.getSenderId()); Company sender = cmpImdg.getSingleObjectByID(payload.getSenderId());
BigDecimal amount = BigDecimalUtil.safeBD(payload.getCreditLeg_amount()); BigDecimal amount = safeBD(payload.getCreditLeg_amount());
log.debug("all checks passed, accCred.id={}, accDeb.id={}, addressee.id={}, sender.id={}, amount: {}", log.debug("all checks passed, accCred.id={}, accDeb.id={}, addressee.id={}, sender.id={}, amount: {}",
accCred.getId(), accDeb.getId(), addressee.getId(), sender.getId(), amount); accCred.getId(), accDeb.getId(), addressee.getId(), sender.getId(), amount);
@ -153,12 +157,18 @@ public class PaymentInstructionOutboundService {
} }
log.debug("assets found and balance is ok. am*b.id={}, am*t.id={}, am*f.id={}", log.debug("assets found and balance is ok. am*b.id={}, am*t.id={}, am*f.id={}",
assets.get().a__b().getId(), assets.get().a__t().getId(), assets.get().a__f().getId()); 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 sDf54 = sdf54Creator.create(pmt);
sDf54.setId(idGenerator.nextId()); sDf54.setId(idGenerator.nextId());
sDf54.setGenerationId(pmt.getId()); sDf54.setGenerationId(pmt.getId());
sdf54Imdg.insert(sDf54); sdf54Imdg.insert(sDf54);
log.debug("new sdf54.id: {}", sDf54.getId()); log.debug("new sdf54.id: {}", sDf54.getId());
if (tcr != null) {
dmiService.setProc(tcr.getId(),
CurrencyCode.RUB.getKey(),
safeBD(amount).negate(),
sDf54.getDocnm_ref());
assetsMng.process(assets.get().a__b(), assets.get().a__t(), assets.get().a__f(), BigDecimal.ZERO);
}
SdfClearingRequest exp = new SdfClearingRequest(); SdfClearingRequest exp = new SdfClearingRequest();
exp.setGroupId(sDf54.getGenerationId()); exp.setGroupId(sDf54.getGenerationId());
kafkaSender.sendRequestToQueue(Consts.SDF54_PROCESS, exp); kafkaSender.sendRequestToQueue(Consts.SDF54_PROCESS, exp);

View file

@ -2,6 +2,7 @@ package ru.spcex.clearing.service.registry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
@ -33,11 +34,17 @@ public class AssetTBFProcessing {
private final Imdg<Registry> rgsImdg; private final Imdg<Registry> rgsImdg;
private final RegistryManager rgsMng; private final RegistryManager rgsMng;
@Autowired
public AssetTBFProcessing(ImdgProvider imdgProvider, RegistryManager rgsMng) { public AssetTBFProcessing(ImdgProvider imdgProvider, RegistryManager rgsMng) {
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.rgsMng = rgsMng; this.rgsMng = rgsMng;
} }
public AssetTBFProcessing(Imdg<Registry> rgsImdg) {
this.rgsImdg = rgsImdg;
this.rgsMng = new RegistryManager(rgsImdg);
}
public void process(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) { public void process(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) {
safeWrapField(am_t::getBalance, am_t::setBalance); safeWrapField(am_t::getBalance, am_t::setBalance);
safeWrapField(am_b::getBalance, am_b::setBalance); safeWrapField(am_b::getBalance, am_b::setBalance);
@ -155,6 +162,18 @@ public class AssetTBFProcessing {
return new AssetTrio(asf, asb, ast); return new AssetTrio(asf, asb, ast);
} }
public Optional<Registry> searchByTcrCompanyAccount(Registry rgs,
RegistryTradingParams params) {
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.sql(RegistryCodeSqlBuilder.getInstance(params).build()),
pb.equals("tradingClearingRegistryId", rgs.getTradingClearingRegistryId()),
pb.equals("companyId", rgs.getCompanyId()),
pb.equals("accountId", rgs.getAccountId())
);
return Optional.ofNullable(rgsImdg.getFirstObjectByPredicate(prdct));
}
public Optional<AssetTrio> searchMoneyByAccAndCompany(Long companyId, Long accountId) { public Optional<AssetTrio> searchMoneyByAccAndCompany(Long companyId, Long accountId) {
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder(); ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
Function<RegistryTradingParams, ImdgPredicate> prdct = rgsCode -> pb.and( Function<RegistryTradingParams, ImdgPredicate> prdct = rgsCode -> pb.and(

View file

@ -34,7 +34,7 @@ public class DmiService {
public void setProc(Long tcrId, public void setProc(Long tcrId,
String securitySymbol, String securitySymbol,
BigDecimal balance, BigDecimal balance,
BigDecimal contract) { String contract) {
findDmi(tcrId, securitySymbol, contract.toString()).ifPresentOrElse(d__i -> { findDmi(tcrId, securitySymbol, contract.toString()).ifPresentOrElse(d__i -> {
d__i.setRegistryStatus(RegistryStatus.PROC.getKey()); d__i.setRegistryStatus(RegistryStatus.PROC.getKey());
d__i.setUpdated(Instant.now()); d__i.setUpdated(Instant.now());

View file

@ -0,0 +1,113 @@
package ru.spcex.clearing.service.validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.sdf.SDf54;
import ru.clearing.classes.statics.data.sdf.SDf55;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
import ru.spcex.clearing.service.AssetTrio;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Optional;
public enum Sdf55ValidationRule implements IValidationRule<ImdgValidationContext<StatementRequest>> {
Fields() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<StatementRequest> context) {
StatementRequest validatedObject = context.getValidatedObject();
if (validatedObject.getGroupId() == null) {
return of(ClearingError.WrongField, "groupId");
}
return empty();
}
},
GenerationIdFound() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<StatementRequest> context) {
StatementRequest validatedObject = context.getValidatedObject();
Long groupId = validatedObject.getGroupId();
Imdg<SDf55> sDf55Imdg = context.obtainMap(IMDGDistributedNames.Map_SDf55, SDf55.class);
SDf55 sDf55 = sDf55Imdg.getFirstObjectBySQL("generationId = %d".formatted(groupId));
if (sDf55 == null) {
return of(ClearingError.RecordNotFound, "SDf55.id=%d".formatted(groupId));
}
context.storeObject(ValidationStored.Sdf55ByGroupId, sDf55);
return empty();
}
},
Sdf54Present() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<StatementRequest> context) {
SDf55 sDf55 = context.getStoredObject(ValidationStored.Sdf55ByGroupId);
Imdg<SDf54> sDf54Imdg = context.obtainMap(IMDGDistributedNames.Map_SDf54, SDf54.class);
SDf54 sDf54 = sDf54Imdg.getFirstObjectBySQL("docnm_ref = '%s'".formatted(sDf55.getDocnm_ref()));
if (sDf54 == null) {
return of(ClearingError.RecordNotFound, "SDf54.docnm_ref=%s".formatted(sDf55.getDocnm_ref()));
}
context.storeObject(ValidationStored.Sdf55Sdf54ByDocnmRef, sDf54);
return empty();
}
},
PaymentInstructionPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<StatementRequest> context) {
SDf54 sDf54 = context.getStoredObject(ValidationStored.Sdf55Sdf54ByDocnmRef);
Imdg<PaymentInstruction> pmtImdg = context.obtainMap(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
PaymentInstruction paymentInstruction = pmtImdg.getSingleObjectByID(sDf54.getGenerationId());
if (paymentInstruction == null) {
return of(ClearingError.RecordNotFound, "PaymentInstruction.id=%d".formatted(sDf54.getGenerationId()));
}
context.storeObject(ValidationStored.Sdf55PaymentInstruction, paymentInstruction);
return empty();
}
},
TcrPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<StatementRequest> context) {
Imdg<TradingClearingRegistry> tcrImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
PaymentInstruction pmt = context.getStoredObject(ValidationStored.Sdf55PaymentInstruction);
Long accCredId = pmt.getCreditLeg_accountId();
Long addresseeId = pmt.getSenderId();
if (accCredId == null || addresseeId == null) return empty();
TradingClearingRegistry tcr = tcrImdg.getFirstObjectBySQL(
"moneyAccountId = '%d' and companyId = %d".formatted(accCredId, addresseeId)
);
if (tcr != null) {
context.storeObject(ValidationStored.Sdf55Tcr, tcr);
}
return empty();
}
},
AssetsPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<StatementRequest> context) {
Imdg<Registry> rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class);
PaymentInstruction pmt = context.getStoredObject(ValidationStored.Sdf55PaymentInstruction);
Long accCredId = pmt.getCreditLeg_accountId();
Long addresseeId = pmt.getSenderId();
AssetTBFProcessing assets = new AssetTBFProcessing(rgsImdg);
Optional<AssetTrio> assetTrio = assets.searchMoneyByAccAndCompany(addresseeId, accCredId);
if (assetTrio.isEmpty()) {
return of(ClearingError.RecordNotFound, "AM*F/AM*B/AM*T");
}
context.storeObject(ValidationStored.Sdf55Assets, assetTrio.get());
return empty();
}
}
;
private final static Logger log = LoggerFactory.getLogger(Sdf55ValidationRule.class);
@Override
public String ruleName() {
return "Sdf55ValidationRule." + name();
}
}

View file

@ -0,0 +1,72 @@
package ru.spcex.clearing.service.validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
import ru.spcex.platform.enumeration.RegistryStatus;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.imdg.validation.Stored;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.text.TextUtil;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Objects;
import java.util.Optional;
public enum StatusExtractValidationRule implements IValidationRule<ImdgValidationContext<RegistryChangeStatusExtractRequest>> {
Fields() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<RegistryChangeStatusExtractRequest> context) {
RegistryChangeStatusExtractRequest validatedObject = context.getValidatedObject();
if (validatedObject.getId() == null) {
return of(ClearingError.WrongField, "id");
}
if (TextUtil.isEmpty(validatedObject.getRegistryStatus())) {
return of(ClearingError.WrongField, "registryStatus");
}
return empty();
}
},
ContractCheck() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<RegistryChangeStatusExtractRequest> context) {
RegistryChangeStatusExtractRequest validatedObject = context.getValidatedObject();
if (TextUtil.isEmpty(validatedObject.getContract())) {
return empty();
}
Registry rgs = context.getStoredObject(Stored.PresentById);
if (rgs == null) {
log.error("PresentById check passed, yet not Stored.PresentById is present");
return of(ClearingError.WrongField, "id");
}
if (!Objects.equals(rgs.getContract(), validatedObject.getContract())) {
return of(ClearingError.WrongField, "contract");
}
return empty();
}
},
RegistryStatusValid() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<RegistryChangeStatusExtractRequest> context) {
RegistryChangeStatusExtractRequest validatedObject = context.getValidatedObject();
if (TextUtil.isEmpty(validatedObject.getRegistryStatus())) {
return empty();
}
RegistryStatus rgsStatus = IEnumKey.getEnumByKey(RegistryStatus.class, validatedObject.getRegistryStatus());
if (rgsStatus == null) {
return of(ClearingError.WrongField, "registryStatus");
}
return empty();
}
}
;
private final static Logger log = LoggerFactory.getLogger(StatusExtractValidationRule.class);
@Override
public String ruleName() {
return "StatusExtractValidationRule." + name();
}
}

View file

@ -26,6 +26,8 @@ public enum ValidationStored {
Sdf20Account, Sdf20Company, Sdf20Tcr, Sdf20Dst, Sdf20Ast, Sdf20Security, Sdf20Account, Sdf20Company, Sdf20Tcr, Sdf20Dst, Sdf20Ast, Sdf20Security,
Sdf55ByGroupId, Sdf55Sdf54ByDocnmRef, Sdf55PaymentInstruction, Sdf55Tcr, Sdf55Assets,
SecurityBySecurityCode, SecurityBySecurityCode,
RegistrysByContract RegistrysByContract

View file

@ -108,6 +108,7 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
inclusionObligations.setSessionType(sessionType()); inclusionObligations.setSessionType(sessionType());
inspectionObligationsReturn.setSessionType(sessionType()); inspectionObligationsReturn.setSessionType(sessionType());
inspectionObligations.setSessionType(sessionType()); inspectionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section());
formingPaymentInstructionDeals.setSection(section()); formingPaymentInstructionDeals.setSection(section());
formingPaymentInstructionDeals.setSessionType(sessionType()); formingPaymentInstructionDeals.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();

View file

@ -102,6 +102,7 @@ public class IntermediateMkrSession extends AbstractSession implements Initializ
); );
inclusionObligations.setSessionType(sessionType()); inclusionObligations.setSessionType(sessionType());
inspectionObligations.setSessionType(sessionType()); inspectionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section());
formingPaymentInstructionDeals.setSection(section()); formingPaymentInstructionDeals.setSection(section());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();

View file

@ -10,6 +10,7 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.error.RgsError;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.service.registry.AssetTBFProcessing; import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.registry.RegistryManager; import ru.spcex.clearing.service.registry.RegistryManager;
@ -18,6 +19,7 @@ import ru.spcex.clearing.session.stage.ISessionStage;
import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.StageResult;
import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.Task;
import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; import ru.spcex.clearing.session.stage.task.InspectionPoolPayload;
import ru.spcex.clearing.session.stage.util.RegistryUtil;
import ru.spcex.platform.enumeration.*; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
@ -34,6 +36,7 @@ import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import static ru.spcex.platform.enumeration.RegistryTradingParams.*; import static ru.spcex.platform.enumeration.RegistryTradingParams.*;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
@ -97,6 +100,7 @@ public class InspectionObligations implements ISessionStage {
.toList(); .toList();
log.info("found {} ({} groups) registries by sql: {}", registriesToProcess.size(), registriesByGroupSorted.size(), sqlCondition); log.info("found {} ({} groups) registries by sql: {}", registriesToProcess.size(), registriesByGroupSorted.size(), sqlCondition);
GROUP:
for (Map.Entry<Long, List<Registry>> entry : registriesByGroupSorted) { for (Map.Entry<Long, List<Registry>> entry : registriesByGroupSorted) {
List<Registry> group = entry.getValue(); List<Registry> group = entry.getValue();
List<Registry> obligationsInGroup = group.stream().filter(registry -> List<Registry> obligationsInGroup = group.stream().filter(registry ->
@ -140,43 +144,58 @@ public class InspectionObligations implements ISessionStage {
.ifPresent(chk -> chk.isUncovered = true); .ifPresent(chk -> chk.isUncovered = true);
} }
} }
for (Registry rgs : group) {
Runnable failGroup = () -> Stream.concat(group.stream(), getRefundDateRgsIfPresent(group).stream())
.forEach(registry -> {
registry.setComment(msgResolver.resolve(RgsError.A__tNotFound));
updateRegistryStatus(registry, RegistryStatus.FAIL);
});
RegistryInstrumentType mOrS = IEnumKey.getEnumByKey(RegistryInstrumentType.class, rgs.getRegistryInstrumentType());
if (mOrS == null) {
log.error("RegistryInstrumentType is null for groupId {} {}.id={}", entry.getKey(),
rgs.getRegistryCode(), rgs.getId());
failGroup.run();
continue;
}
if (Section.MKR.equals(section) && mOrS.equals(RegistryInstrumentType.S)) {
continue;
}
Optional<Registry> a__t = assets.searchByTcrCompanyAccount(rgs, A__T.type(mOrS));
if (a__t.isEmpty()) {
log.debug("groupId {}, {}.id={} - A**T not found. settings FAIL to group",
entry.getKey(), rgs.getRegistryCode(), rgs.getId());
failGroup.run();
continue GROUP;
}
}
defineStatusAndUpdateRegistry(checkResults, group); defineStatusAndUpdateRegistry(checkResults, group);
if (checkResults.stream().noneMatch(checkResult -> checkResult.isUncovered)) { if (checkResults.stream().noneMatch(checkResult -> checkResult.isUncovered)) {
Instant now = Instant.now(); Instant now = Instant.now();
//по каждому регистру OM*T, TM*T, OS*T, TS*T из одной группы //по каждому регистру OM*T, TM*T, OS*T, TS*T из одной группы
for (Registry registry : group) {//TODO CLRNWORM проверка на пустой blockedRegistry for (Registry registry : group) {//TODO CLRNWORM проверка на пустой blockedRegistry
Registry blockedRegistry = null; {
if (IEnumKey.getEnumByKey(RegistryInstrumentType.class, registry.getRegistryInstrumentType()) == RegistryInstrumentType.M) { RegistryInstrumentType mOrS = IEnumKey.getEnumByKey(RegistryInstrumentType.class, registry.getRegistryInstrumentType());
String moneyBAssetSql = searchMoneyBAssetsSql(registry); if (mOrS == null) continue;
log.debug("search money asset by registry.id={} sql {}", registry.getId(), moneyBAssetSql); Optional<Registry> a__t = assets.searchByTcrCompanyAccount(registry, A__T.type(mOrS));
blockedRegistry = registryImdg.getFirstObjectBySQL(moneyBAssetSql); Optional<Registry> a__b = a__t.map(a__tFound -> assets
if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.O) { .searchByTcrCompanyAccount(a__tFound, A__B.type(mOrS))
blockedRegistry.setBalance(blockedRegistry.getBalance().add(registry.getBalance())); .orElseGet(() -> copyB(a__tFound)));
} else if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.T) { Optional<Registry> a__f = a__t.map(a__tFound -> assets
blockedRegistry.setBalance(blockedRegistry.getBalance().subtract(registry.getBalance())); .searchByTcrCompanyAccount(a__tFound, A__F.type(mOrS))
} .orElseGet(() -> copyF(a__tFound)));
blockedRegistry.setSessionId(sessionId); log.debug("registry {}.id={}: {}", registry.getRegistryCode(), registry.getId(),
blockedRegistry.setUpdated(now); a__t.map(r -> "A**T.id=%d/A**B.id=%d/A**F.id=%d"
registryImdg.update(blockedRegistry); .formatted(a__t.get().getId(), a__b.get().getId(), a__f.get().getId()))
} else if (section != null && section == Section.FOND && .orElse("A**T/A**B/A**F not found"));
IEnumKey.getEnumByKey(RegistryInstrumentType.class, registry.getRegistryInstrumentType()) == RegistryInstrumentType.S) { if (a__t.isPresent()) {
String securityBAssetSql = searchSecurityBAssetsSql(registry); BigDecimal amount = safeBD(registry.getBalance());
log.debug("search security asset by registry.id={} sql {}", registry.getId(), securityBAssetSql); if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.O) {
blockedRegistry = registryImdg.getFirstObjectBySQL(securityBAssetSql); amount = amount.negate();
if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.O) { } else if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.T) {
blockedRegistry.setBalance(blockedRegistry.getBalance().add(registry.getBalance())); amount = amount;
} else if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.T) { }
blockedRegistry.setBalance(blockedRegistry.getBalance().subtract(registry.getBalance())); a__b.get().setSessionId(sessionId);
} assets.process(a__b.get(), a__t.get(), a__f.get(), amount);
blockedRegistry.setSessionId(sessionId);
blockedRegistry.setUpdated(now);
registryImdg.update(blockedRegistry);
}
if (blockedRegistry != null) {
Optional<Registry> registryUnitF = registryManager.findRegByUnit(registry.getCompanyId(), registry.getAccountId(), registry.getContract(), blockedRegistry, RegistryUnit.F);
Optional<Registry> registryUnitT = registryManager.findRegByUnit(registry.getCompanyId(), registry.getAccountId(), registry.getContract(), blockedRegistry, RegistryUnit.T);
if (registryUnitF.isPresent() && registryUnitT.isPresent()) {
assets.process(blockedRegistry, registryUnitT.get(), registryUnitF.get(), BigDecimal.ZERO);
} }
} }
} }
@ -253,28 +272,24 @@ foreach( at: rgsAT)
obligation.getCompanyId()); obligation.getCompanyId());
} }
private String searchMoneyBAssetsSql(Registry obligation) { private Registry copyF(Registry rgs) {
return String.format("%s and " + Registry rgsF = rgs.clone();
"tradingClearingRegistryId = '%s' and " + RegistryManager.zeroState(rgsF);
"companyId = '%s' and " + rgsF.setRegistryUnit(RegistryUnit.F.getKey());
"accountId = %s", rgsF.setRegistryCode(RegistryUtil.clearingCode(rgsF));
RegistryCodeSqlBuilder.getInstance(AM_B).build(), registryImdg.insert(rgsF);
obligation.getTradingClearingRegistryId(), log.debug("created {}.id={} by {}.id={}", rgsF.getRegistryCode(), rgsF.getId(), rgs.getRegistryCode(), rgs.getId());
obligation.getCompanyId(), return rgsF;
obligation.getAccountId());
} }
private String searchSecurityBAssetsSql(Registry registry) { private Registry copyB(Registry rgs) {
return String.format("%s and " + Registry rgsB = rgs.clone();
"tradingClearingRegistryId = '%s' and " + RegistryManager.zeroState(rgsB);
"companyId = '%s' and " + rgsB.setRegistryUnit(RegistryUnit.B.getKey());
"securitySymbol = '%s' and " + rgsB.setRegistryCode(RegistryUtil.clearingCode(rgsB));
"accountId = %s", registryImdg.insert(rgsB);
RegistryCodeSqlBuilder.getInstance(AS_B).build(), log.debug("created {}.id={} by {}.id={}", rgsB.getRegistryCode(), rgsB.getId(), rgs.getRegistryCode(), rgs.getId());
registry.getTradingClearingRegistryId(), return rgsB;
registry.getCompanyId(),
registry.getSecuritySymbol(),
registry.getAccountId());
} }
private void defineStatusAndUpdateRegistry(List<CheckResult> checkResults, List<Registry> registries) { private void defineStatusAndUpdateRegistry(List<CheckResult> checkResults, List<Registry> registries) {
@ -295,28 +310,32 @@ foreach( at: rgsAT)
} }
} }
//проверяем есть ли второй день для сделки (он не входит в пул, поэтому ищем отдельно) //проверяем есть ли второй день для сделки (он не входит в пул, поэтому ищем отдельно)
if (registries.stream().anyMatch(rgs -> rgs.getRefundDate() != null) && !SessionType.MEDM.equals(sessionType)) { getRefundDateRgsIfPresent(registries).forEach(rgs -> updateRegistryStatus(rgs, RegistryStatus.FAIL));
Optional<Pair<Long, LocalDate>> groupIdAndSettleDate = registries.stream()
.map(rgs -> new Pair<>(rgs.getGroupId(), rgs.getSettlementDate()))
.filter(pair -> pair.getFirst() != null)
.filter(pair -> pair.getSecond() != null)
.findFirst();
if (groupIdAndSettleDate.isEmpty())
return;
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
Collection<Registry> refundRgs = registryImdg.getCollectionObjectsByPredicate(
pb.and(
pb.equals("groupId", groupIdAndSettleDate.get().getFirst()),
pb.not(pb.equals("settlementDate", groupIdAndSettleDate.get().getSecond()))
)
);
refundRgs.forEach(rgs -> updateRegistryStatus(rgs, RegistryStatus.FAIL));
}
} else { } else {
registries.forEach(registry -> updateRegistryStatus(registry, RegistryStatus.OK)); registries.forEach(registry -> updateRegistryStatus(registry, RegistryStatus.OK));
} }
} }
private Collection<Registry> getRefundDateRgsIfPresent(List<Registry> registries) {
if (registries.stream().anyMatch(rgs -> rgs.getRefundDate() != null) && !SessionType.MEDM.equals(sessionType)) {
Optional<Pair<Long, LocalDate>> groupIdAndSettleDate = registries.stream()
.map(rgs -> new Pair<>(rgs.getGroupId(), rgs.getSettlementDate()))
.filter(pair -> pair.getFirst() != null)
.filter(pair -> pair.getSecond() != null)
.findFirst();
if (groupIdAndSettleDate.isEmpty()) {
return Collections.emptyList();
}
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
return registryImdg.getCollectionObjectsByPredicate(
pb.and(
pb.equals("groupId", groupIdAndSettleDate.get().getFirst()),
pb.not(pb.equals("settlementDate", groupIdAndSettleDate.get().getSecond()))
)
);
} else return Collections.emptyList();
}
private void updateRegistryStatus(Registry registry, RegistryStatus registryStatus) { private void updateRegistryStatus(Registry registry, RegistryStatus registryStatus) {
log.debug("Update registry.id: {} to {}", registry.getId(), registryStatus.getKey()); log.debug("Update registry.id: {} to {}", registry.getId(), registryStatus.getKey());
registry.setRegistryStatus(registryStatus.getKey()); registry.setRegistryStatus(registryStatus.getKey());

View file

@ -6,6 +6,7 @@ import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.platform.messaging.service.Status; import ru.spcex.clearing.platform.messaging.service.Status;
import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.enumeration.IErrorEnumId; import ru.spcex.platform.utils.enumeration.IErrorEnumId;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.error.ClearingBaseException; import ru.spcex.platform.utils.error.ClearingBaseException;
@ -102,4 +103,17 @@ public class RequestHelper {
this.log = log; this.log = log;
return this; return this;
} }
public RequestInfoUpdate success(Long id) {
return new RequestInfoUpdate(id, Status.Success, null);
}
public RequestInfoUpdate error(Long id, EnumMessage err) {
return new RequestInfoUpdate(id, Status.Error, messageResolver.resolve(err));
}
public RequestInfoUpdate error(Long id, IEnumId sbj, Object... args) {
EnumMessage error = new EnumMessage(sbj, args);
return new RequestInfoUpdate(id, Status.Error, messageResolver.resolve(error));
}
} }

View file

@ -88,6 +88,7 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
public final static RegistryTradingParams AM_T; public final static RegistryTradingParams AM_T;
public final static RegistryTradingParams AM_B; public final static RegistryTradingParams AM_B;
public final static RegistryTradingParams A__B; public final static RegistryTradingParams A__B;
public final static RegistryTradingParams A__F;
public final static RegistryTradingParams A__T; public final static RegistryTradingParams A__T;
public final static RegistryTradingParams AS_T; public final static RegistryTradingParams AS_T;
public final static RegistryTradingParams DS_I; public final static RegistryTradingParams DS_I;
@ -153,6 +154,10 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
null, null,
null, null,
RegistryUnit.B); RegistryUnit.B);
A__F = new RegistryTradingParams(RegistryDesignation.A,
null,
null,
RegistryUnit.F);
A__T = new RegistryTradingParams(RegistryDesignation.A, A__T = new RegistryTradingParams(RegistryDesignation.A,
null, null,
null, null,

View file

@ -1,10 +1,11 @@
package ru.spcex.clearing.platform.messaging.domain.cud.registry; package ru.spcex.clearing.platform.messaging.domain.cud.registry;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import ru.spcex.platform.classes.base.interfaces.WithId;
import java.math.BigDecimal; import java.math.BigDecimal;
public class RegistryChangeStatusExtractRequest { public class RegistryChangeStatusExtractRequest implements WithId {
@JsonProperty @JsonProperty
public Long id; public Long id;
@JsonProperty @JsonProperty

View file

@ -2,4 +2,7 @@ package ru.spcex.platform.utils.enumeration;
public interface IMessageResolver { public interface IMessageResolver {
String resolve(EnumMessage errorMessage); String resolve(EnumMessage errorMessage);
default String resolve(IEnumId subject, Object... args) {
return resolve(new EnumMessage(subject, args));
}
} }