* добавил ограничение на активную сессию
* tradingTime
This commit is contained in:
ialbert 2023-08-16 19:47:52 +03:00
parent 0e2adf5807
commit 19579ec0b0
6 changed files with 113 additions and 18 deletions

View file

@ -289,6 +289,7 @@ public class ValidationConfig {
Sdf10ValidationRule.DepoAccountPresent,
CompanyByTradingCodeValidationRule.instance(SDf10::getDepoCode),
Sdf10ValidationRule.CompanyStatus,
Sdf06NewValidationRule.Session,
Sdf10ValidationRule.TcrPresent,
SecurityBySecurityCodeValidationRule.instance(SDf10::getSecurityCode),
Sdf10ValidationRule.Balance

View file

@ -12,8 +12,10 @@ import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity;
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.scheduler.PlannerAllToday;
import ru.clearing.classes.statics.data.sdf.SDf10;
import ru.clearing.classes.statics.data.sdf.SDf11;
import ru.clearing.classes.statics.data.security.Security;
import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
@ -26,11 +28,14 @@ import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApp
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse;
import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.RegistryManager;
import ru.spcex.clearing.service.validation.ValidationStored;
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.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
@ -41,10 +46,8 @@ 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.Map;
import java.util.Optional;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
@Service
@ -61,6 +64,8 @@ public class Sdf10Executor {
private final Imdg<Company> companyImdg;
private final Imdg<SDf10> sdf10Imdg;
private final Imdg<SDf11> sdf11Imdg;
private final Imdg<PlannerAllToday> plannerAllTodayImdg;
private final RegistryManager rgsMng;
private final ImdgId idGenerator;
private final IMessageResolver messageResolver;
private final Function<SDf10, IValidator> sDf10Validator;
@ -75,6 +80,7 @@ public class Sdf10Executor {
private final static String NOT_FOUND_SECURITY = "Не найден код ценной бумаги";
private final static String INVALID_SUM = "Недопустимая сумма списания";
private final static String PREVIOUS_REQUEST_NOT_PROCESSED = "Процесс обработки предыдущего SDF10 не завершен";
private final static String SESSION_IS_ACTIVE = "Существует активная сессия";
private final static String GENERAL_ERROR = "Общая ошибка обработки SDF10";
private Long sdf10GroupId;
@ -82,7 +88,7 @@ public class Sdf10Executor {
@Autowired
public Sdf10Executor(ImdgProvider imdgProvider,
IMessageResolver messageResolver,
RegistryManager rgsMng, IMessageResolver messageResolver,
@Qualifier("sdf10Validator") Function<SDf10, IValidator> sDf10Validator,
KafkaSender kafkaSender) {
this.imdgProvider = imdgProvider;
@ -94,11 +100,13 @@ public class Sdf10Executor {
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
this.idGenerator = imdgProvider.getImdgIdGenerator();
this.rgsMng = rgsMng;
this.messageResolver = messageResolver;
this.sDf10Validator = sDf10Validator;
this.kafkaSender = kafkaSender;
this.sdf10Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf10, SDf10.class);
this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class);
this.plannerAllTodayImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PlannerAllToday, PlannerAllToday.class);
}
public void execute(BaseRequest<StatementRequest> systemRequest) {
@ -153,11 +161,12 @@ public class Sdf10Executor {
Statement stmt = createStatementBySdf10(sDf10, company.getId(), account);
statementImdg.insert(stmt);
log.debug("Statement created: {}", stmt.getId());
if (InOutDirection.in.getKey().equals(stmt.getInOutDirection())) {
processedApproved(stmt, sDf10, now, sdf11GroupId);
sdf11WasCreated = true;
} else {
if (InOutDirection.out.getKey().equals(stmt.getInOutDirection()) && isTradingTime()) {
requests.add(requestFromStatement(stmt, company.getTradingCode(), tcr.getCode(), sDf10.getSecurityCode()));
} else {
SDf11 sDf11 = processedApproved(stmt, sDf10, now, sdf11GroupId);
createDs_t(tcr, company, validator.getStored(ValidationStored.SecurityBySecurityCode), stmt.getAmount(), sDf11.getOutDocument());
sdf11WasCreated = true;
}
}
if (requests.size() > 0) {
@ -171,11 +180,57 @@ public class Sdf10Executor {
}
}
//company, depoAccount, Security, Summ
private void createDs_t(TradingClearingRegistry tcr, Company company, Security security, BigDecimal summ, String outDocument) {
Optional<Registry> as_t = rgsMng.findRelatedAsset(tcr.getId(), company.getId(), security.getSecuritySymbol(), RegistryTradingParams.AS_T);
if (as_t.isEmpty()) {
log.error("AS_T not found for tcr.id={} company.id={} security.symbol={}", tcr.getId(), company.getId(), security.getSecuritySymbol());
return;
}
Registry rgsD = as_t.get().clone();
rgsD.setRegistryDesignation(RegistryDesignation.D.getKey());
rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD));
rgsD.setBalance(summ);
rgsD.setDebit(BigDecimal.ZERO);
rgsD.setCredit(BigDecimal.ZERO);
rgsD.setDiffBalance(BigDecimal.ZERO);
rgsD.setCheckBalance(BigDecimal.ZERO);
rgsD.setRegistryStatus(RegistryStatus.PROC.getKey());
rgsD.setContract(outDocument);
registryImdg.insert(rgsD);
log.debug("created DS*T.id={}", rgsD.getId());
}
private boolean isTradingTime() {
ImdgPredicateBuilder pb = plannerAllTodayImdg.predicateBuilder();
Function<Task, Optional<PlannerAllToday>> plannerByTask = task -> {
ImdgPredicate plannerPrdct = pb.and(
pb.equals("task", task.getKey()),
pb.equals("taskStatus", TaskStatus.Active.getKey()),
pb.equals("clearingDate", LocalDate.now())
);
return Optional.ofNullable(plannerAllTodayImdg.getFirstObjectByPredicate(plannerPrdct));
};
LocalTime startTradingTime = plannerByTask.apply(Task.createRegistry_STRS)
.map(PlannerAllToday::getTaskTime)
.orElse(null);
LocalTime endTradingTime = plannerByTask.apply(Task.createRegistry_ETRS)
.map(PlannerAllToday::getTaskTime)
.orElse(null);
if (startTradingTime == null || endTradingTime == null) {
log.warn("startTradingTime or endTradingTime is null");
return false;
}
LocalTime now = LocalTime.now();
log.debug("now: {}, startTradingTime: {}, endTradingTime: {}", now, startTradingTime, endTradingTime);
return !now.isBefore(startTradingTime) && !now.isAfter(endTradingTime);
}
private void processedApproved(Statement stmt, SDf10 sDf10, Instant time) {
processedApproved(stmt, sDf10, time, sdf11GroupId);
}
private void processedApproved(Statement stmt, SDf10 sDf10, Instant time, Long sdf11GenerationId) {
private SDf11 processedApproved(Statement stmt, SDf10 sDf10, Instant time, Long sdf11GenerationId) {
log.trace("statement.id={}, sdf11.id={}, sdf10.id={} executed",
stmt.getId(),
sDf10.getGenerationId(),
@ -187,6 +242,7 @@ public class Sdf10Executor {
stmt.setUpdated(time);
stmt.setOutSDfId(sdf11.getId());
statementImdg.update(stmt);
return sdf11;
}
public void processGatewayResponse(BaseRequest<AssetOperationApprovalRequest> req) {
@ -266,8 +322,8 @@ public class Sdf10Executor {
private SDf11 createSdf11(SDf10 sdf10, Instant time, String result) {
SDf11 sdf11 = new SDf11();
sdf11.setOutDocument(sdf10.getOutDocument());
// sdf11.setInDocument();
sdf11.setOutDocument(UUID.randomUUID().toString());
sdf11.setInDocument(sdf10.getOutDocument());
sdf11.setDepoCode(sdf10.getDepoCode());
sdf11.setQuantity(sdf10.getQuantity());
sdf11.setSecurityCode(sdf10.getSecurityCode());
@ -334,6 +390,9 @@ public class Sdf10Executor {
if (ClearingError.BalanceInsufficient.equals(err)) {
return INVALID_SUM;
}
if (ClearingError.ActiveSessionIsPresent.equals(err)) {
return SESSION_IS_ACTIVE;
}
return GENERAL_ERROR;
}
}

View file

@ -10,6 +10,7 @@ import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.sdf.SDf10;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.enumeration.RegistryStatus;
import ru.spcex.platform.enumeration.RegistryTradingParams;
import ru.spcex.platform.enumeration.WorkflowStatus;
import ru.spcex.platform.imdg.api.Imdg;
@ -29,7 +30,7 @@ import java.util.Optional;
import java.util.function.Function;
public enum Sdf10ValidationRule implements IValidationRule<ImdgValidationContext<SDf10>> {
DepoAccountPresent() {
DepoAccountPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<SDf10> context) {
SDf10 sdf10 = context.getValidatedObject();
@ -118,14 +119,22 @@ public enum Sdf10ValidationRule implements IValidationRule<ImdgValidationContext
prdctBldr.equals("companyId", company.getId()),
prdctBldr.sql(RegistryCodeSqlBuilder.getInstance(code).build()));
Registry rgsAsf = registryImdg.getSingleObjectByPredicate(prdctByRegistryCode.apply(RegistryTradingParams.AS_F));
Registry rgsDst = registryImdg.getSingleObjectByPredicate(prdctByRegistryCode.apply(RegistryTradingParams.DS_T));
log.trace("validating sdf10 id={} account={} companyId={} found registries: AS*F.id={} DS*T.id={}",
Collection<Registry> rgsDst = registryImdg.getCollectionObjectsByPredicate(
prdctBldr.and(
prdctBldr.equals("registryStatus", RegistryStatus.PROC.getKey()),
prdctByRegistryCode.apply(RegistryTradingParams.DS_T)
)
);
log.trace("validating sdf10 id={} account={} companyId={} found registries: AS*F.id={} DS*T.size={}",
sdf10.getId(), account.getAccount(), company.getId(),
rgsAsf == null ? null : rgsAsf.getId(),
rgsDst == null ? null : rgsDst.getId()
rgsDst.size()
);
BigDecimal asfBalance = rgsAsf == null ? BigDecimal.ZERO : BigDecimalUtil.safeBD(rgsAsf.getBalance());
BigDecimal dstBalance = rgsDst == null ? BigDecimal.ZERO : BigDecimalUtil.safeBD(rgsDst.getBalance());
BigDecimal dstBalance = rgsDst.stream()
.map(rgs -> BigDecimalUtil.safeBD(rgs.getBalance()))
.filter(balance -> balance.compareTo(BigDecimal.ZERO) > 0)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal stmtAmount = BigDecimalUtil.safeBD(new BigDecimal(sdf10.getQuantity())); //fixme safe new BigDecimal
if (asfBalance.subtract(dstBalance).compareTo(stmtAmount.abs()) < 0) {
return of(ClearingError.BalanceInsufficient);

View file

@ -42,6 +42,7 @@ public class SecurityBySecurityCodeValidationRule<T> implements IValidationRule<
if (security == null) {
return of(ClearingError.SecurityNotFound, securitySymbol);
}
context.storeObject(ValidationStored.SecurityBySecurityCode, security);
return empty();
}
}

View file

@ -18,5 +18,7 @@ public enum ValidationStored {
ReturnDepositDmx,
CompanyByTradingCode
CompanyByTradingCode,
SecurityBySecurityCode
}

View file

@ -0,0 +1,23 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum TaskStatus implements IEnumKey {
Active("ACTV"),
;
private final String key;
TaskStatus(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
public String topic() {
return "launcher-" + getKey();
}
}