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": [ "fields": [
{"code": "companyId", {"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", {"code": "documentType",

File diff suppressed because it is too large Load diff

View file

@ -2079,7 +2079,7 @@
"fields": [ "fields": [
{"code": "companyId", {"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", {"code": "documentType",

View file

@ -51,7 +51,8 @@ public class Sdf16Executor extends AbstractExecutor<SDf16> {
LoggingService errorLogger, LoggingService errorLogger,
ImdgProvider imdgProvider, ImdgProvider imdgProvider,
AccountBalanceService accountBalanceService, AccountBalanceService accountBalanceService,
IMessageResolver errorResolver, KafkaSender kafaSender) { IMessageResolver errorResolver,
KafkaSender kafaSender) {
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.sdf17Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf17, SDf17.class); this.sdf17Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf17, SDf17.class);
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.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 IMessageResolver msgResolver;
private final Function<STrades, IValidator> stradesValidator; private final Function<STrades, IValidator> stradesValidator;
private final KafkaSender kafkaSender; 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.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Pattern;
@Service @Service
public class Sdf57Executor extends AbstractExecutor<SDf57> { public class Sdf57Executor extends AbstractExecutor<SDf57> {
@ -66,7 +67,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
private final Imdg<Security> securityImdg; private final Imdg<Security> securityImdg;
private final Imdg<Currency> currencyImdg; private final Imdg<Currency> currencyImdg;
private final IMessageResolver messageResolver; 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, public Sdf57Executor(@Qualifier("sdf57Validator") Function<SDf57, IValidator> sDf57Validator,
LoggingService errorLogger, LoggingService errorLogger,
@ -182,7 +183,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
} }
registryImdg.update(rgs); registryImdg.update(rgs);
}; };
Consumer<RegistryDesignation> create = (dsgn) -> { Consumer<RegistryDesignation> createRegA = (dsgn) -> {
Registry registry = createRegistryByStatement(stmt, company, account, dsgn); Registry registry = createRegistryByStatement(stmt, company, account, dsgn);
Registry registryB = copyRegB(registry); Registry registryB = copyRegB(registry);
Registry registryF = copyRegF(registry, registryB.getBalance()); Registry registryF = copyRegF(registry, registryB.getBalance());
@ -192,11 +193,19 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
registryImdg.insert(registryB); registryImdg.insert(registryB);
}; };
//todo понять что происходит со инициатором/контрагентом, особенно если у нас только один Statement findRegByDesignation(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> createRegA.accept(RegistryDesignation.A));
findRegByDesignation(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A)); InOutDirection direction = IEnumKey.getEnumByKey(InOutDirection.class, stmt.getInOutDirection());
if (!StringUtils.isEmpty(sdf57.getSpecif()) && sdf57.getSpecif().contains("№")) { if (!StringUtils.isEmpty(sdf57.getSpecif()) && pattern.matcher(sdf57.getSpecif()).find() && InOutDirection.in.equals(direction)) {
//todo доделать 11. Идентификация средств УК на клиринговом счете //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()); stmt.setOperationStatus(OperationStatus.Executed.getKey());
} else { } else {
@ -230,6 +239,13 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
return rgsF; 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) { 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("companyId", s.getAddresseeId()),
pb.equals("accountId", s.getAccountId()) 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())); rgstrPredicate = pb.and(rgstrPredicate, pb.equals("contract", s.getContract()));
} }
return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate)); return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate));

View file

@ -61,9 +61,8 @@ public enum RegistryStep3ValidationRule implements IValidationRule<ImdgValidatio
@Override @Override
public Optional<EnumMessage> validate(ImdgValidationContext<Registry> context) { public Optional<EnumMessage> validate(ImdgValidationContext<Registry> context) {
Registry validatedObject = context.getValidatedObject(); Registry validatedObject = context.getValidatedObject();
Relation relation = context.getStoredObject(RegistryValidationStored.Relation);
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); 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))) { if (account == null || (!IEnumKey.contains(account.getStatus(), ServiceStatus.Active, ServiceStatus.Reopened))) {
return of(ClearingError.AccountNotActive, validatedObject.getAccountId()); 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.execution.ExecutionDeposit;
import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.misc.Session;
import ru.clearing.classes.statics.data.payment.PaymentInstruction; 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.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.session.stage.impl.*; import ru.spcex.clearing.session.stage.impl.*;
import ru.spcex.clearing.session.stage.task.*; import ru.spcex.clearing.session.stage.task.*;
import ru.spcex.platform.classes.base.interfaces.ExecutionType; 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.Section;
import ru.spcex.platform.enumeration.SessionStatus; import ru.spcex.platform.enumeration.SessionStatus;
import ru.spcex.platform.enumeration.SessionType; import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
import java.time.LocalDate; import java.time.LocalDate;
@ -37,13 +40,14 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
private final InclusionObligations inclusionObligations; private final InclusionObligations inclusionObligations;
private final InspectionObligations inspectionObligations; private final InspectionObligations inspectionObligations;
private final FormingRegistersOnOS formingRegistersOnOS; private final FormingRegistersOnOS formingRegistersOnOS;
private final FormingPaymentInstruction formingPaymentInstruction; private final FormingPaymentInstructionDealsFinalMkr formingPaymentInstruction;
private final UnlockResources unlockResources; private final UnlockResources unlockResources;
private final FinishingSession finishingSession; private final FinishingSession finishingSession;
private final EndStageNotification endStageNotification; private final EndStageNotification endStageNotification;
private final Imdg<ExecutionDeposit> executionDepositImdg; private final Imdg<ExecutionDeposit> executionDepositImdg;
private final Supplier<List<String>> marketCodes; private final Supplier<List<String>> marketCodes;
private final Imdg<Registry> registryImdg;
public FinalMkrSession( public FinalMkrSession(
@ -54,7 +58,7 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
ObligationAdmission obligationsAdmission, ObligationAdmission obligationsAdmission,
InclusionObligations inclusionObligations, InclusionObligations inclusionObligations,
FormingRegistersOnOS formingRegistersOnOS, FormingRegistersOnOS formingRegistersOnOS,
FormingPaymentInstruction formingPaymentInstruction, FormingPaymentInstructionDealsFinalMkr formingPaymentInstruction,
UnlockResources unlockResources, UnlockResources unlockResources,
FinishingSession finishingSession, FinishingSession finishingSession,
EndStageNotification endStageNotification, EndStageNotification endStageNotification,
@ -75,11 +79,22 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
this.inspectionObligations = inspectionObligations; this.inspectionObligations = inspectionObligations;
this.marketCodes = marketCodes; this.marketCodes = marketCodes;
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
} }
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
dealsPrepare.searchForExecutions(ExecutionType.ExecutionDeposit); 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 @Override
@ -187,6 +202,7 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
payload.setSection(currSession.getSection()); payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId()); payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification); runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
} }
} catch (StageException e) { } catch (StageException e) {
//already logged //already logged

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -179,6 +179,7 @@ public class SecondaryAuctionT0Session extends AbstractSession implements Initia
payload.setSection(currSession.getSection()); payload.setSection(currSession.getSection());
payload.setSessionId(currSession.getId()); payload.setSessionId(currSession.getId());
runStage(TaskType.EndStageNotification, payload, endStageNotification); runStage(TaskType.EndStageNotification, payload, endStageNotification);
endSession();
} }
} catch (StageException e) { } catch (StageException e) {
//already logged //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.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; 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.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.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -30,6 +33,7 @@ public class InspectionObligations implements ISessionStage {
private ImdgProvider imdgProvider; private ImdgProvider imdgProvider;
private Imdg<Registry> registryImdg; private Imdg<Registry> registryImdg;
private final IMessageResolver msgResolver = new SimpleMessageResolver(); private final IMessageResolver msgResolver = new SimpleMessageResolver();
private SessionType sessionType;
private final static RegistryTradingParams OS_T; private final static RegistryTradingParams OS_T;
private final static RegistryTradingParams OM_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); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
} }
public void setSessionType(SessionType sessionType) {
this.sessionType = sessionType;
}
@Override @Override
public StageResult submit(Task<?> task) { public StageResult submit(Task<?> task) {
switch (task.getTaskType()) { switch (task.getTaskType()) {
@ -95,6 +103,10 @@ public class InspectionObligations implements ISessionStage {
boolean isUncovered = false; boolean isUncovered = false;
List<CheckResult> checkResults = new ArrayList<>(); List<CheckResult> checkResults = new ArrayList<>();
for (Registry obligation : obligationsInGroup) { 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); String sqlAssetRegistryCondition = searchAssetsByObligationSql(obligation);
log.debug("search asset by registry.id={} sql {}", sqlAssetRegistryCondition, obligation.getId()); log.debug("search asset by registry.id={} sql {}", sqlAssetRegistryCondition, obligation.getId());
Registry asset = registryImdg.getSingleObjectBySQL(sqlAssetRegistryCondition); Registry asset = registryImdg.getSingleObjectBySQL(sqlAssetRegistryCondition);
@ -154,6 +166,24 @@ public class InspectionObligations implements ISessionStage {
tRegistryWithSameCompany.ifPresent(registry -> updateRegistryStatus(registry, RegistryStatus.FAIL)); 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 { } else {
registries.forEach(registry -> updateRegistryStatus(registry, RegistryStatus.OK)); 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 isTSelling = regDsgn.equals(RegistryDesignation.T) && side.isSell();
boolean isTBuying = regDsgn.equals(RegistryDesignation.T) && side.isBuy(); 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.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
reg.setBalanceDimension(BalanceDimension.MONY.getKey()); reg.setBalanceDimension(BalanceDimension.MONY.getKey());
Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", exec.getSettlementCurrency())); Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", exec.getSettlementCurrency()));
@ -133,11 +133,11 @@ public class RegistryDepoBuilder implements IRegistryBuilder {
reg.setSettledDebit((execDep).getFirstLegAmount()); reg.setSettledDebit((execDep).getFirstLegAmount());
} }
if (secondLeg) { if (secondLeg) {
reg.setSettlementDate(execDep.getFirstLegSettlementDate());
reg.setSettlementCode(execDep.getFirstLegSettlementCode());
} else {
reg.setSettlementDate(execDep.getSecondLegSettlementDate()); reg.setSettlementDate(execDep.getSecondLegSettlementDate());
reg.setSettlementCode(execDep.getSecondLegSettlementCode()); reg.setSettlementCode(execDep.getSecondLegSettlementCode());
} else {
reg.setSettlementDate(execDep.getFirstLegSettlementDate());
reg.setSettlementCode(execDep.getFirstLegSettlementCode());
} }
reg.setRefundDate(execDep.getSecondLegSettlementDate()); reg.setRefundDate(execDep.getSecondLegSettlementDate());
reg.setValueDate(execDep.getFirstLegSettlementDate()); reg.setValueDate(execDep.getFirstLegSettlementDate());

View file

@ -42,8 +42,8 @@ public class ProfileDocumentValidationConfig {
IMDGDistributedNames.Map_Company, IMDGDistributedNames.Map_Company,
Company.class, Company.class,
CompanyErrors.RequiredFieldEmpty, CompanyErrors.RequiredFieldEmpty,
CompanyErrors.CompanyNotFound, CompanyErrors.CompanyNotFound
company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : CompanyErrors.CompanyDisabled), ),
DictionaryPresentRule.instance("documentType", DictionaryPresentRule.instance("documentType",
ProfileDocumentNewRequest::getDocumentType, ProfileDocumentNewRequest::getDocumentType,
IMDGDistributedNames.Map_DocumentTypeDictionary, 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.company.error.CompanyErrors;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts; 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.InformationAccountNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountTerminationRequest; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountTerminationRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; 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.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
@Service @Service
public class AccountNotificationHelper { public class AccountNotificationHelper {
@ -96,4 +92,11 @@ public class AccountNotificationHelper {
Long reqId = kafkaSender.sendRequestToQueue(Consts.INFORMATION_ACCOUNT_SYSTEM_NEW, r); Long reqId = kafkaSender.sendRequestToQueue(Consts.INFORMATION_ACCOUNT_SYSTEM_NEW, r);
log.debug("Send request id={}", reqId); 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(); transaction.beginTransaction();
boolean txOk = false; boolean txOk = false;
try { try {
companyService.relationService.cancelRelation(transaction, clearingMemberCategory.getCompanyId(), clearingMemberCategory);
Imdg<ClearingMemberCategory> txClearingMemberCategoryMap = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); 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; txOk = true;
} finally { } finally {
if (txOk) 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) { if (companySymbols == null) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyInfoNotFound, req.getId())); throw new ClearingBaseException(new EnumMessage(CompanyErrors.CompanyInfoNotFound, req.getId()));
} }
if (!companySymbols.getCompanySymbol().equalsIgnoreCase(req.getCompanySymbolValue())) { // if (!companySymbols.getCompanySymbol().equalsIgnoreCase(req.getCompanySymbolValue())) {
throw new ClearingBaseException(new EnumMessage(CompanyErrors.EditCompanySymbols, req.getId())); // throw new ClearingBaseException(new EnumMessage(CompanyErrors.EditCompanySymbols, req.getId()));
} // }
companySymbols.setCompanySymbolValue(req.getCompanySymbolValue()); companySymbols.setCompanySymbolValue(req.getCompanySymbolValue());
companySymbolsTMap.update(companySymbols); companySymbolsTMap.update(companySymbols);
companyService.updateCompanyBySymbol(transaction, companySymbols, false); 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 @NonNull
private RequestInfoUpdate profileDocumentNew(BaseRequest<ProfileDocumentNewRequest> profileDocumentNewRequestBaseRequest) { protected RequestInfoUpdate profileDocumentNew(BaseRequest<ProfileDocumentNewRequest> profileDocumentNewRequestBaseRequest) {
log.trace("Start processing ProfileDocumentNewRequest!"); log.trace("Start processing ProfileDocumentNewRequest!");
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(profileDocumentNewRequestBaseRequest); 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()); log.warn("Company {} not found by profileDocument {}", profileDocument.getCompanyId(), profileDocument.getId());
return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId()); 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(); ImdgTransaction transaction = imdgProvider.newTransaction();
transaction.beginTransaction(); transaction.beginTransaction();

View file

@ -272,8 +272,9 @@ public class RelationService extends QueueConsumer implements InitializingBean {
return existRelation; return existRelation;
} }
Collection<String> selectCompanyClearingMemberCategory(Long companyId) { Collection<String> selectCompanyClearingMemberCategory(ImdgTransaction tx, Long companyId) {
Collection<ClearingMemberCategory> companyCategory = clearingMemberCategoryImdg.getCollectionObjectsByFieldValues( Imdg<ClearingMemberCategory> cmcMap = tx == null ? clearingMemberCategoryImdg : tx.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
Collection<ClearingMemberCategory> companyCategory = cmcMap.getCollectionObjectsByFieldValues(
Map.of("companyId", companyId) Map.of("companyId", companyId)
); );
return companyCategory.stream() return companyCategory.stream()
@ -325,7 +326,7 @@ public class RelationService extends QueueConsumer implements InitializingBean {
Relation relation = relationMap.getSingleObjectByID(req.getId()); Relation relation = relationMap.getSingleObjectByID(req.getId());
final Long companyId = relation.getConsumerId(); 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()) boolean companyCMCisBIV = companyCMC.contains(ClearingCategory.B.getKey()) || companyCMC.contains(ClearingCategory.I.getKey())
|| companyCMC.contains(ClearingCategory.V.getKey()); || companyCMC.contains(ClearingCategory.V.getKey());
boolean companyCMCisCF = companyCMC.contains(ClearingCategory.C.getKey()) || companyCMC.contains(ClearingCategory.F.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; boolean txOk = false;
try { try {
tx.beginTransaction(); tx.beginTransaction();
relationUpdate0(tx, req, relation); // первоначальное ТЗ. //relationUpdate0(tx, req, relation); // первоначальное ТЗ.
boolean needAddNewRelation = false; // call relationNew0(req, companyId, firstCMC); boolean needAddNewRelation = false; // call relationNew0(req, companyId, firstCMC);
if (ru.spcex.platform.enumeration.Service.MKR.equalsByKey(relation.getService())) { // relation B or I or V 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()); log.debug("Relation {} already reopened(resumed)", relation.getId());
return relation; return relation;
} }
if (req.getComment() != null) {
relation.setComment(req.getComment());
}
relation.setServiceStatus(ServiceStatus.Reopened.getKey()); relation.setServiceStatus(ServiceStatus.Reopened.getKey());
relation.setUpdated(Instant.now()); relation.setUpdated(Instant.now());
@ -505,18 +509,19 @@ public class RelationService extends QueueConsumer implements InitializingBean {
Relation relation = relationMap.getSingleObjectByID(req.getId()); Relation relation = relationMap.getSingleObjectByID(req.getId());
Long companyId = relation.getConsumerId(); 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()) boolean companyCMCisBIV = companyCMC.contains(ClearingCategory.B.getKey()) || companyCMC.contains(ClearingCategory.I.getKey())
|| companyCMC.contains(ClearingCategory.V.getKey()); || companyCMC.contains(ClearingCategory.V.getKey());
boolean companyCMCisCF = companyCMC.contains(ClearingCategory.C.getKey()) || companyCMC.contains(ClearingCategory.F.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 не изменяем // relation не изменяем
} else if (companyCMCisCF) { } else if (companyCMCisCF && FOND.equalsByKey(relation.getService())) {
// relation не изменяем // relation не изменяем
} else {
// удалить.
} }
// else ? todo bad logic! Проверить ТЗ. // else
{ {
ImdgTransaction tx = imdgProvider.newTransaction(); ImdgTransaction tx = imdgProvider.newTransaction();
boolean txOk = false; boolean txOk = false;
@ -588,28 +593,50 @@ public class RelationService extends QueueConsumer implements InitializingBean {
relationMap.insert(relation); relationMap.insert(relation);
} }
/**
* Приходит от ClearingMemberCategory
*/
protected void cancelRelation(ImdgTransaction transaction, Long companyId, ClearingMemberCategory 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"); Objects.requireNonNull(companyId, "companyId");
Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); Imdg<Relation> relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
String serviceStatus = null; // String serviceStatus = null;
if (clearingMemberCategory == null) { // if (clearingMemberCategory == null) {
log.warn("clearingMemberCategory not set for companyId={}", companyId); // log.warn("clearingMemberCategory not set for companyId={}", companyId);
} else { // } else {
ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory()); // ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory());
serviceStatus = serviceForCMC(clearingCategory).getKey(); // 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); Relation relation = searchRelation(transaction, clearingMemberCategory.getClearingMemberCategory(), companyId);
if (relation == null) { if (relation == null) {
log.debug("Relation for clearingMemberCategory.id={} {} not found", clearingMemberCategory.getId(), clearingMemberCategory.getClearingMemberCategory()); log.debug("Relation for clearingMemberCategory.id={} {} not found", clearingMemberCategory.getId(), clearingMemberCategory.getClearingMemberCategory());
return;
} else { } else {
relation.setUpdated(Instant.now()); if (companyCMCisBIV && MKR.equalsByKey(relation.getService())) {
log.debug("Update exist relation.id={}", relation.getId()); // 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) { 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 -- DATA version: 3.5.0.8
/* Dictionaries */ /* 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 (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; 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 (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; 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 PrepareMemberCompanies());
pipeline.add(new ValidateMemberCompanies()); pipeline.add(new ValidateMemberCompanies());
pipeline.add(new CheckMemberCompanyExist(imdgProvider)); pipeline.add(new CheckMemberCompanyExist(imdgProvider));
pipeline.add(new SendMessageToCompanyServiceWithMemberCompanies(kafkaSender, imdgProvider)); pipeline.add(new CompaniesKafkaMessenger(kafkaSender, imdgProvider));
processor.setPipeline(pipeline); processor.setPipeline(pipeline);
return processor; return processor;
} }

View file

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

View file

@ -1,8 +1,6 @@
package ru.spcex.clearing.gatewayapi.config; package ru.spcex.clearing.gatewayapi.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
@ -12,16 +10,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableWebMvc @EnableWebMvc
public class WebConfig implements WebMvcConfigurer { 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 @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html") registry.addResourceHandler("swagger-ui.html")

View file

@ -10,7 +10,7 @@ import java.time.Instant;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
public class InstantDeserializer extends JsonDeserializer<Instant> { 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 @Override
public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 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; import java.time.format.DateTimeFormatter;
public class InstantSerializer extends JsonSerializer<Instant> { 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 @Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException { public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {

View file

@ -70,7 +70,7 @@ public class GatewayController {
) )
@ResponseBody @ResponseBody
public CommonResponse listingsFond(@RequestBody FondListingsRequest request) { 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); FondListingsRequestParam requestParam = new FondListingsRequestParam(request);
ProcessResult processResult = fondListingsRequestProcessor.process(requestParam); ProcessResult processResult = fondListingsRequestProcessor.process(requestParam);
if (processResult.getError() != null) throw new GatewayException(request, processResult.getError()); if (processResult.getError() != null) throw new GatewayException(request, processResult.getError());
@ -91,7 +91,7 @@ public class GatewayController {
) )
@ResponseBody @ResponseBody
public CommonResponse listingsMM(@RequestBody MMListingsRequest request) { 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); MMListingsRequestParam requestParam = new MMListingsRequestParam(request);
ProcessResult processResult = mmListingsRequestProcessor.process(requestParam); ProcessResult processResult = mmListingsRequestProcessor.process(requestParam);
if (processResult.getError() != null) throw new GatewayException(request, processResult.getError()); if (processResult.getError() != null) throw new GatewayException(request, processResult.getError());
@ -112,7 +112,7 @@ public class GatewayController {
) )
@ResponseBody @ResponseBody
public CommonResponse companies(@RequestBody CompaniesRequest request) { public CommonResponse companies(@RequestBody CompaniesRequest request) {
request.validate(validTypes, Collections.emptyList()); // request.validate(validTypes, Collections.emptyList());
CompaniesRequestParam requestParam = new CompaniesRequestParam(request); CompaniesRequestParam requestParam = new CompaniesRequestParam(request);
ProcessResult processResult = companiesRequestProcessor.process(requestParam); ProcessResult processResult = companiesRequestProcessor.process(requestParam);
if (processResult.getError() != null) throw new GatewayException(request, processResult.getError()); 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.setNominalValue(security.getNominalValue());
fixedIncomeSecurityNewRequest.setNominalCurrency(security.getNominalCurrency()); fixedIncomeSecurityNewRequest.setNominalCurrency(security.getNominalCurrency());
fixedIncomeSecurityNewRequest.setMaturityDate(security.getMaturityDate()); fixedIncomeSecurityNewRequest.setMaturityDate(security.getMaturityDate());
fixedIncomeSecurityNewRequest.setCouponFrequency(security.getCouponFrequency()); fixedIncomeSecurityNewRequest.setCouponFrequency(security.getCouponFrequency().longValue());
fixedIncomeSecurityNewRequest.setIssuerId(companyId); fixedIncomeSecurityNewRequest.setIssuerId(companyId);
fixedIncomeSecurityNewRequest.setShortNameEng(security.getShortNameEng()); fixedIncomeSecurityNewRequest.setShortNameEng(security.getShortNameEng());
fixedIncomeSecurityNewRequest.setFullNameEng(security.getFullNameEng()); fixedIncomeSecurityNewRequest.setFullNameEng(security.getFullNameEng());
@ -112,7 +112,7 @@ public class SendMessageToSecurityServiceWithFondSecurities extends Stage<FondLi
fixedIncomeSecurityUpdateRequest.setNominalValue(security.getNominalValue()); fixedIncomeSecurityUpdateRequest.setNominalValue(security.getNominalValue());
fixedIncomeSecurityUpdateRequest.setNominalCurrency(security.getNominalCurrency()); fixedIncomeSecurityUpdateRequest.setNominalCurrency(security.getNominalCurrency());
fixedIncomeSecurityUpdateRequest.setMaturityDate(security.getMaturityDate()); fixedIncomeSecurityUpdateRequest.setMaturityDate(security.getMaturityDate());
fixedIncomeSecurityUpdateRequest.setCouponFrequency(security.getCouponFrequency()); fixedIncomeSecurityUpdateRequest.setCouponFrequency(security.getCouponFrequency().longValue());
fixedIncomeSecurityUpdateRequest.setIssuerId(companyId); fixedIncomeSecurityUpdateRequest.setIssuerId(companyId);
fixedIncomeSecurityUpdateRequest.setShortNameEng(security.getShortNameEng()); fixedIncomeSecurityUpdateRequest.setShortNameEng(security.getShortNameEng());
fixedIncomeSecurityUpdateRequest.setFullNameEng(security.getFullNameEng()); 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.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.gatewayapi.config.deserializers.InstantDeserializer; 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.errors.GatewayError;
import ru.spcex.clearing.gatewayapi.exception.GatewayException; import ru.spcex.clearing.gatewayapi.exception.GatewayException;
import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.Section;
@ -38,6 +40,7 @@ public class CommonRequest {
@JsonProperty("datetime") @JsonProperty("datetime")
@JsonDeserialize(using = InstantDeserializer.class) @JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
@ApiModelProperty( @ApiModelProperty(
value = "Передавать дату и время формирования JSON объекта в формате «ДД.ММ.ГГГГ ЧЧ:ММ:СС:ссс».", value = "Передавать дату и время формирования JSON объекта в формате «ДД.ММ.ГГГГ ЧЧ:ММ:СС:ссс».",
example = "01.01.2023 12:34:56:789" 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.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.gatewayapi.config.deserializers.InstantDeserializer; import ru.spcex.clearing.gatewayapi.config.deserializers.InstantDeserializer;
import ru.spcex.clearing.gatewayapi.config.serializers.InstantSerializer;
import java.time.Instant; import java.time.Instant;
import java.util.UUID; import java.util.UUID;
@ -32,6 +34,7 @@ public class InboundRequest {
@JsonProperty("datetime") @JsonProperty("datetime")
@JsonDeserialize(using = InstantDeserializer.class) @JsonDeserialize(using = InstantDeserializer.class)
@JsonSerialize(using = InstantSerializer.class)
@ApiModelProperty( @ApiModelProperty(
value = "Передавать дату и время формирования JSON объекта в формате «ДД.ММ.ГГГГ ЧЧ:ММ:СС:ссс».", value = "Передавать дату и время формирования JSON объекта в формате «ДД.ММ.ГГГГ ЧЧ:ММ:СС:ссс».",
example = "01.01.2023 12:34:56:789" example = "01.01.2023 12:34:56:789"
@ -42,7 +45,14 @@ public class InboundRequest {
@ApiModelProperty( @ApiModelProperty(
value = "Секция (FOND или MKR)", example = "FOND" 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() { public UUID getId() {

View file

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

View file

@ -22,6 +22,7 @@ import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.enumeration.Task;
import java.time.Instant; import java.time.Instant;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -66,6 +67,7 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
String url = formingInboundUrl(inboundServerSettings.getPathLOCM()); String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpHeaders httpHeaders = new HttpHeaders(); HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
InboundRequest inboundRequest = new InboundRequest(); InboundRequest inboundRequest = new InboundRequest();
inboundRequest.setId(UUID.randomUUID()); inboundRequest.setId(UUID.randomUUID());
inboundRequest.setType("MEMBER_ON_DEMAND"); inboundRequest.setType("MEMBER_ON_DEMAND");
@ -89,11 +91,10 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
String url = formingInboundUrl(inboundServerSettings.getPathLOCM()); String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpHeaders httpHeaders = new HttpHeaders(); HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON); httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
InboundRequest inboundRequest = new InboundRequest(); InboundRequest inboundRequest = new InboundRequest();
inboundRequest.setId(UUID.randomUUID()); inboundRequest.setId(UUID.randomUUID());
inboundRequest.setType("ON_DEMAND"); inboundRequest.setType("ON_DEMAND");
// todo здесь возникла проблема: место обработки LOCM одно, но в этом месте могут быть сформированы запросы с разными
// section, нужно уточнить как определять какой именно section отправлять в запросе
inboundRequest.setSection(Section.FOND.getKey()); inboundRequest.setSection(Section.FOND.getKey());
inboundRequest.setDatetime(Instant.now()); inboundRequest.setDatetime(Instant.now());
HttpEntity<InboundRequest> request = new HttpEntity<>(inboundRequest, httpHeaders); 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.linger-ms=1
gateway-api.kafka-consumer.buffer-memory=33554432 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.host=localhost
gateway-api.inbound-server.port=9999 gateway-api.inbound-server.port=8080
gateway-api.inbound-server.pathLOCM=/inbound_request gateway-api.inbound-server.pathLOCM=test_tomcat9/p1
gateway-api.inbound-server.pathLOSC=/inbound_request gateway-api.inbound-server.pathLOSC=test_tomcat9/p2

View file

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

View file

@ -101,6 +101,7 @@ public class EquitySecurityService extends QueueConsumer implements Initializing
equity.setInstrumentType(req.getInstrumentType()); equity.setInstrumentType(req.getInstrumentType());
equity.setSecurityId(equity.getId()); equity.setSecurityId(equity.getId());
equity.setCreated(Instant.now()); equity.setCreated(Instant.now());
equity.setUpdated(equity.getCreated());
try { try {
transaction.beginTransaction(); transaction.beginTransaction();
Imdg<EquitySecurity> equityImdg = transaction.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class); 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.setInstrumentType(req.getInstrumentType());
fixedIncome.setSecurityId(fixedIncome.getId()); fixedIncome.setSecurityId(fixedIncome.getId());
fixedIncome.setCreated(Instant.now()); fixedIncome.setCreated(Instant.now());
fixedIncome.setUpdated(fixedIncome.getCreated());
try { try {
transaction.beginTransaction(); transaction.beginTransaction();
Imdg<FixedIncomeSecurity> fixedIncomeImdg = transaction.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class); 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.setIssuerId(req.getIssuerId());
mms.setSecurityId(mms.getId()); mms.setSecurityId(mms.getId());
mms.setDescription(req.getDescription()); mms.setDescription(req.getDescription());
mms.setConvention(req.getConvention());
mms.setCreated(Instant.now()); mms.setCreated(Instant.now());
mms.setUpdated(mms.getCreated());
if (req.getWorkflowStatus() == null) { if (req.getWorkflowStatus() == null) {
mms.setWorkflowStatus(WorkflowStatus.Active.getKey()); mms.setWorkflowStatus(WorkflowStatus.Active.getKey());
} else { } else {
@ -206,6 +208,7 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial
mms.setIssuerId(req.getIssuerId()); mms.setIssuerId(req.getIssuerId());
mms.setSecurityId(mms.getId()); mms.setSecurityId(mms.getId());
mms.setDescription(req.getDescription()); mms.setDescription(req.getDescription());
mms.setConvention(req.getConvention());
if (req.getWorkflowStatus() != null) { if (req.getWorkflowStatus() != null) {
mms.setWorkflowStatus(req.getWorkflowStatus()); mms.setWorkflowStatus(req.getWorkflowStatus());
} }

View file

@ -2,14 +2,15 @@ package ru.spcex.clearing.securities.validation;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.misc.Listing; 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.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.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; 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.platform.messaging.domain.cud.securitites.*;
import ru.spcex.clearing.util.security.SecuritySelector; import ru.spcex.clearing.util.security.SecuritySelector;
import ru.spcex.clearing.securities.errors.SecuritiesError; 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.IdPresentRule;
import ru.spcex.clearing.validation.common.rules.SpecialIdPresentRule; import ru.spcex.clearing.validation.common.rules.SpecialIdPresentRule;
import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.SpcexObjectBase;
@ -31,6 +32,7 @@ import java.util.function.Function;
@Component @Component
public class ListingValidationProvider { public class ListingValidationProvider {
final Imdg<SpcexObjectBase> workflowStatusDictionaryImdg; final Imdg<SpcexObjectBase> workflowStatusDictionaryImdg;
final Imdg<SpcexObjectBase> currencyCodeDictionaryImdg;
final Imdg<Listing> listingImdg; final Imdg<Listing> listingImdg;
final Imdg<ru.clearing.classes.statics.data.misc.Market> marketImdg; final Imdg<ru.clearing.classes.statics.data.misc.Market> marketImdg;
final SecuritySelector securitySelector; final SecuritySelector securitySelector;
@ -39,6 +41,7 @@ public class ListingValidationProvider {
public ListingValidationProvider(ImdgProvider imdgProvider, SecuritySelector securitySelector) { public ListingValidationProvider(ImdgProvider imdgProvider, SecuritySelector securitySelector) {
this.securitySelector = securitySelector; this.securitySelector = securitySelector;
this.workflowStatusDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, SpcexObjectBase.class); 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.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, ru.clearing.classes.statics.data.misc.Market.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<>(); ImdgValidationContext<ListingNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(listingRequest); context.setValidatedObject(listingRequest);
context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg); context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, currencyCodeDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_Market, marketImdg); context.addImdg(IMDGDistributedNames.Map_Market, marketImdg);
context.addImdg(IMDGDistributedNames.Map_Listing, listingImdg); context.addImdg(IMDGDistributedNames.Map_Listing, listingImdg);
return new ValidatorImpl<ImdgValidationContext<ListingNewRequest>>(context, return new ValidatorImpl<ImdgValidationContext<ListingNewRequest>>(context,
@ -62,6 +66,16 @@ public class ListingValidationProvider {
SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.MarketNotFound, SecuritiesError.RequiredFieldIsEmpty, SecuritiesError.MarketNotFound,
true 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) new NotSameActiveListing<>(ListingNewRequest::getSecurityId, ListingNewRequest::getMarket)
); );
}; };
@ -72,12 +86,23 @@ public class ListingValidationProvider {
ImdgValidationContext<ListingUpdateRequest> context = new ImdgValidationContext<>(); ImdgValidationContext<ListingUpdateRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(mmsRequest); context.setValidatedObject(mmsRequest);
context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg); context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, currencyCodeDictionaryImdg);
context.addImdg(IMDGDistributedNames.Map_Listing, listingImdg); context.addImdg(IMDGDistributedNames.Map_Listing, listingImdg);
return new ValidatorImpl<>(context, return new ValidatorImpl<>(context,
new PresentById(IMDGDistributedNames.Map_Listing, SecuritiesError.ListingNotFound, true), new PresentById(IMDGDistributedNames.Map_Listing, SecuritiesError.ListingNotFound, true),
new SecurityIdPresentRule<ListingUpdateRequest>("securityId", ListingUpdateRequest::getSecurityId, new SecurityIdPresentRule<ListingUpdateRequest>("securityId", ListingUpdateRequest::getSecurityId,
(Security security) -> (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()); Security security = securitySelector.selectSecurityById(listing.getSecurityId());
if (security != null) { if (security != null) {
if (InstrumentType.RATE.equalsByKey(security.getInstrumentType())) if (InstrumentType.RATE.equalsByKey(security.getInstrumentType()))
return SecuritiesError.ListingOnMMSCreatedBySystem; return SecuritiesError.ListingOnMMSDeletedBySystem;
} }
return null; 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.ErrorResolverConfig;
import ru.spcex.clearing.securities.config.ValidationConfig; import ru.spcex.clearing.securities.config.ValidationConfig;
import ru.spcex.clearing.securities.service.cud.*; 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.securities.validation.ValidationProvider;
import ru.spcex.clearing.test.MatcherFactory; import ru.spcex.clearing.test.MatcherFactory;
import ru.spcex.clearing.test.config.ImdgTestConfig; import ru.spcex.clearing.test.config.ImdgTestConfig;
import ru.spcex.clearing.test.config.KafkaTestConfig; 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.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
@ -37,7 +39,8 @@ import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProv
EquitySecurityService.class, EquitySecurityService.class,
FixedIncomeSecurityService.class, FixedIncomeSecurityService.class,
MoneyMarketSecurityService.class, MoneyMarketSecurityService.class,
ListingService.class, ListingService.class, ListingValidationProvider.class,
SecuritySelector.class,
ImdgTestConfig.class, ImdgTestConfig.class,
KafkaTestConfig.class, KafkaTestConfig.class,
ValidationProvider.class, ValidationProvider.class,

View file

@ -24,6 +24,7 @@ class MoneyMarketSecurityFactory {
private String fullName = "estat"; private String fullName = "estat";
private String shortName = "esasdftat"; private String shortName = "esasdftat";
private String securitySymbol = "sdfafd"; private String securitySymbol = "sdfafd";
private String convention = "convention";
private String istin = "istin"; private String istin = "istin";
private String termType = AbstractServiceTest.termType; private String termType = AbstractServiceTest.termType;
@ -106,6 +107,7 @@ class MoneyMarketSecurityFactory {
moneyMarketSecurity.setDescription(description); moneyMarketSecurity.setDescription(description);
moneyMarketSecurity.setLotSize(lotSize); moneyMarketSecurity.setLotSize(lotSize);
moneyMarketSecurity.setSecuritySymbol(securitySymbol); moneyMarketSecurity.setSecuritySymbol(securitySymbol);
moneyMarketSecurity.setConvention(convention);
moneyMarketSecurity.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey()); moneyMarketSecurity.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey());
return moneyMarketSecurity; return moneyMarketSecurity;
@ -131,6 +133,7 @@ class MoneyMarketSecurityFactory {
moneyMarketSecurityUpdateRequest.setIssuerId(issuerId); moneyMarketSecurityUpdateRequest.setIssuerId(issuerId);
moneyMarketSecurityUpdateRequest.setDescription(description); moneyMarketSecurityUpdateRequest.setDescription(description);
moneyMarketSecurityUpdateRequest.setSecuritySymbol(securitySymbol); moneyMarketSecurityUpdateRequest.setSecuritySymbol(securitySymbol);
moneyMarketSecurityUpdateRequest.setConvention(convention);
moneyMarketSecurityUpdateRequest.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey()); moneyMarketSecurityUpdateRequest.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey());
return moneyMarketSecurityUpdateRequest; return moneyMarketSecurityUpdateRequest;
@ -160,6 +163,7 @@ class MoneyMarketSecurityFactory {
keyRequest.setIsin(istin); keyRequest.setIsin(istin);
keyRequest.setDescription(description); keyRequest.setDescription(description);
keyRequest.setSecuritySymbol(securitySymbol); keyRequest.setSecuritySymbol(securitySymbol);
keyRequest.setConvention(convention);
keyRequest.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey()); 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.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope; 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.KafkaConsumerFactory;
import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory; 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.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 @Configuration
public class KafkaConfig { public class KafkaConfig {
@ -26,4 +36,30 @@ public class KafkaConfig {
return KafkaProducerFactory.producer(settings.getKafkaProducer()); 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; 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_UPDATE = "planner-update";
String DESTINATION_PLANNER_DELETE = "planner-delete"; String DESTINATION_PLANNER_DELETE = "planner-delete";
String DESTINATION_COMPANY_MULTIREQUEST = "company-multirequest-new";
String DESTINATION_COMPANY_NEW = "company-new"; String DESTINATION_COMPANY_NEW = "company-new";
String DESTINATION_COMPANY_DELETE = "company-delete"; String DESTINATION_COMPANY_DELETE = "company-delete";
String DESTINATION_COMPANY_UPDATE = "company-update"; 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_UPDATE = "trading-clearing-registry-update";
String DESTINATION_TRADING_CLEARING_REGISTRY_BLOCK = "trading-clearing-registry-block"; 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_SDF08_NEW = "s-df-08-new";
String DESTINATION_SDF02_NEW = "s-df-02-new"; String DESTINATION_SDF02_NEW = "s-df-02-new";
@ -139,7 +145,7 @@ public interface Consts {
String BALANCE_ACCOUNT_UPDATE = "balance-account-update"; String BALANCE_ACCOUNT_UPDATE = "balance-account-update";
String CONTINUE_CLEARING = "continue-clearing"; String CONTINUE_CLEARING = "continue-clearing";
String LAUNCHER_NEW = "launcher-new"; String LAUNCHER_NEW = "launcher-new";
String NOTIFICATION_NEW = "notification-new";
String REQUEST_INFO_UPDATE = "request-info-update"; 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;
}
}