clearing-service http://jira.mfd.msk:8088/browse/CLS-307 SPLT bug fix
This commit is contained in:
parent
6237f534f2
commit
5cdf12a323
4 changed files with 89 additions and 76 deletions
|
|
@ -64,6 +64,7 @@ public class ValidationConfig {
|
|||
Imdg<Session> imdgSession;
|
||||
Imdg<SectionDictionary> imdgSectionDictionary;
|
||||
Imdg<Statement> imdgStatement;
|
||||
Imdg<InOutDirectionDictionary> imdgInOutDirection;
|
||||
ImdgProvider imdgProvider;
|
||||
|
||||
public ValidationConfig(ImdgProvider imdgProvider) {
|
||||
|
|
@ -82,6 +83,7 @@ public class ValidationConfig {
|
|||
this.equitySecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class);
|
||||
this.imdgStatement = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
|
||||
this.imdgDepoAccount = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class);
|
||||
this.imdgInOutDirection = imdgProvider.getImdg(IMDGDistributedNames.Map_InOutDirectionDictionary, InOutDirectionDictionary.class);
|
||||
this.imdgProvider = imdgProvider;
|
||||
}
|
||||
|
||||
|
|
@ -346,7 +348,8 @@ public class ValidationConfig {
|
|||
ImdgValidationContext<RegistrySplitDepositActionRequest> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(refundDateRequest);
|
||||
context.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry);
|
||||
context.setLogPrefix(r -> "contract=%d refundDate=%s".formatted(r.getContract(), r.getRefundDate()));
|
||||
context.addImdg(IMDGDistributedNames.Map_InOutDirectionDictionary, imdgInOutDirection);
|
||||
context.setLogPrefix(r -> "contract=%s refundDate=%s".formatted(r.getContract(), r.getRefundDate()));
|
||||
return new ValidatorImpl<>(context,
|
||||
FieldRequiredRule.instance("contract", RegistrySplitDepositActionRequest::getContract, ClearingError.RequiredFieldEmpty),
|
||||
FieldRequiredRule.instance("refundDate", RegistrySplitDepositActionRequest::getRefundDate, ClearingError.RequiredFieldEmpty),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.spcex.clearing.error.ClearingError;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.CreateRegistryRequest;
|
||||
|
|
@ -66,6 +65,7 @@ public class RegistryService {
|
|||
this.splitDepositActionVal = splitDepositActionVal;
|
||||
this.msgResolver = msgResolver;
|
||||
this.rights = rights;
|
||||
rights.setRoleForVerification(UserRole.Admin);
|
||||
}
|
||||
|
||||
public void createRegistry(CreateRegistryRequest createRegistryRequest) {
|
||||
|
|
@ -213,24 +213,15 @@ public class RegistryService {
|
|||
RegistryTradingParams registryInfo = null;
|
||||
//todo спросить про дубль C и T
|
||||
switch (registryType) {
|
||||
case Owner_A ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T);
|
||||
case Client_B ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.T);
|
||||
case Trustee_C, DepoOfShares_T ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.T);
|
||||
case TrusteeManager_D ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.A);
|
||||
case Issuer_E ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.E, RegistryUnit.R);
|
||||
case ToThePlacementOrRedeem_Z ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.Z, RegistryUnit.R);
|
||||
case DepoBond_H ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.R);
|
||||
case DepoOfTrustedBond_N ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.R);
|
||||
case DepoOfTrustedShares_S ->
|
||||
registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.T);
|
||||
case Owner_A -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T);
|
||||
case Client_B -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.T);
|
||||
case Trustee_C, DepoOfShares_T -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.T);
|
||||
case TrusteeManager_D -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.A);
|
||||
case Issuer_E -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.E, RegistryUnit.R);
|
||||
case ToThePlacementOrRedeem_Z -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.Z, RegistryUnit.R);
|
||||
case DepoBond_H -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.R);
|
||||
case DepoOfTrustedBond_N -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.R);
|
||||
case DepoOfTrustedShares_S -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.T);
|
||||
}
|
||||
return registryInfo;
|
||||
}
|
||||
|
|
@ -295,7 +286,7 @@ public class RegistryService {
|
|||
if (roleCheck != null) {
|
||||
return roleCheck;
|
||||
}
|
||||
Registry baseRegistry;
|
||||
Collection<Registry> baseRegistrys;
|
||||
{
|
||||
IValidator validator = splitDepositActionVal.apply(requestPayload);
|
||||
Optional<EnumMessage> err = validator.tillFirstError();
|
||||
|
|
@ -305,7 +296,7 @@ public class RegistryService {
|
|||
msgResolver.resolve(err.get()));
|
||||
return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(err.get()));
|
||||
}
|
||||
baseRegistry = validator.getStored(ValidationStored.RegistryByContract);
|
||||
baseRegistrys = validator.getStored(ValidationStored.RegistrysByContract);
|
||||
}
|
||||
|
||||
ImdgTransaction txCtx = imdgProvider.newTransaction();
|
||||
|
|
@ -319,43 +310,56 @@ public class RegistryService {
|
|||
direction = InOutDirection.out;
|
||||
log.debug("Direction not set. Use default: {}", direction);
|
||||
}
|
||||
// 1. Первая группа
|
||||
Registry firstRegistry = baseRegistry.clone();
|
||||
firstRegistry.setId(null);
|
||||
firstRegistry.setCreated(now);
|
||||
firstRegistry.setUpdated(null);
|
||||
if (InOutDirection.out == direction) {
|
||||
firstRegistry.setBalance(baseRegistry.getBalance().subtract(requestPayload.getOutboundAmount()));
|
||||
} else if (InOutDirection.in == direction) {
|
||||
firstRegistry.setBalance(baseRegistry.getBalance().add(requestPayload.getOutboundAmount()));
|
||||
} else {
|
||||
log.warn("Direction not set, do not change Balance");
|
||||
}
|
||||
firstRegistry.setContract(baseRegistry.getContract() + "~1");
|
||||
registryTMap.insert(firstRegistry);
|
||||
log.debug("Process {} for {} registry", direction, baseRegistrys.size());
|
||||
Long groupId = null;
|
||||
for (Registry baseRegistry : baseRegistrys) {
|
||||
log.trace("Registry[{}], groupId={}, ClearingCode={}", baseRegistry.getId(), baseRegistry.getGroupId(), baseRegistry.getClearingCode());
|
||||
if (groupId == null)
|
||||
groupId = baseRegistry.getGroupId();
|
||||
else if (!groupId.equals(baseRegistry.getGroupId())) {
|
||||
log.warn("Group id different: groupId={}; registry[{}].groupId={}", groupId, baseRegistry.getId(), baseRegistry.getGroupId());
|
||||
}
|
||||
// 1. Первая группа
|
||||
Registry firstRegistry = baseRegistry.clone();
|
||||
firstRegistry.setId(null);
|
||||
firstRegistry.setCreated(now);
|
||||
firstRegistry.setUpdated(null);
|
||||
if (InOutDirection.out == direction) {
|
||||
firstRegistry.setBalance(baseRegistry.getBalance().subtract(requestPayload.getOutboundAmount()));
|
||||
} else if (InOutDirection.in == direction) {
|
||||
firstRegistry.setBalance(baseRegistry.getBalance().add(requestPayload.getOutboundAmount()));
|
||||
} else {
|
||||
log.warn("Direction not set, do not change Balance");
|
||||
}
|
||||
firstRegistry.setContract(baseRegistry.getContract() + "~1");
|
||||
registryTMap.insert(firstRegistry);
|
||||
|
||||
// 2. Вторая группа
|
||||
Registry secondRegistry = null;
|
||||
if (InOutDirection.out == direction) {
|
||||
secondRegistry.setId(null);
|
||||
secondRegistry.setCreated(now);
|
||||
secondRegistry.setUpdated(null);
|
||||
secondRegistry.setBalance(requestPayload.getOutboundAmount());
|
||||
secondRegistry.setContract(baseRegistry.getContract() + "~2");
|
||||
registryTMap.insert(secondRegistry);
|
||||
}
|
||||
// 2. Вторая группа
|
||||
Registry secondRegistry = null;
|
||||
if (InOutDirection.out == direction) {
|
||||
secondRegistry = baseRegistry.clone();
|
||||
secondRegistry.setId(null);
|
||||
secondRegistry.setCreated(now);
|
||||
secondRegistry.setUpdated(null);
|
||||
secondRegistry.setBalance(requestPayload.getOutboundAmount());
|
||||
secondRegistry.setContract(baseRegistry.getContract() + "~2");
|
||||
secondRegistry.setRefundDate(requestPayload.getRefundDate());
|
||||
secondRegistry.setSettlementDate(requestPayload.getRefundDate());
|
||||
registryTMap.insert(secondRegistry);
|
||||
}
|
||||
|
||||
// 3. Текущим обязательствам установить статус SPLT
|
||||
baseRegistry.setRegistryStatus(RegistryStatus.SPLT.getKey());
|
||||
baseRegistry.setUpdated(Instant.now());
|
||||
registryTMap.update(baseRegistry);
|
||||
// 3. Текущим обязательствам установить статус SPLT
|
||||
baseRegistry.setRegistryStatus(RegistryStatus.SPLT.getKey());
|
||||
baseRegistry.setUpdated(Instant.now());
|
||||
registryTMap.update(baseRegistry);
|
||||
log.debug("Registry[{}] groupId={} split to: id1={} {}, id2={} {}",
|
||||
baseRegistry.getId(), baseRegistry.getGroupId(),
|
||||
firstRegistry == null ? null : firstRegistry.getId(), firstRegistry == null ? null : firstRegistry.getContract(),
|
||||
secondRegistry == null ? null : secondRegistry.getId(), secondRegistry == null ? null : secondRegistry.getContract()
|
||||
);
|
||||
}
|
||||
|
||||
txOk = true;
|
||||
log.debug("Registry[{}] groupId={} split to: id1={} {}, id2={} {}",
|
||||
baseRegistry.getId(), baseRegistry.getGroupId(),
|
||||
firstRegistry == null ? null : firstRegistry.getId(), firstRegistry == null ? null : firstRegistry.getContract(),
|
||||
secondRegistry == null ? null : secondRegistry.getId(), secondRegistry == null ? null : secondRegistry.getContract()
|
||||
);
|
||||
} finally {
|
||||
if (txOk) {
|
||||
txCtx.commitTransaction();
|
||||
|
|
|
|||
|
|
@ -6,18 +6,20 @@ import ru.clearing.classes.statics.data.registry.Registry;
|
|||
import ru.spcex.clearing.error.ClearingError;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
|
||||
import ru.spcex.platform.enumeration.RegistryDesignation;
|
||||
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||
import ru.spcex.platform.enumeration.RegistryTradingParams;
|
||||
import ru.spcex.platform.enumeration.RegistryUnit;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
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.imdg.validation.ImdgValidationContext;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.validation.IValidationRule;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum SplitDepositRequestValidationRule implements IValidationRule<ImdgValidationContext<RegistrySplitDepositActionRequest>> {
|
||||
CrossvalidateByRegistry() {
|
||||
|
|
@ -30,32 +32,36 @@ public enum SplitDepositRequestValidationRule implements IValidationRule<ImdgVal
|
|||
// Поиск регистра
|
||||
ImdgPredicateBuilder prdBldr = registryImdg.predicateBuilder();
|
||||
ImdgPredicate query = prdBldr.and(
|
||||
RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.OM_T).buildPredicate(prdBldr),
|
||||
prdBldr.equals("contract", request.getContract()));
|
||||
Registry registry = registryImdg.getSingleObjectByPredicate(query);
|
||||
if (registry == null) {
|
||||
log.debug("Registry not found by query \"{}\"", query);
|
||||
prdBldr.or(prdBldr.equals("registryStatus", RegistryStatus.PROC.getKey()), prdBldr.equals("registryStatus", RegistryStatus.MNG.getKey())),
|
||||
prdBldr.or(prdBldr.equals("registryDesignation", RegistryDesignation.O.getKey()), prdBldr.equals("registryDesignation", RegistryDesignation.T.getKey())),
|
||||
prdBldr.equals("registryUnit", RegistryUnit.T.getKey()),
|
||||
prdBldr.equals("contract", request.getContract())
|
||||
);
|
||||
Collection<Registry> registrys = registryImdg.getCollectionObjectsByPredicate(query);
|
||||
registrys = registrys.stream()
|
||||
.filter(r->r.getValueDate()!=null && r.getSettlementDate()!=null && r.getValueDate().isBefore(r.getSettlementDate()))
|
||||
.collect(Collectors.toList());
|
||||
Registry registryO = registrys.stream()
|
||||
.filter(r -> RegistryDesignation.O.equalsByKey(r.getRegistryDesignation()))
|
||||
.findAny().orElse(null);
|
||||
log.trace("Found registry {}. Crossvalidate for {}", registrys, registryO);
|
||||
|
||||
if (registryO == null) {
|
||||
log.debug("Registry not found by query \"{}\" and valueDate < settlementDate", query);
|
||||
return of(ClearingError.TCRegistryNotFound, request.getContract());
|
||||
} else {
|
||||
log.trace("Registry.id={} found by query \"{}\"", registry.getId(), query);
|
||||
}
|
||||
context.storeObject(ValidationStored.RegistryByContract, registry);
|
||||
context.storeObject(ValidationStored.RegistrysByContract, registrys);
|
||||
|
||||
// кросс-валидация
|
||||
if (!RegistryStatus.PROC.equalsByKey(registry.getRegistryStatus())) {
|
||||
log.debug("Registry[{}].RegistryStatus={} - error",
|
||||
registry.getId(), registry.getRegistryStatus());
|
||||
return Optional.of(new EnumMessage(ClearingError.TCRegistryNotFound, request.getContract()));
|
||||
}
|
||||
BigDecimal regBalance = registry.getBalance();
|
||||
if (regBalance == null || regBalance.compareTo(request.getOutboundAmount()) < 0) {
|
||||
BigDecimal regBalance = registryO.getBalance();
|
||||
if (regBalance == null || regBalance.compareTo(request.getOutboundAmount()) <= 0) {
|
||||
log.trace("Registry[{}] balance={} < OutboundAmount {}",
|
||||
registry.getId(), regBalance, request.getOutboundAmount());
|
||||
registryO.getId(), regBalance, request.getOutboundAmount());
|
||||
return Optional.of(new EnumMessage(ClearingError.BalanceInsufficient, request.getContract()));
|
||||
}
|
||||
if (!registry.getRefundDate().isAfter(request.getRefundDate())) {
|
||||
if (registryO.getRefundDate().isBefore(request.getRefundDate())) { // дате в регистре >= refundDate
|
||||
log.trace("Registry[{}].RefundDate={} but request RefundDate={}",
|
||||
registry.getId(), registry.getRefundDate(), request.getRefundDate());
|
||||
registryO.getId(), registryO.getRefundDate(), request.getRefundDate());
|
||||
return Optional.of(new EnumMessage(ClearingError.WrongFieldValue, "RefundDate"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,5 +28,5 @@ public enum ValidationStored {
|
|||
|
||||
SecurityBySecurityCode,
|
||||
|
||||
RegistryByContract
|
||||
RegistrysByContract
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue