This commit is contained in:
ialbert 2023-09-07 11:12:51 +03:00
parent bb4fe2abe5
commit 1ee7c5a985
9 changed files with 110 additions and 57 deletions

View file

@ -34,10 +34,10 @@ 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.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.number.BigDecimalUtil;
import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
@ -49,6 +49,8 @@ import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
@Service
public class Sdf10Executor {
private final Logger log = LoggerFactory.getLogger(getClass());
@ -65,6 +67,7 @@ public class Sdf10Executor {
private final Function<SDf10, IValidator> sDf10Validator;
private final TradingTimeService tradingTimeService;
private final KafkaSender kafkaSender;
private final SecuritySelector<Security> scrtSlct;
private final static String OK = "OK";
private final static String SYNTAX_ERROR = "Синтаксическая ошибка (файл сформирован неверно)";
@ -98,6 +101,7 @@ public class Sdf10Executor {
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);
this.scrtSlct = new SecuritySelector<>(imdgProvider, Security.class);
}
public void execute(BaseRequest<StatementRequest> systemRequest) {
@ -160,7 +164,9 @@ public class Sdf10Executor {
requests.add(requestFromStatement(stmt, company.getTradingCode(), tcr.getCode(), sDf10.getSecurityCode()));
} else {
SDf11 sDf11 = processedApproved(stmt, sDf10, now, sdf11GroupId);
createDs_t(tcr, company, security, stmt.getAmount(), sDf10.getOutDocument());
BigDecimal amount = InOutDirection.in.equalsByKey(stmt.getInOutDirection()) ?
stmt.getAmount() : safeBD(stmt.getAmount()).negate();
createDs_iWithoutGateway(tcr.getId(), company.getId(), security.getSecuritySymbol(), amount, sDf10.getOutDocument());
sdf11WasCreated = true;
}
}
@ -175,15 +181,34 @@ 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);
private void createDs_iResponseFromGateway(Long accountId, String securitySymbol,
BigDecimal summ, String outDocument) {
Optional<Registry> as_t = rgsMng.searchByAccSec(accountId, securitySymbol, 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());
log.error("AS_T not found for account.id={} security.symbol={}",
accountId, securitySymbol);
return;
}
Registry rgsD = as_t.get().clone();
createDs_i(as_t.get(), summ, outDocument);
}
private void createDs_iWithoutGateway(Long tcrId, Long companyId, String securitySymobl, BigDecimal summ, String outDocument) {
Optional<Registry> as_t = rgsMng.findRelatedAsset(tcrId,
companyId,
securitySymobl,
RegistryTradingParams.AS_T);
if (as_t.isEmpty()) {
log.error("AS_T not found for tcr.id={} company.id={} security.symbol={}",
tcrId, companyId, securitySymobl);
return;
}
createDs_i(as_t.get(), summ, outDocument);
}
private void createDs_i(Registry as_t, BigDecimal summ, String outDocument) {
Registry rgsD = as_t.clone();
rgsD.setRegistryDesignation(RegistryDesignation.D.getKey());
rgsD.setRegistryUnit(RegistryUnit.I.getKey());
rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD));
rgsD.setBalance(summ);
rgsD.setDebit(BigDecimal.ZERO);
@ -193,7 +218,7 @@ public class Sdf10Executor {
rgsD.setRegistryStatus(RegistryStatus.PROC.getKey());
rgsD.setContract(outDocument);
registryImdg.insert(rgsD);
log.debug("created DS*T.id={}", rgsD.getId());
log.debug("created DS*I.id={}", rgsD.getId());
}
private void processedApproved(Statement stmt, SDf10 sDf10, Instant time) {
@ -253,6 +278,14 @@ public class Sdf10Executor {
Instant updatedTime = Instant.now();
if (gatewayMsg.isApproved()) {
Security security = scrtSlct.selectSecurityById(stmt.getSecurityId());
createDs_iResponseFromGateway(
stmt.getAccountId(),
// stmt.getAddresseeId(),
security != null ? security.getSecuritySymbol() : null,
stmt.getAmount().negate(),
sdf10.getOutDocument());
//tcrId, companyId, securitySymbol
processedApproved(stmt, sdf10, updatedTime);
} else {
log.trace("statement.id={}, sdf11.id={}, sdf10.id={} rejected (by gateway answer)",
@ -311,7 +344,7 @@ public class Sdf10Executor {
stmt.setSecurityId(securityId);
stmt.setAccountId(account.getId());
stmt.setAccount(account.getAccount());
BigDecimal amount = BigDecimalUtil.safeBD(new BigDecimal(sdf10.getQuantity())); //fixme safe new BigDecimal
BigDecimal amount = safeBD(new BigDecimal(sdf10.getQuantity())); //fixme safe new BigDecimal
if (amount.compareTo(BigDecimal.ZERO) >= 0) {
stmt.setInOutDirection(InOutDirection.in.getKey());
} else {

View file

@ -92,7 +92,7 @@ public class Sdf20Executor {
direction = InOutDirection.out;
quantity = quantity.negate();
} else direction = InOutDirection.in;
Registry ds_t = validator.getStored(ValidationStored.Sdf20Dst);
Registry ds_i = validator.getStored(ValidationStored.Sdf20Dst);
AssetTrio assets = validator.getStored(ValidationStored.Sdf20Ast);
Company cmp = validator.getStored(ValidationStored.Sdf20Company);
Account acc = validator.getStored(ValidationStored.Sdf20Account);
@ -114,25 +114,26 @@ public class Sdf20Executor {
rgsImdg.insert(assets.a__f());
rgsImdg.insert(assets.a__b());
}
if (ds_t == null) {
ds_t = assets.a__t().clone();
RegistryManager.zeroState(ds_t);
ds_t.setBalance(quantity);
ds_t.setRegistryDesignation(RegistryDesignation.D.getKey());
ds_t.setRegistryCode(RegistryUtil.clearingCode(ds_t));
rgsImdg.insert(ds_t);
log.debug("created DS*T.id={} for sdf20.id={}", ds_t.getId(), sDf20.getId());
} else {
if (ds_i == null) {
ds_i = assets.a__t().clone();
RegistryManager.zeroState(ds_i);
ds_i.setBalance(quantity);
ds_i.setRegistryDesignation(RegistryDesignation.D.getKey());
ds_i.setRegistryUnit(RegistryUnit.I.getKey());
ds_i.setRegistryCode(RegistryUtil.clearingCode(ds_i));
rgsImdg.insert(ds_i);
log.debug("created DS*I.id={} for sdf20.id={}", ds_i.getId(), sDf20.getId());
} else if (RegistryStatus.OK.equalsByKey(ds_i.getRegistryStatus())) {
//защита от повторной обработки
log.debug("DS*T.id={} found for sdf20.id={}. skipping sdf20", ds_t.getId(), sDf20.getId());
log.debug("DS*I.id={} found for sdf20.id={}. skipping sdf20", ds_i.getId(), sDf20.getId());
return;
}
Registry as_t = assets.a__t();
ds_t.setComment(sDf20.getTransactionNumber());
ds_t.setContract(sDf20.getInDocument());
ds_t.setRegistryStatus(RegistryStatus.OK.getKey());
ds_t.setUpdated(now);
ds_i.setComment(sDf20.getTransactionNumber());
ds_i.setContract(sDf20.getInDocument());
ds_i.setRegistryStatus(RegistryStatus.OK.getKey());
ds_i.setUpdated(now);
as_t.setBalance(safeBD(as_t.getBalance()).add(quantity));
if (direction.equals(InOutDirection.in)) {
as_t.setCredit(safeBD(as_t.getCredit()).add(quantity.abs()));
@ -142,7 +143,7 @@ public class Sdf20Executor {
as_t.setCheckBalance(BigDecimalUtil.parseLeadingZeroes(sDf20.getCloseBalance()));
as_t.setUpdated(now);
rgsImdg.update(as_t);
rgsImdg.update(ds_t);
rgsImdg.update(ds_i);
assetsMng.process(assets.a__b(), assets.a__t(), assets.a__f(), BigDecimal.ZERO);
//statement recfree in
@ -152,7 +153,7 @@ public class Sdf20Executor {
log.debug("sdf20.id={}, processing as_t.id={}, as_f.id={}, as_b.id={}, ds_t.id={}. statement.id={}",
sDf20.getId(),
assets.a__t().getId(), assets.a__f().getId(), assets.a__b().getId(),
ds_t.getId(),
ds_i.getId(),
statement.getId());
//только при зачислении на 20 и 21 идет запрос в gateway в Торговую систему
if (InOutDirection.in.equals(direction)) {

View file

@ -23,6 +23,7 @@ import ru.spcex.clearing.service.AnltSearcher;
import ru.spcex.clearing.service.LoggingService;
import ru.spcex.clearing.service.builder.RegistrySecurityBuilder;
import ru.spcex.clearing.service.model.Result;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.clearing.session.stage.util.RegistryUtil;
import ru.spcex.platform.enumeration.*;
@ -68,13 +69,14 @@ public class Sdf21Executor extends AbstractExecutor<SDf21> {
private final Imdg<Currency> currencyImdg;
private final SecuritySelector<Security> scrSlct;
private final AnltSearcher anltSearcher;
private final AssetTBFProcessing assets;
private final IMessageResolver messageResolver;
private final Pattern pattern = Pattern.compile("№.*");
public Sdf21Executor(@Qualifier("sdf21Validator") Function<SDf21, IValidator> sDf21Validator,
LoggingService errorLogger,
ImdgProvider imdgProvider,
IMessageResolver errorResolver, AnltSearcher anltSearcher, IMessageResolver messageResolver) {
IMessageResolver errorResolver, AnltSearcher anltSearcher, AssetTBFProcessing assets, IMessageResolver messageResolver) {
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
@ -90,6 +92,7 @@ public class Sdf21Executor extends AbstractExecutor<SDf21> {
this.errorResolver = errorResolver;
this.scrSlct = new SecuritySelector<>(imdgProvider, Security.class);
this.anltSearcher = anltSearcher;
this.assets = assets;
this.messageResolver = messageResolver;
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
}
@ -167,21 +170,20 @@ public class Sdf21Executor extends AbstractExecutor<SDf21> {
//добавил создание если не найдены
Registry registryUnitB = findRegByUnit(company.getId(), account.getId(), stmt.getContract(), rgs, RegistryUnit.B).orElse(copyRegB(rgs));
Registry registryUnitF = findRegByUnit(company.getId(), account.getId(), stmt.getContract(), rgs, RegistryUnit.F).orElse(copyRegF(rgs, null)); //передаю null т.к. отнимется ниже по коду
registryUnitF.setBalance(rgs.getBalance().subtract(registryUnitB.getBalance()));
registryUnitF.setUpdated(Instant.now());
// registryUnitF.setBalance(rgs.getBalance().subtract(registryUnitB.getBalance()));
// registryUnitF.setUpdated(Instant.now());
//registry F всегда меняется
if (registryUnitF.getId() == null) {
registryImdg.insert(registryUnitF);
log.debug("stmt.id={}, new AM*F.id={}", stmt.getId(), registryUnitF.getId());
} else {
registryImdg.update(registryUnitF);
log.debug("stmt.id={}, updated AM*F.id={}", stmt.getId(), registryUnitF.getId());
}
//нужно сохранить registry B только если его не было
if (registryUnitB.getId() == null) {
registryImdg.insert(registryUnitB);
log.debug("stmt.id={}, new AM*B.id={}", stmt.getId(), registryUnitB.getId());
}
assets.process(registryUnitB, rgs, registryUnitF, BigDecimal.ZERO);
log.debug("stmt.id={}, updated AM*F.id={}", stmt.getId(), registryUnitF.getId());
//нужно сохранить registry B только если его не было
registryImdg.update(rgs);
log.debug("stmt.id={}, updated AM*T.id={}: balance {}/debit {}/ credit {}",
stmt.getId(),

View file

@ -15,16 +15,18 @@ 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.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.number.BigDecimalUtil;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static ru.spcex.platform.enumeration.RegistryTradingParams.*;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
@Service
public class AssetTBFProcessing {
@ -41,10 +43,18 @@ public class AssetTBFProcessing {
safeWrapField(am_t::getBalance, am_t::setBalance);
safeWrapField(am_b::getBalance, am_b::setBalance);
safeWrapField(am_f::getBalance, am_f::setBalance);
Collection<Registry> d__is = searchD__i(am_b.getAccount(),
am_b.getSecuritySymbol(),
am_b.getCompanyId(),
IEnumKey.getEnumByKey(RegistryInstrumentType.class, am_b.getRegistryInstrumentType()));
BigDecimal d__iSum = d__is.stream()
.filter(d__i -> safeBD(d__i.getBalance()).compareTo(BigDecimal.ZERO) < 0)
.map(rgs -> safeBD(rgs.getBalance()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
Instant now = Instant.now();
am_b.setBalance(am_b.getBalance().subtract(sum));
am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance()));
am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance()).add(d__iSum));
am_b.setUpdated(now);
am_f.setUpdated(now);
@ -52,16 +62,23 @@ public class AssetTBFProcessing {
rgsImdg.update(am_f);
}
public void processWithoutChangingB(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) {
safeWrapField(am_t::getBalance, am_t::setBalance);
safeWrapField(am_b::getBalance, am_b::setBalance);
safeWrapField(am_f::getBalance, am_f::setBalance);
Instant now = Instant.now();
private Collection<Registry> searchD__i(String account,
String securitySymbol,
Long companyId,
RegistryInstrumentType instrumentType) {
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
RegistryTradingParams params = new RegistryTradingParams(
RegistryDesignation.D, instrumentType, null, RegistryUnit.I
);
am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance()));
am_f.setUpdated(now);
rgsImdg.update(am_f);
ImdgPredicate d__iPrdct = pb.and(
pb.equals("account", account),
pb.equals("securitySymbol", securitySymbol),
pb.equals("companyId", companyId),
pb.equals("registryStatus", RegistryStatus.PROC.getKey()),
pb.sql(RegistryCodeSqlBuilder.getInstance(params).build())
);
return rgsImdg.getCollectionObjectsByPredicate(d__iPrdct);
}
public void processByAm_b(Registry am_b, BigDecimal sum) {
@ -138,12 +155,12 @@ public class AssetTBFProcessing {
}
public boolean insufficientBalance(Registry registry, BigDecimal amount) {
return BigDecimalUtil.safeBD(registry.getBalance()).compareTo(BigDecimalUtil.safeBD(amount)) < 0;
return safeBD(registry.getBalance()).compareTo(safeBD(amount)) < 0;
}
//точно будет аналогично и с другими полями
private void safeWrapField(Supplier<BigDecimal> getter, Consumer<BigDecimal> setter) {
BigDecimal fieldValue = getter.get();
setter.accept(BigDecimalUtil.safeBD(fieldValue));
setter.accept(safeBD(fieldValue));
}
}

View file

@ -122,10 +122,10 @@ public enum Sdf10ValidationRule implements IValidationRule<ImdgValidationContext
Collection<Registry> rgsDst = registryImdg.getCollectionObjectsByPredicate(
prdctBldr.and(
prdctBldr.equals("registryStatus", RegistryStatus.PROC.getKey()),
prdctByRegistryCode.apply(RegistryTradingParams.DS_T)
prdctByRegistryCode.apply(RegistryTradingParams.DS_I)
)
);
log.trace("validating sdf10 id={} account={} companyId={} found registries: AS*F.id={} DS*T.size={}",
log.trace("validating sdf10 id={} account={} companyId={} found registries: AS*F.id={} DS*I.size={}",
sdf10.getId(), account.getAccount(), company.getId(),
rgsAsf == null ? null : rgsAsf.getId(),
rgsDst.size()

View file

@ -135,15 +135,15 @@ public enum Sdf20ValidationRule implements IValidationRule<ImdgValidationContext
String security = sDf20.getSecurity();
Account acc = context.getStoredObject(ValidationStored.Sdf20Account);
if (TextUtil.isEmpty(transactionNumber) || TextUtil.isEmpty(security) || acc == null) {
return of(ClearingError.RecordNotFound, "DS*T");
return of(ClearingError.RecordNotFound, "DS*I");
}
Imdg<Registry> rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class);
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
ImdgPredicate dstPrdct = pb.and(
pb.sql(RegistryCodeSqlBuilder.getInstance(DS_T).build()),
pb.sql(RegistryCodeSqlBuilder.getInstance(DS_I).build()),
pb.equals("accountId", acc.getId()),
pb.equals("securitySymbol", security),
pb.equals("comment", transactionNumber)
pb.equals("contract", sDf20.getInDocument())
);
Registry ds_t = rgsImdg.getFirstObjectByPredicate(dstPrdct);
if (ds_t != null) {

View file

@ -50,7 +50,7 @@ public enum Sdf21ValidationRule implements IValidationRule<ImdgValidationContext
Imdg<Registry> rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class);
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.DS_T).build()),
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.DS_I).build()),
pb.equals("comment", sdf21.getTransactionNumber())
);
if (OperationCode.DELFREE.equalsByKey(sdf21.getOperationCode())) {

View file

@ -21,7 +21,7 @@ import java.util.List;
import java.util.function.Function;
import static ru.spcex.platform.enumeration.RegistryTradingParams.AS_F;
import static ru.spcex.platform.enumeration.RegistryTradingParams.DS_T;
import static ru.spcex.platform.enumeration.RegistryTradingParams.DS_I;
@Service
public class SecurityExporterService extends AbstractExporterService {
@ -50,7 +50,7 @@ public class SecurityExporterService extends AbstractExporterService {
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
Function<Registry, ImdgPredicate> prdct = registry -> pb.and(
pb.sql(RegistryCodeSqlBuilder.getInstance(DS_T).build()),
pb.sql(RegistryCodeSqlBuilder.getInstance(DS_I).build()),
pb.equals("registryStatus", RegistryStatus.PROC.getKey()),
pb.equals("companyId", registry.getCompanyId()),
pb.equals("tradingClearingRegistry", registry.getTradingClearingRegistry()),

View file

@ -27,7 +27,7 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
public final static RegistryTradingParams A__B;
public final static RegistryTradingParams A__T;
public final static RegistryTradingParams AS_T;
public final static RegistryTradingParams DS_T;
public final static RegistryTradingParams DS_I;
public final static RegistryTradingParams AS_B;
public final static RegistryTradingParams AS_F;
public final static RegistryTradingParams CM_T;
@ -149,10 +149,10 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
RegistryInstrumentType.M,
RegistryCapacity.A,
RegistryUnit.U);
DS_T = new RegistryTradingParams(RegistryDesignation.D,
DS_I = new RegistryTradingParams(RegistryDesignation.D,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
RegistryUnit.I);
D__I = new RegistryTradingParams(RegistryDesignation.D,
null,
null,