Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
psemenkov 2023-06-07 16:04:08 +03:00
commit 2f2d99e7ce
61 changed files with 4421 additions and 2959 deletions

File diff suppressed because it is too large Load diff

View file

@ -2079,7 +2079,7 @@
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компании","link": "company","linkCode": "shortName","required": true,"enabled": false
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false
}
,
{"code": "documentType",

File diff suppressed because it is too large Load diff

View file

@ -2079,7 +2079,7 @@
"fields": [
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компании","link": "company","linkCode": "shortName","required": true,"enabled": false
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true,"enabled": false
}
,
{"code": "documentType",

View file

@ -51,7 +51,8 @@ public class Sdf16Executor extends AbstractExecutor<SDf16> {
LoggingService errorLogger,
ImdgProvider imdgProvider,
AccountBalanceService accountBalanceService,
IMessageResolver errorResolver, KafkaSender kafaSender) {
IMessageResolver errorResolver,
KafkaSender kafaSender) {
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.sdf17Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf17, SDf17.class);
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);

View file

@ -0,0 +1,252 @@
package ru.spcex.clearing.service.builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.security.Security;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.time.TimeUtil;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
public class PaymentInstructionBuilderFinalMkr {
private final static Logger log = LoggerFactory.getLogger(PaymentInstructionBuilderFinalMkr.class);
private Registry cm_t;
private Registry lm_t;
private Account tranAccount;
private Imdg<Account> accountImdg;
private Imdg<Company> companyImdg;
private Imdg<CompanySymbols> companySymbolsImdg;
private Imdg<Security> securityImdg;
private Long sessionId;
private BigDecimal amount;
protected LocalDate documentNumberResetAt;
protected AtomicLong documentNumberId = new AtomicLong(0L); // порядковый номер (сквозной по всем компаниям за день
private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy");
public static PaymentInstructionBuilderFinalMkr builder(ImdgProvider imdgProvider) {
return new PaymentInstructionBuilderFinalMkr(imdgProvider);
}
private PaymentInstructionBuilderFinalMkr(ImdgProvider imdgProvider) {
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
this.companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
}
public PaymentInstructionBuilderFinalMkr lm_t(Registry lm_t) {
this.lm_t = lm_t;
return this;
}
public PaymentInstructionBuilderFinalMkr cm_t(Registry cm_t) {
this.cm_t = cm_t;
return this;
}
public PaymentInstructionBuilderFinalMkr tranAcc(Account account) {
this.tranAccount = account;
return this;
}
public PaymentInstructionBuilderFinalMkr sessionId(Long sessionId) {
this.sessionId = sessionId;
return this;
}
public PaymentInstructionBuilderFinalMkr amount(BigDecimal amount) {
this.amount = amount;
return this;
}
public Pair<PaymentInstruction, PaymentInstruction> build() {
PaymentInstruction payment1;
PaymentInstruction payment2;
Instant now = Instant.now();
String symbolPRC = selectSymbolValue(Sender.Prc.getId(), CompanySymbol.BIC); // 2 "НКО АО ПРЦ"
{ // record 1
payment1 = new PaymentInstruction();
payment1.setCreated(now);
payment1.setClearingDate(TimeUtil.toLocalDate(now));
payment1.setSenderId(lm_t.getCompanyId());
payment1.setAddresseeId(Sender.One.getId());
String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC);
if (symbol1 == null) {
log.warn("CompanySymbols BIC not found for companyId={}", payment1.getAddresseeId());
} else {
payment1.setAdresseeBic(symbol1);
}
Company companyPRC = companyImdg.getSingleObjectByID(Sender.Prc.getId()); // 2 "НКО АО ПРЦ"
String companyPRCName = null;
if (companyPRC == null) {
log.warn("Company.id={} not found", Sender.Prc.getId());
} else {
companyPRCName = companyPRC.getShortName();
}
payment1.setPayeeBankName(companyPRCName);
payment1.setPayeeBic(symbolPRC);
payment1.setAddresseeBankName(companyPRCName);
payment1.setPaymentDate(TimeUtil.localDateToInstant(lm_t.getSettlementDate()));
payment1.setPaymentPurpose("Размещение депозита " + lm_t.getContract());
payment1.setSettlementDate(lm_t.getSettlementDate());
BigDecimal amount = lm_t.getBalance() == null ? null : lm_t.getBalance().abs();
payment1.setCreditLeg_amount(amount);
payment1.setDebitLeg_amount(amount);
{
Long accountId = lm_t.getAccountId();
Account acc1 = accountImdg.getSingleObjectByID(accountId);
if (acc1 == null) {
log.warn("Account not found: {}", accountId);
} else {
payment1.setCreditLeg_accountId(acc1.getId());
payment1.setCreditLeg_account(acc1.getAccount());
}
}
payment1.setCredit_csAccount(null);
{
Account acc1 = selectAccount(payment1.getAddresseeId(), AccountType.Corr, Status.Active, Allowed.ALLOWED);
if (acc1 != null) {
payment1.setDebitLeg_accountId(acc1.getId());
payment1.setDebitLeg_account(acc1.getAccount());
}
}
payment1.setDebit_csAccount(null);
payment1.setCreditLeg_currencyCode(CurrencyCode.RUB.getKey());
payment1.setDebitLeg_currencyCode(CurrencyCode.RUB.getKey());
payment1.setTransactionStatus(TransactionStatus.stld.getKey());
payment1.setDocumentNumber(nextDocumentNumber(lm_t, payment1));
}
//****************
{ // record 2
payment2 = new PaymentInstruction();
payment2.setCreated(now);
payment2.setClearingDate(TimeUtil.toLocalDate(now));
payment2.setSenderId(Sender.One.getId()); // СПВБ
payment2.setAddresseeId(lm_t.getCompanyId());
String symbol2 = selectSymbolValue(payment2.getAddresseeId(), CompanySymbol.BIC);
if (symbol2 == null) {
log.warn("CompanySymbols BIC not found for companyId={}", payment2.getAddresseeId());
} else {
payment2.setAdresseeBic(symbol2);
}
Company companyPRC = companyImdg.getSingleObjectByID(Sender.Prc.getId());
if (companyPRC == null) {
log.warn("Company.id={} not found", Sender.Prc.getId());
} else {
payment2.setPayeeBankName(companyPRC.getShortName());
payment2.setAddresseeBankName(companyPRC.getShortName());
}
payment2.setPayeeBic(symbolPRC);
payment2.setPaymentDate(TimeUtil.localDateToInstant(lm_t.getSettlementDate()));
payment2.setPaymentPurpose("Размещение депозита " + lm_t.getContract());
payment2.setSettlementDate(lm_t.getSettlementDate());
BigDecimal amount = lm_t.getBalance() == null ? null : lm_t.getBalance().abs();
payment2.setCreditLeg_amount(amount);
payment2.setDebitLeg_amount(amount);
{
payment2.setCreditLeg_accountId(tranAccount.getId());
payment2.setCreditLeg_account(tranAccount.getAccount());
}
payment2.setCredit_csAccount(null);
{
Account acc2 = accountImdg.getSingleObjectByID(cm_t.getAccountId());
if (acc2 != null) {
payment2.setDebitLeg_accountId(acc2.getId());
payment2.setDebitLeg_account(acc2.getAccount());
}
}
payment2.setDebit_csAccount(null);
payment2.setTransactionStatus(TransactionStatus.stld.getKey());
payment2.setDocumentNumber(nextDocumentNumber(cm_t, payment2));
}
return new Pair<>(payment1, payment2);
}
protected String nextDocumentNumber(Registry rgs, PaymentInstruction paymentInstruction) {
LocalDate nowD = LocalDate.now();
if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this) {
long oldNum = documentNumberId.get(); // reset optimistic
if (oldNum > 0) {
while (!documentNumberId.compareAndSet(oldNum, 0)) {
oldNum = documentNumberId.get();
if (oldNum < 2) break;
}
}
documentNumberResetAt = nowD;
}
String paymentDate = DATE_FORMATTER_ddMMyy.format(TimeUtil.toLocalDate(paymentInstruction.getPaymentDate()));
String num = String.format("%s/%s/%s/%s",
rgs.getContract(), paymentDate,
paymentInstruction.getSenderId(), documentNumberId.incrementAndGet()
);
return num;
}
protected String selectSymbolValue(Long companyId, CompanySymbol symbol) {
if (companyId == null) {
return null;
}
CompanySymbols cSymbol = companySymbolsImdg.getSingleObjectByFieldValues(Map.of(
"companyId", companyId,
"companySymbol", symbol.getKey()));
if (cSymbol == null) {
return null;
} else {
return cSymbol.getCompanySymbolValue();
}
}
protected Account selectAccount(Long companyId, AccountType accountType, Status accountStatus, Allowed processingSign) {
if (companyId == null) {
return null;
}
Account account = accountImdg.getSingleObjectByFieldValues(Map.of(
"companyId", companyId,
"accountType", accountType.getKey(),
"accountStatus", accountStatus.getKey(),
"processingSign", processingSign.getKey()
));
if (account == null) {
log.trace("Account not found by: companyId={} accountType={} accountStatus={} processingSign={}",
companyId, accountType.getKey(), accountStatus.getKey(), processingSign.getKey()
);
} else {
log.trace("Found Account.id={} by: companyId={} accountType={} accountStatus={} processingSign={}", account.getId(),
companyId, accountType.getKey(), accountStatus.getKey(), processingSign.getKey()
);
}
return account;
}
}

View file

@ -61,7 +61,7 @@ public class ExecutionDepositComponent {
private final IMessageResolver msgResolver;
private final Function<STrades, IValidator> stradesValidator;
private final KafkaSender kafkaSender;
private static final DateTimeFormatter contractFormatter = DateTimeFormatter.ofPattern("ddMMyyyy");
private static final DateTimeFormatter contractFormatter = DateTimeFormatter.ofPattern("ddMMyy");

View file

@ -47,6 +47,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Pattern;
@Service
public class Sdf57Executor extends AbstractExecutor<SDf57> {
@ -66,7 +67,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
private final Imdg<Security> securityImdg;
private final Imdg<Currency> currencyImdg;
private final IMessageResolver messageResolver;
// private final Pair<>
private final Pattern pattern = Pattern.compile("\\w*/\\d{6}/\\d*/\\d*");
public Sdf57Executor(@Qualifier("sdf57Validator") Function<SDf57, IValidator> sDf57Validator,
LoggingService errorLogger,
@ -182,7 +183,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
}
registryImdg.update(rgs);
};
Consumer<RegistryDesignation> create = (dsgn) -> {
Consumer<RegistryDesignation> createRegA = (dsgn) -> {
Registry registry = createRegistryByStatement(stmt, company, account, dsgn);
Registry registryB = copyRegB(registry);
Registry registryF = copyRegF(registry, registryB.getBalance());
@ -192,11 +193,19 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
registryImdg.insert(registryB);
};
//todo понять что происходит со инициатором/контрагентом, особенно если у нас только один Statement
findRegByDesignation(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A));
if (!StringUtils.isEmpty(sdf57.getSpecif()) && sdf57.getSpecif().contains("")) {
findRegByDesignation(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> createRegA.accept(RegistryDesignation.A));
InOutDirection direction = IEnumKey.getEnumByKey(InOutDirection.class, stmt.getInOutDirection());
if (!StringUtils.isEmpty(sdf57.getSpecif()) && pattern.matcher(sdf57.getSpecif()).find() && InOutDirection.in.equals(direction)) {
//todo доделать 11. Идентификация средств УК на клиринговом счете
findRegByDesignation(stmt, RegistryDesignation.D).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.D));
findRegByDesignation(stmt, RegistryDesignation.D).ifPresentOrElse(rgs -> {
rgs.setBalance(safeBD(rgs.getBalance()).add(safeBD(stmt.getAmount())));
rgs.setUpdated(Instant.now());
registryImdg.update(rgs);
},
() -> findRegByDesignation(stmt, RegistryDesignation.O).ifPresent(rgs -> {
Registry registryD = copyRegD(rgs);
registryImdg.insert(registryD);
}));
}
stmt.setOperationStatus(OperationStatus.Executed.getKey());
} else {
@ -230,6 +239,13 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
return rgsF;
}
private Registry copyRegD(Registry rgs) {
Registry rgsB = rgs.clone();
rgsB.setRegistryDesignation(RegistryDesignation.D.getKey());
rgsB.setRegistryCode(RegistryUtil.clearingCode(rgsB));
return rgsB;
}
private record StmtCmpAcc(Statement statement, Company company, Account account) {
}
@ -363,7 +379,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
pb.equals("companyId", s.getAddresseeId()),
pb.equals("accountId", s.getAccountId())
);
if (des.equals(RegistryDesignation.D) && !TextUtil.isEmpty(s.getContract())) {
if (des.equals(RegistryDesignation.D) || des.equals(RegistryDesignation.O) && !TextUtil.isEmpty(s.getContract())) {
rgstrPredicate = pb.and(rgstrPredicate, pb.equals("contract", s.getContract()));
}
return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate));

View file

@ -61,9 +61,8 @@ public enum RegistryStep3ValidationRule implements IValidationRule<ImdgValidatio
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<Registry> context) {
Registry validatedObject = context.getValidatedObject();
Relation relation = context.getStoredObject(RegistryValidationStored.Relation);
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
Account account = accountImdg.getSingleObjectBySQL("id = %d and relationId = %d".formatted(validatedObject.getAccountId(), relation.getId()));
Account account = accountImdg.getSingleObjectBySQL("id = %d".formatted(validatedObject.getAccountId()));
if (account == null || (!IEnumKey.contains(account.getStatus(), ServiceStatus.Active, ServiceStatus.Reopened))) {
return of(ClearingError.AccountNotActive, validatedObject.getAccountId());
}

View file

@ -9,16 +9,19 @@ import ru.clearing.classes.statics.data.execution.ExecutionCommon;
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
import ru.clearing.classes.statics.data.misc.Session;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.session.stage.impl.*;
import ru.spcex.clearing.session.stage.task.*;
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
import ru.spcex.platform.enumeration.RegistryStatus;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.SessionStatus;
import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import java.time.LocalDate;
@ -37,13 +40,14 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
private final InclusionObligations inclusionObligations;
private final InspectionObligations inspectionObligations;
private final FormingRegistersOnOS formingRegistersOnOS;
private final FormingPaymentInstruction formingPaymentInstruction;
private final FormingPaymentInstructionDealsFinalMkr formingPaymentInstruction;
private final UnlockResources unlockResources;
private final FinishingSession finishingSession;
private final EndStageNotification endStageNotification;
private final Imdg<ExecutionDeposit> executionDepositImdg;
private final Supplier<List<String>> marketCodes;
private final Imdg<Registry> registryImdg;
public FinalMkrSession(
@ -54,7 +58,7 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
ObligationAdmission obligationsAdmission,
InclusionObligations inclusionObligations,
FormingRegistersOnOS formingRegistersOnOS,
FormingPaymentInstruction formingPaymentInstruction,
FormingPaymentInstructionDealsFinalMkr formingPaymentInstruction,
UnlockResources unlockResources,
FinishingSession finishingSession,
EndStageNotification endStageNotification,
@ -75,11 +79,22 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
this.inspectionObligations = inspectionObligations;
this.marketCodes = marketCodes;
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
}
@Override
public void afterPropertiesSet() throws Exception {
dealsPrepare.searchForExecutions(ExecutionType.ExecutionDeposit);
//fixme спросить у Кости нужны ли эти поправки
ImdgPredicateBuilder rgsPrctBuilder = registryImdg.predicateBuilder();
inclusionObligations.addRegistryCondition(
rgsPrctBuilder.or(rgsPrctBuilder.equals("registryStatus", RegistryStatus.PROC.getKey()),
rgsPrctBuilder.equals("registryStatus", RegistryStatus.MNG.getKey()))
);
inclusionObligations.addRegistryCondition(
rgsPrctBuilder.less("valueDate", LocalDate.now())
);
inspectionObligations.setSessionType(sectionType());
}
@Override
@ -187,6 +202,7 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -192,6 +192,7 @@ public class IntermediateMkrSession extends AbstractSession implements Initializ
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -180,6 +180,7 @@ public class PrimaryAuctionB0Session extends AbstractSession implements Initiali
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -178,6 +178,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -179,6 +179,7 @@ public class PrimaryAuctionT0Session extends AbstractSession implements Initiali
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -166,6 +166,7 @@ public class ReturnDepositSession extends AbstractSession implements Initializin
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -179,6 +179,7 @@ public class SecondaryAuctionT0Session extends AbstractSession implements Initia
payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
}
} catch (StageException e) {
//already logged

View file

@ -0,0 +1,303 @@
package ru.spcex.clearing.session.stage.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.sdf.SDf03;
import ru.clearing.classes.statics.data.sdf.SDf12;
import ru.clearing.classes.statics.data.security.Security;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.builder.PaymentInstructionBuilderFinalMkr;
import ru.spcex.clearing.session.stage.ISessionStage;
import ru.spcex.clearing.session.stage.StageResult;
import ru.spcex.clearing.session.stage.Task;
import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload;
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.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
import ru.spcex.platform.utils.time.TimeUtil;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static ru.spcex.platform.enumeration.RegistryTradingParams.CM_T;
import static ru.spcex.platform.enumeration.RegistryTradingParams.LM_T;
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class FormingPaymentInstructionDealsFinalMkr implements ISessionStage {
private final Logger log = LoggerFactory.getLogger(getClass());
//todo remove (set all in single method setImdg(provider -> setImdg1();setIdGenerator();...)
private ImdgProvider imdgProvider;
private ImdgId idGenerator;
private Imdg<Registry> registryImdg;
private Imdg<PaymentInstruction> paymentInstructionImdg;
private Imdg<Security> securityImdg;
private Imdg<Account> accountImdg;
private Imdg<Company> companyImdg;
private Imdg<SDf03> sDf03Imdg;
private Imdg<SDf12> sDf12Imdg;
private KafkaSender kafkaSender;
private final IMessageResolver msgResolver = new SimpleMessageResolver();
@Autowired
public FormingPaymentInstructionDealsFinalMkr(ImdgProvider imdgProvider,
KafkaSender kafkaSender) {
this.kafkaSender = kafkaSender;
this.imdgProvider = imdgProvider;
this.idGenerator = imdgProvider.getImdgIdGenerator();
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
this.sDf03Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf03, SDf03.class);
this.sDf12Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf12, SDf12.class);
this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
}
@Override
public StageResult<?> submit(Task<?> task) {
FormingPaymentInstructionPayload payload = (FormingPaymentInstructionPayload) task.getData();
switch (task.getTaskType()) {
case FormingPaymentInstruction -> {
return formingPaymentInstructions(payload.getSessionId());
}
default -> {
throw new IllegalStateException("Unknown task type: " + task.getTaskType());
}
}
}
private Collection<Registry> selectRegistries() {
ImdgPredicateBuilder rgsPb = registryImdg.predicateBuilder();
RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(
LM_T, CM_T
);
ImdgPredicate rgsCodePrdct = rgsPb.sql(registryCodeSqlBuilder.build());
Collection<Registry> registries = registryImdg.getCollectionObjectsByPredicate(rgsCodePrdct);
return registries.stream()
.filter(rgs -> Objects.equals(rgs.getValueDate(), rgs.getSettlementDate()))
.collect(Collectors.toList());
}
/**
* аккаунт-счет с accountType='TRAN' - это счет СПВБ который принадлежит самой бирже<br>
* хранят деньги разных участников<br>
* в сделке: <br>
* регистр CMAT кому переводить (registry.account)<br>
* регистр LMAT кто переводит деньги (registry.account)<br>
* в итоге создается 2 PaymentInstruction: LMAT -> TRAN счет -> CMAT счет
*/
private StageResult<?> formingPaymentInstructions(Long sessionId) {
Collection<Registry> registries = selectRegistries();
log.debug("found registries.size() = {}", registries.size());
Account tranAcc = accountImdg.getSingleObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'"
.formatted(AccountType.Tran.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey()));
if (tranAcc == null) {
return new StageResult<>(
new EnumMessage(ClearingError.AccountNotPresent, "accountType = " + AccountType.Tran.getKey()),
false);
}
log.debug("found tranAcc.id = {}", tranAcc.getId());
Map<Long, List<Registry>> groups = registries
.stream()
.collect(Collectors.groupingBy(Registry::getGroupId));
log.debug("groups.size = {}", groups.size());
List<PaymentInstruction> allPaymentInstructions = new ArrayList<>();
for (Map.Entry<Long, List<Registry>> group : groups.entrySet()) {
Long groupId = group.getKey();
Function<RegistryTradingParams, Registry> findByCode = rgsCode -> group.getValue()
.stream()
.filter(rgs -> equalsByRegistry(rgsCode, rgs))
.findFirst()
.orElse(null);
Registry rgsCmt = findByCode.apply(CM_T);
Registry rgsLmt = findByCode.apply(LM_T);
if (rgsCmt == null || rgsLmt == null) {
log.error("groupId {} cmt_t {} lm_t {} - both must be present", groupId, rgsCmt, rgsLmt);
continue;
}
log.debug("generating payment instruction for groupId {} cmt_t {} lm_t {}",
groupId,
rgsCmt.getId(),
rgsLmt.getId());
Pair<PaymentInstruction, PaymentInstruction> pmtInstrs = PaymentInstructionBuilderFinalMkr
.builder(imdgProvider)
.cm_t(rgsCmt)
.lm_t(rgsLmt)
.tranAcc(tranAcc)
.sessionId(sessionId)
.build();
Pair.forEach(pmtInstrs, pmtInstr -> {
paymentInstructionImdg.insert(pmtInstr);
allPaymentInstructions.add(pmtInstr);
});
log.debug("generated PaymentInstructions for groupId {}: pmtInstr1.id={} pmtInstr2.id={}",
groupId,
pmtInstrs.getFirst().getId(),
pmtInstrs.getSecond().getId());
}
sendSdfs(allPaymentInstructions);
StageResult<Collection<PaymentInstruction>> stageResult = new StageResult<>(null, true);
stageResult.setStageResult(allPaymentInstructions);
return stageResult;
}
private void sendSdfs(List<PaymentInstruction> formedPaymentInstructions) {
List<SDf03> sDf03Created = new ArrayList<>();
List<SDf12> sDf12Created = new ArrayList<>();
for (PaymentInstruction paymentInstruction : formedPaymentInstructions) {
Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId());
Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId());
if (InstrumentType.CRNC.equalsByKey(security.getInstrumentType()) &&
List.of(AccountType.Corr, AccountType.Clrn).contains(IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()))) {
sDf03Created.add(newSDf03(paymentInstruction));
} else if (!InstrumentType.CRNC.equalsByKey(security.getInstrumentType()) &&
AccountType.Depo.equalsByKey(account.getAccountType())) {
sDf12Created.add(newSDf12(paymentInstruction));
}
}
Long sdf03GroupId = !sDf03Created.isEmpty() ? imdgProvider.getImdgIdGenerator().nextId() : null;
for (SDf03 sDf03 : sDf03Created) {
sDf03.setGenerationId(sdf03GroupId);
sDf03Imdg.insert(sDf03);
}
if (sdf03GroupId != null) {
ExportToFileRequest exportToFileRequest = new ExportToFileRequest();
exportToFileRequest.setNameOfTable("DF-03");
exportToFileRequest.setSdfGroupId(sdf03GroupId);
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportToFileRequest);
}
Long sdf12GroupId = null;
Long maxTxNumber = 1L;
if (!sDf12Created.isEmpty()) {
sdf12GroupId = imdgProvider.getImdgIdGenerator().nextId();
ImdgPredicateBuilder predicateBuilder = sDf12Imdg.predicateBuilder();
ImdgPredicate notEmptyTransactionNum = predicateBuilder.not(predicateBuilder.equals("transaction_number", ""));
Long maxId = sDf12Imdg.aggregateLongMax("id", notEmptyTransactionNum);
if (maxId != null) {
SDf12 sDf12 = sDf12Imdg.getSingleObjectByID(maxId);
maxTxNumber = Long.parseLong(sDf12.getTransactionNumber()) + 1;
}
}
for (SDf12 sDf12 : sDf12Created) {
sDf12.setGenerationId(sdf03GroupId);
sDf12.setTransactionNumber(maxTxNumber.toString());
sDf12.setTransactionQuantity(String.valueOf(sDf12Created.size()));
sDf12Imdg.insert(sDf12);
}
if (sdf12GroupId != null) {
SwtExporterRequest swtExporterRequest = new SwtExporterRequest();
swtExporterRequest.setType("SDF_12");
kafkaSender.sendRequestToQueue(Consts.SWT_EXPORTER, swtExporterRequest);
}
}
private SDf03 newSDf03(PaymentInstruction paymentInstruction) {
log.debug("creating sdf03");
SDf03 sDf03 = new SDf03();
sDf03.setId(idGenerator.nextId());
sDf03.setSeg_type("S");
sDf03.setDoc_type("002");
String strId = paymentInstruction.getId().toString();
String strIdCut = strId.length() > 16 ? strId.substring(strId.length() - 16) : strId;
sDf03.setDocnm_ref(strIdCut);
sDf03.setC_acc_deb(paymentInstruction.getCreditLeg_account());
String senderSbankName = "";
if (paymentInstruction.getSenderId().equals(1L)) {
senderSbankName = paymentInstruction.getPayeeBankName();
} else {
Company company = companyImdg.getSingleObjectByID(paymentInstruction.getSenderId());
if (company != null) {
senderSbankName = company.getShortName();
}
}
sDf03.setSbanknam1(senderSbankName);
sDf03.setSbanknam2(senderSbankName);
sDf03.setSbanknam3(senderSbankName);
sDf03.setSbanknam4(senderSbankName);
sDf03.setSbanknam5(senderSbankName);
sDf03.setC_acc_cred(paymentInstruction.getDebitLeg_account());
String addresseeSbankName = "";
if (paymentInstruction.getAddresseeId().equals(1L)) {
addresseeSbankName = paymentInstruction.getAddresseeBankName();
} else {
Company company = companyImdg.getSingleObjectByID(paymentInstruction.getAddresseeId());
if (company != null) {
addresseeSbankName = company.getShortName();
}
}
sDf03.setRbanknam1(addresseeSbankName);
sDf03.setRbanknam2(addresseeSbankName);
sDf03.setRbanknam3(addresseeSbankName);
sDf03.setRbanknam4(addresseeSbankName);
sDf03.setRbanknam5(addresseeSbankName);
sDf03.setPay_date(payDateFormatter.format(TimeUtil.toLocalDate(paymentInstruction.getPaymentDate())));
sDf03.setPay_val("RUR");
sDf03.setSum_deb(paymentInstruction.getDebitLeg_amount() != null ? paymentInstruction.getDebitLeg_amount().toString() : "");
sDf03.setSpecif_1(paymentInstruction.getPaymentPurpose());
sDf03.setGenerationTime(Instant.now());
sDf03.setPaymentInstructionId(paymentInstruction.getId());
log.debug("successfully processed, new id {}", sDf03.getId());
return sDf03;
}
private SDf12 newSDf12(PaymentInstruction paymentInstruction) {
log.debug("creating sdf12");
SDf12 sDf12 = new SDf12();
sDf12.setId(idGenerator.nextId());
sDf12.setOutDocument(sDf12.getId().toString());
sDf12.setDirection("DELFREE");
sDf12.setQuantity(paymentInstruction.getCreditLeg_amount().toString());
sDf12.setSecurityCode(paymentInstruction.getCreditLeg_securityId().toString());
sDf12.setDepoCodeSender(paymentInstruction.getCreditLeg_account());
sDf12.setDepoCodeAdressee(paymentInstruction.getDebitLeg_account());
// sDf12.setTransactionNumber();
sDf12.setGenerationTime(Instant.now());
return sDf12;
}
DateTimeFormatter payDateFormatter = DateTimeFormatter.ofPattern("dd.MM.yy");
private static boolean equalsByRegistry(RegistryTradingParams code, Registry rgs) {
return code.equalByRegistry(
IEnumKey.getEnumByKey(RegistryDesignation.class, rgs.getRegistryDesignation()),
IEnumKey.getEnumByKey(RegistryInstrumentType.class, rgs.getRegistryInstrumentType()),
IEnumKey.getEnumByKey(RegistryCapacity.class, rgs.getRegistryCapacity()),
IEnumKey.getEnumByKey(RegistryUnit.class, rgs.getRegistryUnit())
);
}
}

View file

@ -13,13 +13,16 @@ import ru.spcex.clearing.session.stage.Task;
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.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
@ -30,6 +33,7 @@ public class InspectionObligations implements ISessionStage {
private ImdgProvider imdgProvider;
private Imdg<Registry> registryImdg;
private final IMessageResolver msgResolver = new SimpleMessageResolver();
private SessionType sessionType;
private final static RegistryTradingParams OS_T;
private final static RegistryTradingParams OM_T;
@ -65,6 +69,10 @@ public class InspectionObligations implements ISessionStage {
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
}
public void setSessionType(SessionType sessionType) {
this.sessionType = sessionType;
}
@Override
public StageResult submit(Task<?> task) {
switch (task.getTaskType()) {
@ -95,6 +103,10 @@ public class InspectionObligations implements ISessionStage {
boolean isUncovered = false;
List<CheckResult> checkResults = new ArrayList<>();
for (Registry obligation : obligationsInGroup) {
if (SessionType.FINL.equals(sessionType) && RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType())) {
checkResults.add(new CheckResult(obligation, false));
continue;
}
String sqlAssetRegistryCondition = searchAssetsByObligationSql(obligation);
log.debug("search asset by registry.id={} sql {}", sqlAssetRegistryCondition, obligation.getId());
Registry asset = registryImdg.getSingleObjectBySQL(sqlAssetRegistryCondition);
@ -154,6 +166,24 @@ public class InspectionObligations implements ISessionStage {
tRegistryWithSameCompany.ifPresent(registry -> updateRegistryStatus(registry, RegistryStatus.FAIL));
}
}
//проверяем есть ли второй день для сделки (он не входит в пул, поэтому ищем отдельно)
if (registries.stream().anyMatch(rgs -> rgs.getRefundDate() != null)) {
Optional<Pair<Long, LocalDate>> groupIdAndSettleDate = registries.stream()
.map(rgs -> new Pair<>(rgs.getGroupId(), rgs.getSettlementDate()))
.filter(pair -> pair.getFirst() != null)
.filter(pair -> pair.getSecond() != null)
.findFirst();
if (groupIdAndSettleDate.isEmpty())
return;
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
Collection<Registry> refundRgs = registryImdg.getCollectionObjectsByPredicate(
pb.and(
pb.equals("groupId", groupIdAndSettleDate.get().getFirst()),
pb.not(pb.equals("settlementDate", groupIdAndSettleDate.get().getSecond()))
)
);
refundRgs.forEach(rgs -> updateRegistryStatus(rgs, RegistryStatus.FAIL));
}
} else {
registries.forEach(registry -> updateRegistryStatus(registry, RegistryStatus.OK));
}

View file

@ -98,7 +98,7 @@ public class RegistryDepoBuilder implements IRegistryBuilder {
boolean isTSelling = regDsgn.equals(RegistryDesignation.T) && side.isSell();
boolean isTBuying = regDsgn.equals(RegistryDesignation.T) && side.isBuy();
if ((isOBuying || isTSelling) && !secondLeg || (isOSelling || isTBuying) && secondLeg) {
if ((isOSelling || isTBuying) && !secondLeg || (isOBuying || isTSelling) && secondLeg) {
reg.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
reg.setBalanceDimension(BalanceDimension.MONY.getKey());
Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", exec.getSettlementCurrency()));
@ -133,11 +133,11 @@ public class RegistryDepoBuilder implements IRegistryBuilder {
reg.setSettledDebit((execDep).getFirstLegAmount());
}
if (secondLeg) {
reg.setSettlementDate(execDep.getFirstLegSettlementDate());
reg.setSettlementCode(execDep.getFirstLegSettlementCode());
} else {
reg.setSettlementDate(execDep.getSecondLegSettlementDate());
reg.setSettlementCode(execDep.getSecondLegSettlementCode());
} else {
reg.setSettlementDate(execDep.getFirstLegSettlementDate());
reg.setSettlementCode(execDep.getFirstLegSettlementCode());
}
reg.setRefundDate(execDep.getSecondLegSettlementDate());
reg.setValueDate(execDep.getFirstLegSettlementDate());

View file

@ -42,8 +42,8 @@ public class ProfileDocumentValidationConfig {
IMDGDistributedNames.Map_Company,
Company.class,
CompanyErrors.RequiredFieldEmpty,
CompanyErrors.CompanyNotFound,
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : CompanyErrors.CompanyDisabled),
CompanyErrors.CompanyNotFound
),
DictionaryPresentRule.instance("documentType",
ProfileDocumentNewRequest::getDocumentType,
IMDGDistributedNames.Map_DocumentTypeDictionary,

View file

@ -9,19 +9,15 @@ import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets;
import ru.spcex.clearing.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.account.InformationAccountNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountTerminationRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.enumeration.AccountType;
import ru.spcex.platform.enumeration.WorkflowStatus;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Service
public class AccountNotificationHelper {
@ -96,4 +92,11 @@ public class AccountNotificationHelper {
Long reqId = kafkaSender.sendRequestToQueue(Consts.INFORMATION_ACCOUNT_SYSTEM_NEW, r);
log.debug("Send request id={}", reqId);
}
public void clientCodeNew(ClientCodeNewRequest clientCodeNewRequest) {
log.debug("Sending messages to account-service {} for company {}",
Consts.DESTINATION_CLIENT_CODE_NEW_UM_COMPANY, clientCodeNewRequest.getCompanyId());
Long reqId = kafkaSender.sendRequestToQueue(Consts.DESTINATION_CLIENT_CODE_NEW_UM_COMPANY, clientCodeNewRequest);
log.debug("Send request id={}", reqId);
}
}

View file

@ -175,9 +175,9 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init
transaction.beginTransaction();
boolean txOk = false;
try {
companyService.relationService.cancelRelation(transaction, clearingMemberCategory.getCompanyId(), clearingMemberCategory);
Imdg<ClearingMemberCategory> txClearingMemberCategoryMap = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
txClearingMemberCategoryMap.delete(clearingMemberCategory);
txClearingMemberCategoryMap.delete(clearingMemberCategory); // далить до cancelRelation внутри транзакции
companyService.relationService.cancelRelation(transaction, clearingMemberCategory.getCompanyId(), clearingMemberCategory);
txOk = true;
} finally {
if (txOk)

View file

@ -379,6 +379,104 @@ public class CompanyService extends QueueConsumer implements InitializingBean {
}
public synchronized Company createOrUpdateCompany(BaseRequest<CompanyNewRequest> companyNewRequestBaseRequest, Long existCompanyId) throws ValidationException {
CompanyNewRequest req = companyNewRequestBaseRequest.getRequestPayload();
log.debug("company new or update, request {}, existCOmpanyId={}", companyNewRequestBaseRequest.getId(), existCompanyId);
{ // Валидация
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(companyNewRequestBaseRequest);
if (requestInfoUpdate != null)
throw new ValidationException(CompanyErrors.GeneralError, requestInfoUpdate.getMessage());
// requestInfoUpdate = validationHelper.validateTillFirstError(companyNewRequestBaseRequest, companyNewRequestValidator);
// if (requestInfoUpdate != null) throw new ValidationException(CompanyErrors.GeneralError, requestInfoUpdate.getMessage());
}
Company company = null;
if (existCompanyId != null) {
company = companyIMap.getSingleObjectByID(existCompanyId);
if (company == null) {
throw new ValidationException(CompanyErrors.CompanyNotFound, String.valueOf(existCompanyId));
}
}
if (company == null) {
// #createCompany
company = new Company();
company.setId(idSequence.nextId());
Instant now = Instant.now();
company.setCreated(now);
company.setUpdated(now);
log.debug("Create new company {}", company.getId());
company.setShortName(req.getShortName());
company.setFullName(req.getFullName());
ImdgTransaction transaction = imdgProvider.newTransaction();
transaction.beginTransaction();
boolean txOk = false;
try {
if (req.getCompanySymbol() != null) {
CompanySymbols newSymbol = companySymbolService.createCompanySymbol(transaction, company.getId(), req.getCompanySymbol(), req.getCompanySymbolValue());
updateCompanyBySymbol(company, newSymbol, false);
}
company.setWorkflowStatus(req.getWorkflowStatus());
fillNewCompanyInfo(company, req);
Imdg<Company> companyMap = transaction.getImdg(IMDGDistributedNames.Map_Company, Company.class);
companyMap.insert(company);
log.debug("company-new request processed, BaseRequest.id = {}, company.id={}",
companyNewRequestBaseRequest.getId(), company.getId());
txOk = true;
} finally {
if (txOk)
transaction.commitTransaction();
else
transaction.rollbackTransaction();
}
accountNotification.makeInfoAccount(company.getId());
} else {
log.debug("Update exist company {}", company.getId());
company.setUpdated(Instant.now());
// #updateCompany
company.setUpdated(Instant.now());
company.setShortName(req.getShortName());
company.setFullName(req.getFullName());
if (req.getCompanySymbol() != null || req.getCompanySymbolValue() != null) {
log.trace("Request field CompanySymbol, CompanySymbolValue ignore for update company request.");
}
// CompanySymbols не обновляем
ImdgTransaction transaction = imdgProvider.newTransaction();
transaction.beginTransaction();
boolean txOk = false;
try {
String prevStatus = company.getWorkflowStatus();
if (req.getWorkflowStatus() != null) {
company.setWorkflowStatus(req.getWorkflowStatus());
if (!Objects.equals(prevStatus, company.getWorkflowStatus())) {
relationService.onChangeWorkflowStatus(transaction, company, prevStatus, company.getWorkflowStatus());
} else {
log.trace("Status was not changed");
}
} else {
log.trace("Null new WorkflowStatus");
}
Imdg<Company> companyMap = transaction.getImdg(IMDGDistributedNames.Map_Company, Company.class);
companyMap.update(company);
txOk = true;
} finally {
if (txOk)
transaction.commitTransaction();
else
transaction.rollbackTransaction();
}
}
return company;
}
/**
* Блокировка компании после блокировки счетов
*

View file

@ -154,9 +154,9 @@ public class CompanySymbolService extends QueueConsumer implements InitializingB
if (companySymbols == null) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyInfoNotFound, req.getId()));
}
if (!companySymbols.getCompanySymbol().equalsIgnoreCase(req.getCompanySymbolValue())) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.EditCompanySymbols, req.getId()));
}
// if (!companySymbols.getCompanySymbol().equalsIgnoreCase(req.getCompanySymbolValue())) {
// throw new ClearingBaseException(new EnumMessage(CompanyErrors.EditCompanySymbols, req.getId()));
// }
companySymbols.setCompanySymbolValue(req.getCompanySymbolValue());
companySymbolsTMap.update(companySymbols);
companyService.updateCompanyBySymbol(transaction, companySymbols, false);

View file

@ -0,0 +1,223 @@
package ru.spcex.clearing.company.service;
import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.*;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.util.security.UserRoleVerification;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.clearing.validation.common.ValidationHelper;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.enumeration.UserRole;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.error.ValidationException;
import ru.spcex.platform.utils.log.ExceptionUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
/**
* Обрабатывает MultiCompanyRequest и распределяет сложный объект по...
*/
@Service
public class MultiCompanyService
extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final RequestHelper requestHelper;
protected UserRoleVerification userRoleVerification;
// private final ValidationHelper validationHelper;
final CompanyService companyService;
final CompanyInfoService companyInfoService;
final ProfileDocumentService profileDocumentService;
final CompanySymbolService companySymbolService;
final ContactService contactService;
final AccountNotificationHelper accountNotification;
final RelationService relationService;
final ImdgProvider imdgProvider;
final Imdg<Company> companyIMap;
final Imdg<CompanySymbols> companySymbolsImdg;
@Autowired
public MultiCompanyService(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaProducer,
ImdgProvider imdgProvider,
RequestHelper requestHelper,
CompanyService companyService,
CompanyInfoService companyInfoService,
ProfileDocumentService profileDocumentService,
CompanySymbolService companySymbolService,
ContactService contactService,
AccountNotificationHelper accountNotification,
RelationService relationService,
ValidationHelper validationHelper
) {
super(kafkaQueue, kafkaProducer);
this.imdgProvider = imdgProvider;
this.requestHelper = requestHelper.setLogger(log);
// this.idSequence = imdgProvider.getImdgIdGenerator();
// this.userRoleVerification = userRoleVerification;
// userRoleVerification.setRoleForVerification(UserRole.Admin);
// this.validationHelper = validationHelper;
this.companyService = companyService;
this.companyInfoService = companyInfoService;
this.profileDocumentService = profileDocumentService;
this.companySymbolService = companySymbolService;
this.contactService = contactService;
this.accountNotification = accountNotification;
this.relationService = relationService;
companyIMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
}
@Override
public void afterPropertiesSet() {
callback(MultiCompanyRequest.class)
.setFunction(request -> requestHelper.requestFunction(this::processMultiRequest, request))
.forDestination(Consts.DESTINATION_COMPANY_MULTIREQUEST, callbacks::put);
init();
}
private synchronized RequestInfoUpdate processMultiRequest(BaseRequest<MultiCompanyRequest> baseRequest) {
MultiCompanyRequest req = baseRequest.getRequestPayload();
log.debug("company-batch-new request received, BaseRequest.id = {}", baseRequest.getId());
{ // Валидация
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(baseRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
}
/*
todo:
1) добавить апдейт кейсы
2) сделать транзакции.
*/
Long companyId = null;
boolean txOk = false;
synchronized (companyService) {
try {
companyId = getCompanyIdForCompanySymbols(req.getUuid(), req.getCompany());
log.debug("For request {} (uuid {}) company {}.", baseRequest.getId(), req.getUuid(), companyId == null ? "not found" : ("found, id=" + companyId));
RequestInfoUpdate replyI;
Company company = companyService.createOrUpdateCompany(wrapRequest(baseRequest, req.getCompany()), companyId);
companyId = company.getId();
log.debug("The companyId={}", companyId);
fillCompanyId(req, companyId);
//todo update case:
replyI = companyInfoService.companyInfoUpdate(wrapRequest(baseRequest, req.getCompanyInfo()));
for (ProfileDocumentNewRequest partRequest : req.getProfileDocuments()) {
replyI = profileDocumentService.profileDocumentNew(wrapRequest(baseRequest, partRequest));
}
for (CompanySymbolNewRequest partRequest : req.getCompanySymbols()) {
replyI = companySymbolService.companySymbolNew(wrapRequest(baseRequest, partRequest));
}
for (ContactNewRequest partRequest : req.getContacts()) {
replyI = contactService.contactNew(wrapRequest(baseRequest, partRequest));
}
txOk = true;
} catch (ValidationException vex) {
log.error("For companyId={} error: {}", companyId, ExceptionUtils.getStackTrace(vex));
}
}
if (txOk) {
log.debug("Create or update sendNewClientCode for company {}", companyId);
for (ClientCodeNewRequest partRequest : req.getClientCodes()) {
accountNotification.clientCodeNew(partRequest); // Consts.DESTINATION_CLIENT_CODE_NEW Consts.DESTINATION_CLIENT_CODE_UPDATE
}
}
return null;
}
Long getCompanyIdForCompanySymbols(String uuid, CompanyNewRequest cnr) {
CompanySymbols companySymbol = null;
if (StringUtils.isNotEmpty(uuid)) {
log.trace("Search company by companySymbol uuid={}", uuid);
Collection<CompanySymbols> companySymbolsFromImdg = companySymbolsImdg.getCollectionObjectsByFieldValues(
Map.of(
"companySymbol", CompanySymbol.UUID.getKey(),
"companySymbolValue", uuid
)
);
if (!companySymbolsFromImdg.isEmpty()) {
companySymbol = companySymbolsFromImdg.iterator().next();
if (companySymbolsFromImdg.size() > 1) {
log.warn("For UUID found > 1 company_symbols, use first (id = {})", companySymbol.getId());
}
}
}
if (companySymbol == null && StringUtils.isNotEmpty(cnr.getCompanySymbol())) {
log.trace("Search company by companySymbol {}={}", cnr.getCompanySymbol(), cnr.getCompanySymbolValue());
Collection<CompanySymbols> companySymbolsFromImdg = companySymbolsImdg.getCollectionObjectsByFieldValues(
Map.of(
"companySymbol", cnr.getCompanySymbol(),
"companySymbolValue", cnr.getCompanySymbolValue()
)
);
if (!companySymbolsFromImdg.isEmpty()) {
companySymbol = companySymbolsFromImdg.iterator().next();
if (companySymbolsFromImdg.size() > 1) {
log.warn("For {} found > 1 company_symbols, use first (id = {})", cnr.getCompanySymbol(), cnr.getCompanySymbolValue());
}
}
}
if (companySymbol != null)
return companySymbol.getCompanyId();
else
return null;
}
private <T> BaseRequest<T> wrapRequest(BaseRequest<?> template, T payload) {
BaseRequest<T> r = new BaseRequest<>();
r.setId(template.getId());
r.setActionType(template.getActionType()); // todo?
r.setUserId(template.getUserId());
r.setCorrelationId(template.getCorrelationId());
r.setRequestPayload(payload);
return r;
}
void fillCompanyId(MultiCompanyRequest req, Long companyId) {
req.getCompany().setId(companyId);
req.getCompanyInfo().setId(companyId);
if (req.getCompanySymbols() == null) req.setCompanySymbols(new ArrayList<>());
if (req.getClientCodes() == null) req.setClientCodes(new ArrayList<>());
if (req.getProfileDocuments() == null) req.setProfileDocuments(new ArrayList<>());
if (req.getContacts() == null) req.setContacts(new ArrayList<>());
for (CompanySymbolNewRequest cs : req.getCompanySymbols()) {
cs.setCompanyId(companyId);
}
for (ClientCodeNewRequest cc : req.getClientCodes()) {
cc.setCompanyId(companyId);
}
for (ProfileDocumentNewRequest pd : req.getProfileDocuments()) {
pd.setCompanyId(companyId);
}
for (ContactNewRequest c : req.getContacts()) {
c.setCompanyId(companyId);
}
}
}

View file

@ -94,7 +94,7 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
}
@NonNull
private RequestInfoUpdate profileDocumentNew(BaseRequest<ProfileDocumentNewRequest> profileDocumentNewRequestBaseRequest) {
protected RequestInfoUpdate profileDocumentNew(BaseRequest<ProfileDocumentNewRequest> profileDocumentNewRequestBaseRequest) {
log.trace("Start processing ProfileDocumentNewRequest!");
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(profileDocumentNewRequestBaseRequest);
@ -146,10 +146,6 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin
log.warn("Company {} not found by profileDocument {}", profileDocument.getCompanyId(), profileDocument.getId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId());
}
if (!WorkflowStatus.Active.equalsByKey(existCompany.getWorkflowStatus())) {
log.debug("Company {} not active", profileDocument.getCompanyId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId());
}
ImdgTransaction transaction = imdgProvider.newTransaction();
transaction.beginTransaction();

View file

@ -272,8 +272,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
return existRelation;
}
Collection<String> selectCompanyClearingMemberCategory(Long companyId) {
Collection<ClearingMemberCategory> companyCategory = clearingMemberCategoryImdg.getCollectionObjectsByFieldValues(
Collection<String> selectCompanyClearingMemberCategory(ImdgTransaction tx, Long companyId) {
Imdg<ClearingMemberCategory> cmcMap = tx == null ? clearingMemberCategoryImdg : tx.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
Collection<ClearingMemberCategory> companyCategory = cmcMap.getCollectionObjectsByFieldValues(
Map.of("companyId", companyId)
);
return companyCategory.stream()
@ -325,7 +326,7 @@ public class RelationService extends QueueConsumer implements InitializingBean {
Relation relation = relationMap.getSingleObjectByID(req.getId());
final Long companyId = relation.getConsumerId();
Collection<String> companyCMC = selectCompanyClearingMemberCategory(companyId);
Collection<String> companyCMC = selectCompanyClearingMemberCategory(null, companyId);
boolean companyCMCisBIV = companyCMC.contains(ClearingCategory.B.getKey()) || companyCMC.contains(ClearingCategory.I.getKey())
|| companyCMC.contains(ClearingCategory.V.getKey());
boolean companyCMCisCF = companyCMC.contains(ClearingCategory.C.getKey()) || companyCMC.contains(ClearingCategory.F.getKey());
@ -335,7 +336,7 @@ public class RelationService extends QueueConsumer implements InitializingBean {
boolean txOk = false;
try {
tx.beginTransaction();
relationUpdate0(tx, req, relation); // первоначальное ТЗ.
//relationUpdate0(tx, req, relation); // первоначальное ТЗ.
boolean needAddNewRelation = false; // call relationNew0(req, companyId, firstCMC);
if (ru.spcex.platform.enumeration.Service.MKR.equalsByKey(relation.getService())) { // relation B or I or V
@ -467,6 +468,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
log.debug("Relation {} already reopened(resumed)", relation.getId());
return relation;
}
if (req.getComment() != null) {
relation.setComment(req.getComment());
}
relation.setServiceStatus(ServiceStatus.Reopened.getKey());
relation.setUpdated(Instant.now());
@ -505,18 +509,19 @@ public class RelationService extends QueueConsumer implements InitializingBean {
Relation relation = relationMap.getSingleObjectByID(req.getId());
Long companyId = relation.getConsumerId();
Collection<String> companyCMC = selectCompanyClearingMemberCategory(companyId);
Collection<String> companyCMC = selectCompanyClearingMemberCategory(null, companyId);
boolean companyCMCisBIV = companyCMC.contains(ClearingCategory.B.getKey()) || companyCMC.contains(ClearingCategory.I.getKey())
|| companyCMC.contains(ClearingCategory.V.getKey());
boolean companyCMCisCF = companyCMC.contains(ClearingCategory.C.getKey()) || companyCMC.contains(ClearingCategory.F.getKey());
String firstCMC = companyCMC.isEmpty() ? null : companyCMC.iterator().next();
if (companyCMCisBIV) {
if (companyCMCisBIV && MKR.equalsByKey(relation.getService())) {
// relation не изменяем
} else if (companyCMCisCF) {
} else if (companyCMCisCF && FOND.equalsByKey(relation.getService())) {
// relation не изменяем
} else {
// удалить.
}
// else ? todo bad logic! Проверить ТЗ.
// else
{
ImdgTransaction tx = imdgProvider.newTransaction();
boolean txOk = false;
@ -588,28 +593,50 @@ public class RelationService extends QueueConsumer implements InitializingBean {
relationMap.insert(relation);
}
/**
* Приходит от ClearingMemberCategory
*/
protected void cancelRelation(ImdgTransaction transaction, Long companyId, ClearingMemberCategory clearingMemberCategory) {
log.debug("Cancelling relations for companyId={} and clearingMemberCategory {}", companyId, clearingMemberCategory == null ? null : clearingMemberCategory.getClearingMemberCategory());
Objects.requireNonNull(companyId, "companyId");
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
String serviceStatus = null;
if (clearingMemberCategory == null) {
log.warn("clearingMemberCategory not set for companyId={}", companyId);
} else {
ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
serviceStatus = serviceForCMC(clearingCategory).getKey();
// String serviceStatus = null;
// if (clearingMemberCategory == null) {
// log.warn("clearingMemberCategory not set for companyId={}", companyId);
// } else {
// ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
// serviceStatus = serviceForCMC(clearingCategory).getKey();
// }
Collection<String> companyCMC = selectCompanyClearingMemberCategory(null, companyId);
if (companyCMC.contains(clearingMemberCategory.getClearingMemberCategory())) {
// never
log.warn("ClearingMemberCategory \"{}\" already exist in set for company {}.", clearingMemberCategory.getClearingMemberCategory(), companyId);
}
boolean companyCMCisBIV = companyCMC.contains(ClearingCategory.B.getKey()) || companyCMC.contains(ClearingCategory.I.getKey())
|| companyCMC.contains(ClearingCategory.V.getKey());
boolean companyCMCisCF = companyCMC.contains(ClearingCategory.C.getKey()) || companyCMC.contains(ClearingCategory.F.getKey());
Relation relation = searchRelation(transaction, clearingMemberCategory.getClearingMemberCategory(), companyId);
if (relation == null) {
log.debug("Relation for clearingMemberCategory.id={} {} not found", clearingMemberCategory.getId(), clearingMemberCategory.getClearingMemberCategory());
return;
} else {
relation.setUpdated(Instant.now());
log.debug("Update exist relation.id={}", relation.getId());
if (companyCMCisBIV && MKR.equalsByKey(relation.getService())) {
// relation не изменяем
log.debug("Relation {} {} lost for ClearingMemberCategory \"{}\".", relation.getId(), relation.getService(), clearingMemberCategory.getClearingMemberCategory());
} else if (companyCMCisCF && FOND.equalsByKey(relation.getService())) {
// relation не изменяем
log.debug("Relation {} {} lost for ClearingMemberCategory \"{}\".", relation.getId(), relation.getService(), clearingMemberCategory.getClearingMemberCategory());
} else {
// удалить.
log.debug("Block exist relation.id={}", relation.getId());
relation.setUpdated(Instant.now());
relation.setServiceStatus(Closed.getKey());
relationMap.update(relation);
log.debug("Relation[{}] updated (closed) by clearingMemberCategory[{}].", relation.getId(), clearingMemberCategory.getId());
}
}
relation.setServiceStatus(Closed.getKey());
log.debug("Relation[{}] updated (closed) by clearingMemberCategory[{}].", relation.getId(), clearingMemberCategory.getId());
relationMap.insert(relation);
}
protected void cancelAllRelationForCompany(ImdgTransaction transaction, Long companyId) {

View file

@ -1,4 +1,4 @@
-- DB version: 3.5.0.28
-- DB version: 3.5.0.31
-- DATA version: 3.5.0.8
/* Dictionaries */
@ -652,11 +652,11 @@ INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1019, 'SECR', 'Инс
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1020, 'SECR', 'Режим %s не найден.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1021, 'SECR', 'Информиция об инструментах Денежного рынка на режимах добавляется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1021, 'SECR', 'Информация об инструментах Денежного рынка на режимах добавляется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1022, 'SECR', 'Информиция об инструментах Денежного рынка на режимах изменяется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1022, 'SECR', 'Информация об инструментах Денежного рынка на режимах изменяется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1023, 'SECR', 'Информиция об инструментах Денежного рынка на режимах блокируется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1023, 'SECR', 'Информация об инструментах Денежного рынка на режимах блокируется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (2000, 'UTIL', 'Общая ошибка модуля utility-service.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -864,7 +864,7 @@ INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (7010, 'SCHD', 'Нев
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (7011, 'SCHD', 'Невозможно добавить задачу на прошедшее время.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (7012, 'SCHD', 'Указанный в задаче нструмент не найден.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (7012, 'SCHD', 'Указанный в задаче инструмент не найден.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (7013, 'SCHD', 'Указанный инструмент неактивен.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;

View file

@ -0,0 +1,35 @@
package ru.spcex.clearing.gatewayapi.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.nio.charset.Charset;
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
public ClientHttpResponse intercept(HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
log.info("Request URI: " + request.getURI());
log.info("Request method: " + request.getMethod());
log.info("Request headers: " + request.getHeaders());
log.info("Request body: " + new String(body, "UTF-8"));
ClientHttpResponse response = execution.execute(request, body);
log.info("Response status code: " + response.getStatusCode());
log.info("Response body: " + StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
return response;
}
}

View file

@ -55,7 +55,7 @@ public class ProcessorConfiguration {
pipeline.add(new PrepareMemberCompanies());
pipeline.add(new ValidateMemberCompanies());
pipeline.add(new CheckMemberCompanyExist(imdgProvider));
pipeline.add(new SendMessageToCompanyServiceWithMemberCompanies(kafkaSender, imdgProvider));
pipeline.add(new CompaniesKafkaMessenger(kafkaSender, imdgProvider));
processor.setPipeline(pipeline);
return processor;
}

View file

@ -7,6 +7,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import java.time.Duration;
import java.util.Collections;
@Configuration
public class RestTemplateConfig {
@ -19,9 +20,11 @@ public class RestTemplateConfig {
@Bean("rest-template")
public RestTemplate restTemplate() {
return builder
RestTemplate restTemplate = builder
.setConnectTimeout(Duration.ofMillis(10000))
.setReadTimeout(Duration.ofMillis(40000))
.build();
restTemplate.setInterceptors(Collections.singletonList(new LoggingInterceptor()));
return restTemplate;
}
}

View file

@ -1,8 +1,6 @@
package ru.spcex.clearing.gatewayapi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
@ -12,16 +10,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
public CommonsRequestLoggingFilter loggingFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludePayload(true);
filter.setIncludeQueryString(true);
filter.setMaxPayloadLength(1000000000);
filter.setAfterMessagePrefix("Income request data: ");
return filter;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")

View file

@ -10,7 +10,7 @@ import java.time.Instant;
import java.time.format.DateTimeFormatter;
public class InstantDeserializer extends JsonDeserializer<Instant> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss:SSS");
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
@Override
public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {

View file

@ -0,0 +1,30 @@
package ru.spcex.clearing.gatewayapi.config.filters;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class CachedHttpServletRequest extends HttpServletRequestWrapper {
private byte[] cachedPayload;
public CachedHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream requestInputStream = request.getInputStream();
this.cachedPayload = StreamUtils.copyToByteArray(requestInputStream);
}
@Override
public ServletInputStream getInputStream() {
return new CachedServletInputStream(this.cachedPayload);
}
@Override
public BufferedReader getReader() {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedPayload);
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
}
}

View file

@ -0,0 +1,44 @@
package ru.spcex.clearing.gatewayapi.config.filters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CachedServletInputStream extends ServletInputStream {
private final Logger log = LoggerFactory.getLogger(getClass());
private InputStream cachedInputStream;
public CachedServletInputStream(byte[] cachedBody) {
this.cachedInputStream = new ByteArrayInputStream(cachedBody);
}
@Override
public boolean isFinished() {
try {
return cachedInputStream.available() == 0;
} catch (IOException exp) {
log.error(exp.getMessage());
}
return false;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
@Override
public int read() throws IOException {
return cachedInputStream.read();
}
}

View file

@ -0,0 +1,34 @@
package ru.spcex.clearing.gatewayapi.config.filters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@Component
@WebFilter(filterName = "RequestCachingFilter", urlPatterns = "/*")
public class RequestCachingFilter extends OncePerRequestFilter {
private final Logger log = LoggerFactory.getLogger(getClass());
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CachedHttpServletRequest cachedHttpServletRequest = new CachedHttpServletRequest(request);
log.info("REQUEST QUERY: " + request.getQueryString());
log.info("REQUEST DATA: " + StreamUtils.copyToString(cachedHttpServletRequest.getInputStream(), StandardCharsets.UTF_8));
filterChain.doFilter(cachedHttpServletRequest, response);
}
}

View file

@ -10,7 +10,7 @@ import java.time.Instant;
import java.time.format.DateTimeFormatter;
public class InstantSerializer extends JsonSerializer<Instant> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss:SSS");
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
@Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {

View file

@ -70,7 +70,7 @@ public class GatewayController {
)
@ResponseBody
public CommonResponse listingsFond(@RequestBody FondListingsRequest request) {
request.validate(validTypes, List.of(Section.FOND));
// request.validate(validTypes, List.of(Section.FOND));
FondListingsRequestParam requestParam = new FondListingsRequestParam(request);
ProcessResult processResult = fondListingsRequestProcessor.process(requestParam);
if (processResult.getError() != null) throw new GatewayException(request, processResult.getError());
@ -91,7 +91,7 @@ public class GatewayController {
)
@ResponseBody
public CommonResponse listingsMM(@RequestBody MMListingsRequest request) {
request.validate(validTypes, List.of(Section.MKR));
// request.validate(validTypes, List.of(Section.MKR));
MMListingsRequestParam requestParam = new MMListingsRequestParam(request);
ProcessResult processResult = mmListingsRequestProcessor.process(requestParam);
if (processResult.getError() != null) throw new GatewayException(request, processResult.getError());
@ -112,7 +112,7 @@ public class GatewayController {
)
@ResponseBody
public CommonResponse companies(@RequestBody CompaniesRequest request) {
request.validate(validTypes, Collections.emptyList());
// request.validate(validTypes, Collections.emptyList());
CompaniesRequestParam requestParam = new CompaniesRequestParam(request);
ProcessResult processResult = companiesRequestProcessor.process(requestParam);
if (processResult.getError() != null) throw new GatewayException(request, processResult.getError());

View file

@ -0,0 +1,104 @@
package ru.spcex.clearing.gatewayapi.logic.companies;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.company.Company;
import ru.spcex.clearing.gatewayapi.logic.ProcessResult;
import ru.spcex.clearing.gatewayapi.logic.Stage;
import ru.spcex.clearing.gatewayapi.request.objects.*;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.*;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.util.List;
/**
* Отправка сообщения к company-service на создание/обновление company
* todo Пока убрал совсем не рабочую логику с sendToQueueWaitForAnswer
*/
public class CompaniesKafkaMessenger extends Stage<CompaniesRequestParam> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final KafkaSender kafkaSender;
private final Imdg<Company> companyImdg;
public CompaniesKafkaMessenger(KafkaSender kafkaSender, ImdgProvider imdgProvider) {
this.kafkaSender = kafkaSender;
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
}
@Override
public ProcessResult process(CompaniesRequestParam param) {
List<MemberCompany> companyList = param.getMemberCompanyList();
for (MemberCompany company : companyList) {
if (company.isInvalidData()) continue;
MultiCompanyRequest multiCompanyRequest = new MultiCompanyRequest();
CompanyNewRequest companyNewRequest = new CompanyNewRequest();
companyNewRequest.setShortName(company.getShortName());
companyNewRequest.setFullName(company.getFullName());
companyNewRequest.setCompanySymbol(CompanySymbol.UUID.getKey());
companyNewRequest.setCompanySymbolValue(company.getId().toString());
multiCompanyRequest.setCompany(companyNewRequest);
MemberCompanyInfo companyInfo = company.getCompanyInfo();
CompanyInfoUpdateRequest companyInfoUpdateRequest = new CompanyInfoUpdateRequest();
companyInfoUpdateRequest.setCountryCode("RUS"); // todo в текущей версии ТЗ присылается в цифровом обозначении
companyInfoUpdateRequest.setProfessionalSign(companyInfo.getProfessionalSign());
companyInfoUpdateRequest.setLegalKind(companyInfo.getLegalKind());
companyInfoUpdateRequest.setOrganizationType(companyInfo.getOrganizationType());
companyInfoUpdateRequest.setResidence(companyInfo.getResidence());
multiCompanyRequest.setCompanyInfo(companyInfoUpdateRequest);
for (MemberCompanySymbols companySymbols : company.getMemberCompanySymbolsList()) {
if (companySymbols.isInvalidData()) continue;
CompanySymbolNewRequest companySymbolNewRequest = new CompanySymbolNewRequest();
companySymbolNewRequest.setCompanySymbol(companySymbols.getCompanySymbol());
companySymbolNewRequest.setCompanySymbolValue(companySymbols.getCompanySymbolValue());
multiCompanyRequest.getCompanySymbols().add(companySymbolNewRequest);
}
for (MemberContact contact : company.getContactList()) {
if (contact.isInvalidData()) continue;
ContactNewRequest contactNewRequest = new ContactNewRequest();
contactNewRequest.setContactType(contact.getContactType());
contactNewRequest.setContactValue(contact.getContactValue());
multiCompanyRequest.getContacts().add(contactNewRequest);
}
for (MemberProfileDocument profileDocument : company.getProfileDocumentList()) {
if (profileDocument.isInvalidData()) continue;
ProfileDocumentNewRequest profileDocumentNewRequest = new ProfileDocumentNewRequest();
profileDocumentNewRequest.setDocumentType(profileDocument.getDocumentType());
profileDocumentNewRequest.setIssueDate(profileDocument.getIssueDate());
profileDocumentNewRequest.setIssuer(profileDocument.getIssuer());
profileDocumentNewRequest.setNumber(profileDocument.getNumber());
profileDocumentNewRequest.setValidToDate(profileDocument.getValidToDate());
profileDocumentNewRequest.setLink(profileDocument.getLink());
multiCompanyRequest.getProfileDocuments().add(profileDocumentNewRequest);
}
for (MemberClient client : company.getClientList()) {
if (client.isInvalidData()) continue;
if (!company.isAlreadyExist() || !client.isAlreadyExist()) {
ClientCodeNewRequest clientCodeNewRequest = new ClientCodeNewRequest();
clientCodeNewRequest.setCode(client.getClientCode());
clientCodeNewRequest.setMoneyAccountId(client.getMoneyAccountId());
clientCodeNewRequest.setDepoAccountId(client.getDepoAccountId());
multiCompanyRequest.getClientCodes().add(clientCodeNewRequest);
}
}
kafkaSender.sendRequestToQueue(Consts.DESTINATION_COMPANY_MULTIREQUEST, multiCompanyRequest);
}
return null;
}
}

View file

@ -1,179 +0,0 @@
package ru.spcex.clearing.gatewayapi.logic.companies;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.company.Company;
import ru.spcex.clearing.gatewayapi.logic.ProcessResult;
import ru.spcex.clearing.gatewayapi.logic.Stage;
import ru.spcex.clearing.gatewayapi.request.objects.*;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeUpdateRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.company.*;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.enumeration.CompanySymbol;
import ru.spcex.platform.enumeration.ServiceStatus;
import ru.spcex.platform.enumeration.WorkflowStatus;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import java.util.List;
import java.util.Map;
/**
* Отправка сообщения к company-service на создание/обновление company
* todo Пока убрал совсем не рабочую логику с sendToQueueWaitForAnswer
*/
public class SendMessageToCompanyServiceWithMemberCompanies extends Stage<CompaniesRequestParam> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final KafkaSender kafkaSender;
private final Imdg<Company> companyImdg;
public SendMessageToCompanyServiceWithMemberCompanies(KafkaSender kafkaSender, ImdgProvider imdgProvider) {
this.kafkaSender = kafkaSender;
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
}
@Override
public ProcessResult process(CompaniesRequestParam param) {
List<MemberCompany> companyList = param.getMemberCompanyList();
for (MemberCompany company : companyList) {
if (company.isInvalidData()) continue;
String companyWorkflowStatus = WorkflowStatus.Active.getKey();
if (!company.getCompanyClearingCategoryList().isEmpty()) {
MemberCompanyClearingCategory clearingCategory = company.getCompanyClearingCategoryList().get(0);
ServiceStatus categoryStatus = IEnumKey.getEnumByKey(ServiceStatus.class, clearingCategory.getWorkflowStatus());
if (categoryStatus == ServiceStatus.Active || categoryStatus == ServiceStatus.Appl || categoryStatus == ServiceStatus.Reopened) {
companyWorkflowStatus = WorkflowStatus.Active.getKey();
} else {
companyWorkflowStatus = WorkflowStatus.Blocked.getKey();
}
}
CompanyNewRequest companyNewRequest = new CompanyNewRequest();
if (company.isAlreadyExist()) companyNewRequest.setId(company.getMapId());
companyNewRequest.setShortName(company.getShortName());
companyNewRequest.setFullName(company.getFullName());
companyNewRequest.setCompanySymbol(CompanySymbol.UUID.getKey());
companyNewRequest.setCompanySymbolValue(company.getId().toString());
MemberCompanyInfo companyInfo = company.getCompanyInfo();
if (company.isAlreadyExist()) {
kafkaSender.sendRequestToQueue(Consts.DESTINATION_COMPANY_UPDATE, companyNewRequest);
} else {
kafkaSender.sendRequestToQueue(Consts.DESTINATION_COMPANY_NEW, companyNewRequest);
Company companyFromImdg = companyImdg.getSingleObjectByFieldValues(
Map.of(
"shortName", company.getShortName(),
"fullName", company.getFullName(),
"workflowStatus", companyWorkflowStatus
)
);
if (companyFromImdg == null) {
log.warn("Can't insert company (UUID {}), skipped", company.getId());
company.setInvalidData(true);
continue;
}
company.setAlreadyExist(true);
company.setMapId(companyFromImdg.getId());
}
Long companyId = company.getMapId();
CompanyInfoUpdateRequest companyInfoUpdateRequest = new CompanyInfoUpdateRequest();
companyInfoUpdateRequest.setId(companyId);
companyInfoUpdateRequest.setCountryCode("RUS"); // todo в текущей версии ТЗ присылается в цифровом обозначении
companyInfoUpdateRequest.setProfessionalSign(companyInfo.getProfessionalSign());
companyInfoUpdateRequest.setLegalKind(companyInfo.getLegalKind());
companyInfoUpdateRequest.setOrganizationType(companyInfo.getOrganizationType());
companyInfoUpdateRequest.setResidence(companyInfo.getResidence());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_COMPANY_UPDATE, companyInfoUpdateRequest);
for (MemberCompanySymbols companySymbols : company.getMemberCompanySymbolsList()) {
if (companySymbols.isInvalidData()) continue;
if (!company.isAlreadyExist() || !companySymbols.isAlreadyExist()) {
CompanySymbolNewRequest companySymbolNewRequest = new CompanySymbolNewRequest();
companySymbolNewRequest.setCompanyId(companyId);
companySymbolNewRequest.setCompanySymbol(companySymbols.getCompanySymbol());
companySymbolNewRequest.setCompanySymbolValue(companySymbols.getCompanySymbolValue());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_COMPANY_SYMBOL_NEW, companySymbolNewRequest);
} else {
CompanySymbolUpdateRequest companySymbolUpdateRequest = new CompanySymbolUpdateRequest();
companySymbolUpdateRequest.setId(companySymbols.getMapId());
companySymbolUpdateRequest.setCompanyId(companyId);
companySymbolUpdateRequest.setCompanySymbolValue(companySymbols.getCompanySymbolValue());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_COMPANY_SYMBOL_UPDATE, companySymbolUpdateRequest);
}
}
for (MemberContact contact : company.getContactList()) {
if (contact.isInvalidData()) continue;
if (!company.isAlreadyExist() || !contact.isAlreadyExist()) {
ContactNewRequest contactNewRequest = new ContactNewRequest();
contactNewRequest.setCompanyId(companyId);
contactNewRequest.setContactType(contact.getContactType());
contactNewRequest.setContactValue(contact.getContactValue());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_CONTACT_NEW, contactNewRequest);
} else {
ContactUpdateRequest contactUpdateRequest = new ContactUpdateRequest();
contactUpdateRequest.setId(contact.getMapId());
contactUpdateRequest.setContactType(contact.getContactType());
contactUpdateRequest.setContactValue(contact.getContactValue());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_CONTACT_UPDATE, contactUpdateRequest);
}
}
for (MemberProfileDocument profileDocument : company.getProfileDocumentList()) {
if (profileDocument.isInvalidData()) continue;
if (!company.isAlreadyExist() || !profileDocument.isAlreadyExist()) {
ProfileDocumentNewRequest profileDocumentNewRequest = new ProfileDocumentNewRequest();
profileDocumentNewRequest.setCompanyId(companyId);
profileDocumentNewRequest.setDocumentType(profileDocument.getDocumentType());
profileDocumentNewRequest.setIssueDate(profileDocument.getIssueDate());
profileDocumentNewRequest.setIssuer(profileDocument.getIssuer());
profileDocumentNewRequest.setNumber(profileDocument.getNumber());
profileDocumentNewRequest.setValidToDate(profileDocument.getValidToDate());
profileDocumentNewRequest.setLink(profileDocument.getLink());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_PROFILE_DOCUMENT_NEW, profileDocumentNewRequest);
} else {
ProfileDocumentUpdateRequest profileDocumentUpdateRequest = new ProfileDocumentUpdateRequest();
profileDocumentUpdateRequest.setId(profileDocument.getMapId());
profileDocumentUpdateRequest.setCompanyId(companyId);
profileDocumentUpdateRequest.setDocumentType(profileDocument.getDocumentType());
profileDocumentUpdateRequest.setIssueDate(profileDocument.getIssueDate());
profileDocumentUpdateRequest.setIssuer(profileDocument.getIssuer());
profileDocumentUpdateRequest.setNumber(profileDocument.getNumber());
profileDocumentUpdateRequest.setValidToDate(profileDocument.getValidToDate());
profileDocumentUpdateRequest.setLink(profileDocument.getLink());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_PROFILE_DOCUMENT_NEW, profileDocumentUpdateRequest);
}
}
for (MemberClient client : company.getClientList()) {
if (client.isInvalidData()) continue;
if (!company.isAlreadyExist() || !client.isAlreadyExist()) {
ClientCodeNewRequest clientCodeNewRequest = new ClientCodeNewRequest();
clientCodeNewRequest.setCompanyId(companyId);
clientCodeNewRequest.setCode(client.getClientCode());
clientCodeNewRequest.setMoneyAccountId(client.getMoneyAccountId());
clientCodeNewRequest.setDepoAccountId(client.getDepoAccountId());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_CLIENT_CODE_NEW, clientCodeNewRequest);
} else {
ClientCodeUpdateRequest clientCodeUpdateRequest = new ClientCodeUpdateRequest();
clientCodeUpdateRequest.setId(client.getMapId());
clientCodeUpdateRequest.setCompanyId(companyId);
clientCodeUpdateRequest.setCode(client.getClientCode());
clientCodeUpdateRequest.setMoneyAccountId(client.getMoneyAccountId());
clientCodeUpdateRequest.setDepoAccountId(client.getDepoAccountId());
kafkaSender.sendRequestToQueue(Consts.DESTINATION_CLIENT_CODE_NEW, clientCodeUpdateRequest);
}
}
}
return null;
}
}

View file

@ -94,7 +94,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
fixedIncomeSecurityNewRequest.setNominalValue(security.getNominalValue());
fixedIncomeSecurityNewRequest.setNominalCurrency(security.getNominalCurrency());
fixedIncomeSecurityNewRequest.setMaturityDate(security.getMaturityDate());
fixedIncomeSecurityNewRequest.setCouponFrequency(security.getCouponFrequency());
fixedIncomeSecurityNewRequest.setCouponFrequency(security.getCouponFrequency().longValue());
fixedIncomeSecurityNewRequest.setIssuerId(companyId);
fixedIncomeSecurityNewRequest.setShortNameEng(security.getShortNameEng());
fixedIncomeSecurityNewRequest.setFullNameEng(security.getFullNameEng());
@ -112,7 +112,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
fixedIncomeSecurityUpdateRequest.setNominalValue(security.getNominalValue());
fixedIncomeSecurityUpdateRequest.setNominalCurrency(security.getNominalCurrency());
fixedIncomeSecurityUpdateRequest.setMaturityDate(security.getMaturityDate());
fixedIncomeSecurityUpdateRequest.setCouponFrequency(security.getCouponFrequency());
fixedIncomeSecurityUpdateRequest.setCouponFrequency(security.getCouponFrequency().longValue());
fixedIncomeSecurityUpdateRequest.setIssuerId(companyId);
fixedIncomeSecurityUpdateRequest.setShortNameEng(security.getShortNameEng());
fixedIncomeSecurityUpdateRequest.setFullNameEng(security.getFullNameEng());

View file

@ -2,8 +2,10 @@ package ru.spcex.clearing.gatewayapi.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.gatewayapi.config.deserializers.InstantDeserializer;
import ru.spcex.clearing.gatewayapi.config.serializers.InstantSerializer;
import ru.spcex.clearing.gatewayapi.errors.GatewayError;
import ru.spcex.clearing.gatewayapi.exception.GatewayException;
import ru.spcex.platform.enumeration.Section;
@ -38,6 +40,7 @@ public class CommonRequest {
@JsonProperty("datetime")
@JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
@ApiModelProperty(
value = "Передавать дату и время формирования JSON объекта в формате «ДД.ММ.ГГГГ ЧЧ:ММ:СС:ссс».",
example = "01.01.2023 12:34:56:789"

View file

@ -2,8 +2,10 @@ package ru.spcex.clearing.gatewayapi.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.gatewayapi.config.deserializers.InstantDeserializer;
import ru.spcex.clearing.gatewayapi.config.serializers.InstantSerializer;
import java.time.Instant;
import java.util.UUID;
@ -32,6 +34,7 @@ public class InboundRequest {
@JsonProperty("datetime")
@JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
@ApiModelProperty(
value = "Передавать дату и время формирования JSON объекта в формате «ДД.ММ.ГГГГ ЧЧ:ММ:СС:ссс».",
example = "01.01.2023 12:34:56:789"
@ -42,7 +45,14 @@ public class InboundRequest {
@ApiModelProperty(
value = "Секция (FOND или MKR)", example = "FOND"
)
private String section;
private String section = "";
// todo Пока так, чтобы отсылал null, в дальнейшем тип надо заменить на используемый в запросе. Возможно с помощью параметризации
@JsonProperty("content")
@ApiModelProperty(
value = "Контент", example = "null"
)
private String content = null;
public UUID getId() {

View file

@ -170,7 +170,7 @@ public class FondSecurity extends WithMapId {
value = "Дополнительная информация\\Количество купонов в год",
example = "1000"
)
private Long couponFrequency;
private BigDecimal couponFrequency;
@ -327,11 +327,11 @@ public class FondSecurity extends WithMapId {
this.couponType = couponType;
}
public Long getCouponFrequency() {
public BigDecimal getCouponFrequency() {
return couponFrequency;
}
public void setCouponFrequency(Long couponFrequency) {
public void setCouponFrequency(BigDecimal couponFrequency) {
this.couponFrequency = couponFrequency;
}

View file

@ -22,6 +22,7 @@ import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.Task;
import java.time.Instant;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
@ -66,6 +67,7 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
InboundRequest inboundRequest = new InboundRequest();
inboundRequest.setId(UUID.randomUUID());
inboundRequest.setType("MEMBER_ON_DEMAND");
@ -89,11 +91,10 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
InboundRequest inboundRequest = new InboundRequest();
inboundRequest.setId(UUID.randomUUID());
inboundRequest.setType("ON_DEMAND");
// todo здесь возникла проблема: место обработки LOCM одно, но в этом месте могут быть сформированы запросы с разными
// section, нужно уточнить как определять какой именно section отправлять в запросе
inboundRequest.setSection(Section.FOND.getKey());
inboundRequest.setDatetime(Instant.now());
HttpEntity<InboundRequest> request = new HttpEntity<>(inboundRequest, httpHeaders);

View file

@ -25,8 +25,8 @@ gateway-api.kafka-consumer.auto-offset-reset=latest
gateway-api.kafka-consumer.linger-ms=1
gateway-api.kafka-consumer.buffer-memory=33554432
gateway-api.inbound-server.enable-ssl=true
gateway-api.inbound-server.enable-ssl=false
gateway-api.inbound-server.host=localhost
gateway-api.inbound-server.port=9999
gateway-api.inbound-server.pathLOCM=/inbound_request
gateway-api.inbound-server.pathLOSC=/inbound_request
gateway-api.inbound-server.port=8080
gateway-api.inbound-server.pathLOCM=test_tomcat9/p1
gateway-api.inbound-server.pathLOSC=test_tomcat9/p2

View file

@ -15,9 +15,11 @@ public enum SecuritiesError implements IErrorEnumId {
CurrencyAlreadyExists(1015L),
CurrencyNotFound(1016L),
ListingAlreadyExist(1017L), // Инструмент на режиме %s уже существует
ListingNotFound(1017L), // Инструмент на режиме %s не найден
ListingNotFound(1018L), // Инструмент на режиме %s не найден
MarketNotFound(1020L), // Режим %s не найден
ListingOnMMSCreatedBySystem(1021L), // Информиция об инструментах Денежного рынка на режимах добавляется автоматически
ListingOnMMSCreatedBySystem(1021L), // Информиция об инструментах Денежного рынка на режимах добавляется автоматически.
ListingOnMMSUpdatedBySystem(1022L), // Информиция об инструментах Денежного рынка на режимах изменяется автоматически.
ListingOnMMSDeletedBySystem(1023L), // Информиция об инструментах Денежного рынка на режимах блокируется автоматически.
;
private final Long id;

View file

@ -101,6 +101,7 @@ public class EquitySecurityService extends QueueConsumer implements Initializing
equity.setInstrumentType(req.getInstrumentType());
equity.setSecurityId(equity.getId());
equity.setCreated(Instant.now());
equity.setUpdated(equity.getCreated());
try {
transaction.beginTransaction();
Imdg<EquitySecurity> equityImdg = transaction.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class);

View file

@ -105,6 +105,7 @@ public class FixedIncomeSecurityService extends QueueConsumer implements Initial
fixedIncome.setInstrumentType(req.getInstrumentType());
fixedIncome.setSecurityId(fixedIncome.getId());
fixedIncome.setCreated(Instant.now());
fixedIncome.setUpdated(fixedIncome.getCreated());
try {
transaction.beginTransaction();
Imdg<FixedIncomeSecurity> fixedIncomeImdg = transaction.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class);

View file

@ -135,7 +135,9 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
mms.setIssuerId(req.getIssuerId());
mms.setSecurityId(mms.getId());
mms.setDescription(req.getDescription());
mms.setConvention(req.getConvention());
mms.setCreated(Instant.now());
mms.setUpdated(mms.getCreated());
if (req.getWorkflowStatus() == null) {
mms.setWorkflowStatus(WorkflowStatus.Active.getKey());
} else {
@ -206,6 +208,7 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
mms.setIssuerId(req.getIssuerId());
mms.setSecurityId(mms.getId());
mms.setDescription(req.getDescription());
mms.setConvention(req.getConvention());
if (req.getWorkflowStatus() != null) {
mms.setWorkflowStatus(req.getWorkflowStatus());
}

View file

@ -2,14 +2,15 @@ package ru.spcex.clearing.securities.validation;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.misc.Listing;
import ru.clearing.classes.statics.data.scheduler.PlannerTemplate;
import ru.clearing.classes.statics.data.security.Security;
import ru.clearing.platform.dictionary.CurrencyCodeDictionary;
import ru.clearing.platform.dictionary.WorkflowStatusDictionary;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.schedule.PlannerTemplateUpdateRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.*;
import ru.spcex.clearing.util.security.SecuritySelector;
import ru.spcex.clearing.securities.errors.SecuritiesError;
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
import ru.spcex.clearing.validation.common.rules.SpecialIdPresentRule;
import ru.spcex.platform.classes.base.SpcexObjectBase;
@ -31,6 +32,7 @@ import java.util.function.Function;
@Component
public class ListingValidationProvider {
final Imdg<SpcexObjectBase> workflowStatusDictionaryImdg;
final Imdg<SpcexObjectBase> currencyCodeDictionaryImdg;
final Imdg<Listing> listingImdg;
final Imdg<ru.clearing.classes.statics.data.misc.Market> marketImdg;
final SecuritySelector securitySelector;
@ -39,6 +41,7 @@ public class ListingValidationProvider {
public ListingValidationProvider(ImdgProvider imdgProvider, SecuritySelector securitySelector) {
this.securitySelector = securitySelector;
this.workflowStatusDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, SpcexObjectBase.class);
this.currencyCodeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, SpcexObjectBase.class);
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, ru.clearing.classes.statics.data.misc.Market.class);
}
@ -49,6 +52,7 @@ public class ListingValidationProvider {
ImdgValidationContext<ListingNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(listingRequest);
context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, currencyCodeDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_Market, marketImdg);
context.addImdg(IMDGDistributedNames.Map_Listing, listingImdg);
return new ValidatorImpl<ImdgValidationContext<ListingNewRequest>>(context,
@ -62,6 +66,16 @@ public class ListingValidationProvider {
SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.MarketNotFound,
true
),
DictionaryPresentRule.instance("tradingCurrency", ListingNewRequest::getTradingCurrency,
IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class,
SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.WrongFieldValue,
false
),
DictionaryPresentRule.instance("workflowStatus", ListingNewRequest::getWorkflowStatus,
IMDGDistributedNames.Map_WorkflowStatusDictionary, WorkflowStatusDictionary.class,
SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.WrongFieldValue,
false
),
new NotSameActiveListing<>(ListingNewRequest::getSecurityId, ListingNewRequest::getMarket)
);
};
@ -72,12 +86,23 @@ public class ListingValidationProvider {
ImdgValidationContext<ListingUpdateRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(mmsRequest);
context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, currencyCodeDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_Listing, listingImdg);
return new ValidatorImpl<>(context,
new PresentById(IMDGDistributedNames.Map_Listing, SecuritiesError.ListingNotFound, true),
new SecurityIdPresentRule<ListingUpdateRequest>("securityId", ListingUpdateRequest::getSecurityId,
(Security security) ->
InstrumentType.RATE.equalsByKey(security.getInstrumentType()) ? SecuritiesError.ListingOnMMSCreatedBySystem : null
InstrumentType.RATE.equalsByKey(security.getInstrumentType()) ? SecuritiesError.ListingOnMMSUpdatedBySystem : null
),
DictionaryPresentRule.instance("tradingCurrency", ListingUpdateRequest::getTradingCurrency,
IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class,
SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.WrongFieldValue,
false
),
DictionaryPresentRule.instance("workflowStatus", ListingUpdateRequest::getWorkflowStatus,
IMDGDistributedNames.Map_WorkflowStatusDictionary, WorkflowStatusDictionary.class,
SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.WrongFieldValue,
false
)
);
};
@ -102,7 +127,7 @@ public class ListingValidationProvider {
Security security = securitySelector.selectSecurityById(listing.getSecurityId());
if (security != null) {
if (InstrumentType.RATE.equalsByKey(security.getInstrumentType()))
return SecuritiesError.ListingOnMMSCreatedBySystem;
return SecuritiesError.ListingOnMMSDeletedBySystem;
}
return null;
}

View file

@ -18,10 +18,12 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.securities.config.ErrorResolverConfig;
import ru.spcex.clearing.securities.config.ValidationConfig;
import ru.spcex.clearing.securities.service.cud.*;
import ru.spcex.clearing.securities.validation.ListingValidationProvider;
import ru.spcex.clearing.securities.validation.ValidationProvider;
import ru.spcex.clearing.test.MatcherFactory;
import ru.spcex.clearing.test.config.ImdgTestConfig;
import ru.spcex.clearing.test.config.KafkaTestConfig;
import ru.spcex.clearing.util.security.SecuritySelector;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
@ -37,7 +39,8 @@ import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProv
EquitySecurityService.class,
FixedIncomeSecurityService.class,
MoneyMarketSecurityService.class,
ListingService.class,
ListingService.class, ListingValidationProvider.class,
SecuritySelector.class,
ImdgTestConfig.class,
KafkaTestConfig.class,
ValidationProvider.class,

View file

@ -24,6 +24,7 @@ class MoneyMarketSecurityFactory {
private String fullName = "estat";
private String shortName = "esasdftat";
private String securitySymbol = "sdfafd";
private String convention = "convention";
private String istin = "istin";
private String termType = AbstractServiceTest.termType;
@ -106,6 +107,7 @@ class MoneyMarketSecurityFactory {
moneyMarketSecurity.setDescription(description);
moneyMarketSecurity.setLotSize(lotSize);
moneyMarketSecurity.setSecuritySymbol(securitySymbol);
moneyMarketSecurity.setConvention(convention);
moneyMarketSecurity.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey());
return moneyMarketSecurity;
@ -131,6 +133,7 @@ class MoneyMarketSecurityFactory {
moneyMarketSecurityUpdateRequest.setIssuerId(issuerId);
moneyMarketSecurityUpdateRequest.setDescription(description);
moneyMarketSecurityUpdateRequest.setSecuritySymbol(securitySymbol);
moneyMarketSecurityUpdateRequest.setConvention(convention);
moneyMarketSecurityUpdateRequest.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey());
return moneyMarketSecurityUpdateRequest;
@ -160,6 +163,7 @@ class MoneyMarketSecurityFactory {
keyRequest.setIsin(istin);
keyRequest.setDescription(description);
keyRequest.setSecuritySymbol(securitySymbol);
keyRequest.setConvention(convention);
keyRequest.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey());

View file

@ -3,13 +3,23 @@ package ru.spcex.clearing.utility.config;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory;
import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory;
import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings;
import ru.spcex.clearing.platform.messaging.service.RequestInfo;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.utility.config.settings.UtilityServiceSettings;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
@Configuration
public class KafkaConfig {
@ -26,4 +36,30 @@ public class KafkaConfig {
return KafkaProducerFactory.producer(settings.getKafkaProducer());
}
@Bean
public ProducerFactory<String, Object> pf(UtilityServiceSettings settings) {
KafkaProducerSettings kafkaSettings = settings.getKafkaProducer();
return KafkaProducerFactory.producerFactory(kafkaSettings);
}
@Bean("kafkaTemplate")
public KafkaTemplate<String, Object> kafkaTemplate(ProducerFactory<String, Object> pf) {
return new KafkaTemplate<>(pf);
}
@Autowired
@Bean
public KafkaSender kafkaSender(@Qualifier("kafkaTemplate") KafkaTemplate<String, Object> kafkaTemplate,
ImdgProvider imdgProvider) {
ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator();
return KafkaSender
.setup()
.setKafkaTemplate(kafkaTemplate)
.idGenerator(imdgIdGenerator::nextId)
.imdgProvider(s -> {
Imdg<RequestInfo> imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class);
return imdg::insert;
})
.build();
}
}

View file

@ -0,0 +1,102 @@
package ru.spcex.clearing.utility.service;
import org.apache.kafka.clients.consumer.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.misc.Notification;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.NotificationFeedbackRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.NotificationNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.NotificationUpdateRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.time.Instant;
import java.time.LocalDate;
import static ru.spcex.clearing.platform.messaging.domain.Consts.*;
import static ru.spcex.platform.enumeration.NotificationStatus.PEND;
import static ru.spcex.platform.enumeration.ObjectType.statement;
@Service
public class NotificationService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<Notification> notificationMap;
private final KafkaSender kafkaSender;
@Autowired
public NotificationService(Consumer<String, Object> kafkaQueue,
ImdgProvider imdgProvider,
KafkaSender kafkaSender) {
super(kafkaQueue);
this.notificationMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Notification, Notification.class);
this.kafkaSender = kafkaSender;
}
@Override
public void afterPropertiesSet() {
callback(NotificationNewRequest.class)
.setConsumer(this::notificationNewRequest)
.forDestination(NOTIFICATION_NEW, callbacks::put);
callback(NotificationUpdateRequest.class)
.setConsumer(this::notificationUpdateRequest)
.forDestination(NOTIFICATION_UPDATE, callbacks::put);
init();
}
private void notificationNewRequest(BaseRequest<NotificationNewRequest> notificationNewRequestBaseRequest) {
log.info("Starting notificationNewRequest processing...");
NotificationNewRequest request = notificationNewRequestBaseRequest.getRequestPayload();
Notification notification = notificationBuilderFromNotificationNewRequest(request);
notificationMap.insert(notification);
log.info("NotificationNewRequest successfully processed! Generated id:\t{}", notification.getId());
}
private void notificationUpdateRequest(BaseRequest<NotificationUpdateRequest> notificationUpdateRequestBaseRequest) {
NotificationUpdateRequest request = notificationUpdateRequestBaseRequest.getRequestPayload();
Long id = request.getId();
log.info("Starting notificationUpdateRequest processing by id: {} ...", id);
Notification notification = notificationMap.getSingleObjectByID(id);
if (notification == null) {
throw new NullPointerException("Notification by id:{" + id + "} is null!");
}
notification.setNotificationStatus(request.getNotificationStatus());
notification.setUpdated(Instant.now());
notificationMap.update(notification);
sendFeedbackString(notification.getObjectType(), notification.getNotificationStatus());
log.info("NotificationUpdateRequest successfully processed!");
}
private Notification notificationBuilderFromNotificationNewRequest(NotificationNewRequest request) {
Notification notification = new Notification();
notification.setClearingDate(LocalDate.now());
notification.setSenderId(request.getSenderId());
notification.setAddresseeId(request.getAddresseeId());
notification.setObjectType(request.getObjectType());
notification.setObjectId(request.getObjectId());
notification.setNotificationStatus(PEND.getKey());
notification.setCreated(Instant.now());
notification.setUpdated(Instant.now());
return notification;
}
private void sendFeedbackString(String objectType, String status) {
if (objectType.equalsIgnoreCase(statement.getKey())) {
kafkaSender.sendRequestToQueue(CLEARING_NOTIFICATION_FEEDBACK, buildFeedbackRequest(status));
} else {
log.warn("Unsupported notification type {}", objectType);
}
}
private NotificationFeedbackRequest buildFeedbackRequest(String status) {
NotificationFeedbackRequest request = new NotificationFeedbackRequest();
request.setNotificationStatus(status);
return request;
}
}

View file

@ -0,0 +1,21 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum NotificationStatus implements IEnumKey {
PEND("PEND"),
CNCL("CNCL"),
ACPT("ACPT"),
READ("READ");
private final String key;
NotificationStatus(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}

View file

@ -14,4 +14,94 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
return isEqualDesignation && isEqualInstrumentType && isEqualCapacity && isEqualUnit;
}
public final static RegistryTradingParams OS_T;
public final static RegistryTradingParams OM_T;
public final static RegistryTradingParams TS_T;
public final static RegistryTradingParams TM_T;
public final static RegistryTradingParams DM_X;
public final static RegistryTradingParams DM_T;
public final static RegistryTradingParams AM_F;
public final static RegistryTradingParams AM_T;
public final static RegistryTradingParams AM_B;
public final static RegistryTradingParams AS_T;
public final static RegistryTradingParams AS_B;
public final static RegistryTradingParams AS_F;
public final static RegistryTradingParams CM_T;
public final static RegistryTradingParams LM_T;
public final static RegistryTradingParams CS_T;
public final static RegistryTradingParams LS_T;
public final static RegistryTradingParams L__T;
static {
OS_T = new RegistryTradingParams(RegistryDesignation.O,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
OM_T = new RegistryTradingParams(RegistryDesignation.O,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
TS_T = new RegistryTradingParams(RegistryDesignation.T,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
TM_T = new RegistryTradingParams(RegistryDesignation.T,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
DM_X = new RegistryTradingParams(RegistryDesignation.D,
RegistryInstrumentType.M,
null,
RegistryUnit.X);
DM_T = new RegistryTradingParams(RegistryDesignation.D,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
AM_F = new RegistryTradingParams(RegistryDesignation.A,
RegistryInstrumentType.M,
null,
RegistryUnit.F);
AM_T = new RegistryTradingParams(RegistryDesignation.A,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
AM_B = new RegistryTradingParams(RegistryDesignation.A,
RegistryInstrumentType.M,
null,
RegistryUnit.B);
AS_T = new RegistryTradingParams(RegistryDesignation.A,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
AS_B = new RegistryTradingParams(RegistryDesignation.A,
RegistryInstrumentType.S,
null,
RegistryUnit.B);
AS_F = new RegistryTradingParams(RegistryDesignation.A,
RegistryInstrumentType.S,
null,
RegistryUnit.F);
CM_T = new RegistryTradingParams(RegistryDesignation.C,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
LM_T = new RegistryTradingParams(RegistryDesignation.L,
RegistryInstrumentType.M,
null,
RegistryUnit.T);
CS_T = new RegistryTradingParams(RegistryDesignation.C,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
LS_T = new RegistryTradingParams(RegistryDesignation.L,
RegistryInstrumentType.S,
null,
RegistryUnit.T);
L__T = new RegistryTradingParams(RegistryDesignation.L,
null,
null,
RegistryUnit.T);
}
}

View file

@ -41,6 +41,7 @@ public interface Consts {
String DESTINATION_PLANNER_UPDATE = "planner-update";
String DESTINATION_PLANNER_DELETE = "planner-delete";
String DESTINATION_COMPANY_MULTIREQUEST = "company-multirequest-new";
String DESTINATION_COMPANY_NEW = "company-new";
String DESTINATION_COMPANY_DELETE = "company-delete";
String DESTINATION_COMPANY_UPDATE = "company-update";
@ -104,6 +105,11 @@ public interface Consts {
String DESTINATION_TRADING_CLEARING_REGISTRY_UPDATE = "trading-clearing-registry-update";
String DESTINATION_TRADING_CLEARING_REGISTRY_BLOCK = "trading-clearing-registry-block";
String CLEARING_NOTIFICATION_FEEDBACK = "clearing-notification-feedback";
String NOTIFICATION_NEW = "notification-new";
String NOTIFICATION_UPDATE = "notification-update";
String DESTINATION_SDF08_NEW = "s-df-08-new";
String DESTINATION_SDF02_NEW = "s-df-02-new";
@ -139,7 +145,7 @@ public interface Consts {
String BALANCE_ACCOUNT_UPDATE = "balance-account-update";
String CONTINUE_CLEARING = "continue-clearing";
String LAUNCHER_NEW = "launcher-new";
String NOTIFICATION_NEW = "notification-new";
String REQUEST_INFO_UPDATE = "request-info-update";

View file

@ -0,0 +1,81 @@
package ru.spcex.clearing.platform.messaging.domain.cud.company;
import com.fasterxml.jackson.annotation.JsonProperty;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
import java.util.ArrayList;
import java.util.List;
public class MultiCompanyRequest {
@JsonProperty
String uuid; // для лога
@JsonProperty
CompanyNewRequest company;
@JsonProperty
CompanyInfoUpdateRequest companyInfo;
@JsonProperty
List<ProfileDocumentNewRequest> profileDocuments = new ArrayList<>();
@JsonProperty
List<CompanySymbolNewRequest> companySymbols = new ArrayList<>();
@JsonProperty
List<ContactNewRequest> contacts = new ArrayList<>();
@JsonProperty
List<ClientCodeNewRequest> clientCodes = new ArrayList<>();
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public CompanyNewRequest getCompany() {
return company;
}
public void setCompany(CompanyNewRequest company) {
this.company = company;
}
public CompanyInfoUpdateRequest getCompanyInfo() {
return companyInfo;
}
public void setCompanyInfo(CompanyInfoUpdateRequest companyInfo) {
this.companyInfo = companyInfo;
}
public List<ProfileDocumentNewRequest> getProfileDocuments() {
return profileDocuments;
}
public void setProfileDocuments(List<ProfileDocumentNewRequest> profileDocuments) {
this.profileDocuments = profileDocuments;
}
public List<CompanySymbolNewRequest> getCompanySymbols() {
return companySymbols;
}
public void setCompanySymbols(List<CompanySymbolNewRequest> companySymbols) {
this.companySymbols = companySymbols;
}
public List<ContactNewRequest> getContacts() {
return contacts;
}
public void setContacts(List<ContactNewRequest> contacts) {
this.contacts = contacts;
}
public List<ClientCodeNewRequest> getClientCodes() {
return clientCodes;
}
public void setClientCodes(List<ClientCodeNewRequest> clientCodes) {
this.clientCodes = clientCodes;
}
}

View file

@ -0,0 +1,17 @@
package ru.spcex.clearing.platform.messaging.domain.cud.utilities;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
public class NotificationFeedbackRequest {
@JsonProperty
public String notificationStatus;
public String getNotificationStatus() {
return notificationStatus;
}
public void setNotificationStatus(String notificationStatus) {
this.notificationStatus = notificationStatus;
}
}

View file

@ -0,0 +1,27 @@
package ru.spcex.clearing.platform.messaging.domain.cud.utilities;
import com.fasterxml.jackson.annotation.JsonProperty;
public class NotificationUpdateRequest {
@JsonProperty
public Long id;
@JsonProperty
public String notificationStatus;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNotificationStatus() {
return notificationStatus;
}
public void setNotificationStatus(String notificationStatus) {
this.notificationStatus = notificationStatus;
}
}