SDF10
* добавил ограничение на активную сессию * tradingTime
This commit is contained in:
parent
0e2adf5807
commit
19579ec0b0
6 changed files with 113 additions and 18 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,7 @@ public enum ValidationStored {
|
|||
|
||||
ReturnDepositDmx,
|
||||
|
||||
CompanyByTradingCode
|
||||
CompanyByTradingCode,
|
||||
|
||||
SecurityBySecurityCode
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue