clearing-service http://jira.mfd.msk:8088/browse/CLS-307 SPLT todo уточнить ТЗ
This commit is contained in:
parent
94831710e4
commit
99e83b8bf9
4 changed files with 152 additions and 2 deletions
|
|
@ -25,8 +25,10 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
|||
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.RegistryReturnDepositRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
|
||||
import ru.spcex.clearing.service.validation.*;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
|
||||
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
|
||||
import ru.spcex.platform.enumeration.ClearingCategory;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
|
|
@ -336,6 +338,20 @@ public class ValidationConfig {
|
|||
};
|
||||
}
|
||||
|
||||
@Bean("splitDepositValidator")
|
||||
public Function<RegistrySplitDepositActionRequest, IValidator> splitDepositValidator() {
|
||||
return refundDateRequest -> {
|
||||
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()));
|
||||
return new ValidatorImpl<>(context,
|
||||
FieldRequiredRule.instance("contract", RegistrySplitDepositActionRequest::getContract, ClearingError.RequiredFieldEmpty),
|
||||
FieldRequiredRule.instance("refundDate", RegistrySplitDepositActionRequest::getRefundDate, ClearingError.RequiredFieldEmpty)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Function<PIClearingOutbondActionNewRequest, IValidator> piOutboundValidation() {
|
||||
return pmtOut -> {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApp
|
|||
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.RegistryReturnDepositRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.STradesImportedRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
|
||||
|
|
@ -138,6 +139,9 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
|
|||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(event -> registryService.resetBalances())
|
||||
.forDestination(Task.createRegistry_GRYT.topic(), callbacks::put);
|
||||
callback(RegistrySplitDepositActionRequest.class)
|
||||
.setFunction(registryService::splitDeposit)
|
||||
.forDestination(Consts.REGISTRY_SPLIT_DEPOSIT_ACTION, callbacks::put);
|
||||
|
||||
callback(LauncherCommandRequest.class)
|
||||
.setConsumer(task -> {
|
||||
|
|
|
|||
|
|
@ -6,18 +6,22 @@ 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;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
|
||||
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.service.RequestInfoUpdate;
|
||||
import ru.spcex.clearing.platform.messaging.service.Status;
|
||||
import ru.spcex.clearing.service.validation.ValidationStored;
|
||||
import ru.spcex.clearing.session.stage.util.RegistryUtil;
|
||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||
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.ImdgTransaction;
|
||||
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;
|
||||
|
|
@ -43,18 +47,25 @@ public class RegistryService {
|
|||
private final Imdg<Registry> registryImdg;
|
||||
private final Function<RegistryReturnDepositRequest, IValidator> returnDepositVal;
|
||||
private final Function<RegistryChangeRefundDateRequest, IValidator> refundDateVal;
|
||||
private final Function<RegistrySplitDepositActionRequest, IValidator> splitDepositActionVal;
|
||||
|
||||
private final IMessageResolver msgResolver;
|
||||
private final UserRoleVerification rights;
|
||||
|
||||
public RegistryService(ImdgProvider imdgProvider,
|
||||
@Qualifier("returnDepositValidator") Function<RegistryReturnDepositRequest, IValidator> returnDepositVal,
|
||||
@Qualifier("refundDateValidator") Function<RegistryChangeRefundDateRequest, IValidator> refundDateVal,
|
||||
IMessageResolver msgResolver) {
|
||||
@Qualifier("splitDepositValidator") Function<RegistrySplitDepositActionRequest, IValidator> splitDepositActionVal,
|
||||
IMessageResolver msgResolver,
|
||||
UserRoleVerification rights) {
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
this.returnDepositVal = returnDepositVal;
|
||||
this.refundDateVal = refundDateVal;
|
||||
this.splitDepositActionVal = splitDepositActionVal;
|
||||
this.msgResolver = msgResolver;
|
||||
this.rights = rights;
|
||||
}
|
||||
|
||||
public void createRegistry(CreateRegistryRequest createRegistryRequest) {
|
||||
|
|
@ -276,4 +287,122 @@ public class RegistryService {
|
|||
registryImdg.update(registry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public RequestInfoUpdate splitDeposit(BaseRequest<RegistrySplitDepositActionRequest> req) {
|
||||
RegistrySplitDepositActionRequest requestPayload = req.getRequestPayload();
|
||||
RequestInfoUpdate roleCheck = rights.validateRoleAndGetResult(req);
|
||||
if (roleCheck != null) {
|
||||
return roleCheck;
|
||||
}
|
||||
{
|
||||
IValidator validator = splitDepositActionVal.apply(requestPayload);
|
||||
Optional<EnumMessage> err = validator.tillFirstError();
|
||||
if (err.isPresent()) {
|
||||
log.info("RegistrySplitDepositActionRequest request id={} validation error: {}",
|
||||
req.getId(),
|
||||
msgResolver.resolve(err.get()));
|
||||
return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(err.get()));
|
||||
}
|
||||
}
|
||||
|
||||
Registry baseRegistry;
|
||||
{
|
||||
ImdgPredicateBuilder prdBldr = registryImdg.predicateBuilder();
|
||||
ImdgPredicate query = prdBldr.and(
|
||||
RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.OM_T).buildPredicate(prdBldr),
|
||||
prdBldr.equals("contract", requestPayload.getContract()));
|
||||
baseRegistry = registryImdg.getSingleObjectByPredicate(query);
|
||||
if (baseRegistry == null) {
|
||||
String errMsg = msgResolver.resolve(new EnumMessage(ClearingError.TCRegistryNotFound, requestPayload.getContract()));
|
||||
log.info("RegistrySplitDepositActionRequest request id={}, registry query \"{}\": {}",
|
||||
req.getId(), query, errMsg);
|
||||
return new RequestInfoUpdate(req.getId(), Status.Error, errMsg);
|
||||
} else {
|
||||
log.debug("Registry.id={} found by query \"{}\"",
|
||||
baseRegistry.getId(), query);
|
||||
}
|
||||
}
|
||||
{
|
||||
Optional<EnumMessage> err = validateSplitDepositRegister(baseRegistry, requestPayload);
|
||||
if (err.isPresent()) {
|
||||
log.info("RegistrySplitDepositActionRequest request id={} cross validation with registry.id={} error: {}",
|
||||
req.getId(), baseRegistry.getId(), msgResolver.resolve(err.get()));
|
||||
return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(err.get()));
|
||||
}
|
||||
}
|
||||
|
||||
ImdgTransaction txCtx = imdgProvider.newTransaction();
|
||||
boolean txOk = false;
|
||||
txCtx.beginTransaction();
|
||||
try {
|
||||
Imdg<Registry> registryTMap = txCtx.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
Instant now = Instant.now();
|
||||
InOutDirection direction = InOutDirection.out; // todo откуда брать направление?
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 3. Текущим обязательствам установить статус SPLT
|
||||
baseRegistry.setRegistryStatus(RegistryStatus.SPLT.getKey());
|
||||
baseRegistry.setUpdated(Instant.now());
|
||||
registryTMap.update(baseRegistry);
|
||||
|
||||
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();
|
||||
} else {
|
||||
txCtx.rollbackTransaction();
|
||||
log.debug("Transaction rollback {}", txCtx);
|
||||
}
|
||||
}
|
||||
|
||||
return new RequestInfoUpdate(req.getId(), Status.Success, null);
|
||||
}
|
||||
|
||||
private Optional<EnumMessage> validateSplitDepositRegister(Registry registry, RegistrySplitDepositActionRequest request) {
|
||||
if (!RegistryStatus.PROC.equalsByKey(registry.getRegistryStatus())) {
|
||||
log.trace("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) {
|
||||
log.trace("Registry[{}] balance={} < OutboundAmount {}", registry.getId(), regBalance, request.getOutboundAmount());
|
||||
return Optional.of(new EnumMessage(ClearingError.BalanceInsufficient, request.getContract()));
|
||||
}
|
||||
if (!registry.getRefundDate().isAfter(request.getRefundDate())) {
|
||||
log.trace("Registry[{}].RefundDate={} but request RefundDate={}", registry.getId(), registry.getRefundDate(), request.getRefundDate());
|
||||
return Optional.of(new EnumMessage(ClearingError.WrongFieldValue, "RefundDate"));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ public enum RegistryStatus implements IEnumKey {
|
|||
FAIL("FAIL"),
|
||||
UNCV("UNCV"),
|
||||
MNG("MNG"),
|
||||
POOL("POOL")
|
||||
POOL("POOL"),
|
||||
SPLT("SPLT")
|
||||
;
|
||||
|
||||
private final String key;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue