Compare commits

..

124 commits

Author SHA1 Message Date
ialbert
7c2ce48bd1 DM_X search: statuses PROC/MNG 2024-01-29 13:54:12 +03:00
ialbert
0fd9208e41 clearing-service changeStatusExtract => gateway without timeout
optional max-poll-interval-ms setting
2024-01-17 13:22:13 +03:00
ialbert
ab80d194a5 SDF57 cs_blocked to gateway DM_V 2024-01-12 13:12:53 +03:00
ialbert
6590d63026 cs_blocked при создании PaymentInstruction: для категории I ИЛИ V 2024-01-12 11:20:41 +03:00
ialbert
b96fcaae7d http://jira.mfd.msk:8088/browse/CLS-311 2024-01-11 15:33:27 +03:00
ialbert
517dc8669a http://jira.mfd.msk:8088/browse/CLS-311 2024-01-11 14:29:59 +03:00
ialbert
8df2442aa6 SDF06 DM*T.status condition OK/MNG => PROC/MNG 2024-01-10 17:24:38 +03:00
ialbert
c959023094 A**T openBalance null => 0 2023-12-20 11:58:23 +03:00
ialbert
54c3d7c235 >> SDF57 D**I -> OK && session present => AxxT.planned += DxxI.balance 2023-12-19 14:47:04 +03:00
AKurakin
892bdcb769 http://jira.mfd.msk:8088/browse/CLS-600 meta 2023-12-18 14:02:40 +03:00
ialbert
66ead14acb lim-exporter money DM*T settlement_date condition removed [2] 2023-12-18 12:34:18 +03:00
ialbert
072a5dbcd9 lim-exporter money DM*T settlement_date condition removed 2023-12-18 11:26:07 +03:00
ialbert
730ae2aba4 imdg application.properties 2023-12-15 17:29:54 +03:00
ialbert
5ad1b0d569 imdg settings: imdg.hazelcast.instance-name/imdg.hazelcast.db-sync-seconds/imdg.database.min-pool-size/imdg.database.max-pool-size 2023-12-15 17:12:59 +03:00
AKurakin
2a400e1a8a Merge branch 'tmpCLS-585' into dev 2023-12-15 16:29:44 +03:00
AKurakin
c8336ce8a4 http://jira.mfd.msk:8088/browse/CLS-585 уточнение получено 2023-12-15 16:29:11 +03:00
ialbert
08867e3cb9 http://jira.mfd.msk:8088/browse/CLS-603 2023-12-15 13:12:35 +03:00
akulikov
999b0999de http://jira.mfd.msk:8088/browse/CLS-602 (fix date format) 2023-12-15 10:06:00 +03:00
akulikov
038f676eef http://jira.mfd.msk:8088/browse/CLS-602 2023-12-14 12:17:12 +03:00
ialbert
c5a62a0bd4 removed mm2-prefixless-policy.jar 2023-12-13 15:25:56 +03:00
ialbert
ab34364a22 lim-exporter OPEN-BALANCE fix 2023-12-12 13:38:27 +03:00
akulikov
91b6f9efbc http://jira.mfd.msk:8088/browse/CLS-601 fixes 2023-12-12 10:45:33 +03:00
akulikov
9a279eead8 http://jira.mfd.msk:8088/browse/CLS-601 remove DM_X registry sessionId condition 2023-12-08 15:29:11 +03:00
akulikov
c5f79afb50 http://jira.mfd.msk:8088/browse/CLS-601 fix report test 2023-12-08 14:00:56 +03:00
akulikov
de9619376b registry-service fix, ImdgPredicateBuilder fix, RegistryCodeSqlBuilder fix dot 2023-12-08 13:53:12 +03:00
akulikov
0dd5cec12e http://jira.mfd.msk:8088/browse/CLS-601 2023-12-08 13:31:30 +03:00
etreschenkov
cd488b19d8 revert dot 2023-12-08 13:11:23 +03:00
etreschenkov
1ec2b25714 http://jira.mfd.msk:8088/browse/CLS-523 2023-12-08 13:07:24 +03:00
akulikov
8fe43dee98 http://jira.mfd.msk:8088/browse/CLS-599 2023-12-07 19:13:06 +03:00
akulikov
49b3191a63 http://jira.mfd.msk:8088/browse/CLS-599 2023-12-07 18:52:46 +03:00
akulikov
2a81e33b78 http://jira.mfd.msk:8088/browse/CLS-599 2023-12-07 17:27:56 +03:00
akulikov
313ff28cbd http://jira.mfd.msk:8088/browse/CLS-599 2023-12-07 13:19:11 +03:00
AKurakin
2656d6a78c db-scripts DATA_INITIAL.sql поправлен TRADING_CODE для СПВБ=001, транзитный счёт для бумаг SPCEX 2023-12-07 12:19:04 +03:00
ialbert
dc21de68f2 http://jira.mfd.msk:8088/browse/CLS-328 fix 2023-12-01 19:31:52 +03:00
ialbert
2c2cc64595 http://jira.mfd.msk:8088/browse/CLS-328 2023-12-01 19:27:45 +03:00
ialbert
17910bd224 http://jira.mfd.msk:8088/browse/CLS-328 2023-12-01 19:04:18 +03:00
ialbert
02e2b3a3f2 indexes for Registry map 2023-11-30 20:13:32 +03:00
ialbert
fe48b00464 ExecutionFond from s_trade log, clearing-service log pattern 2023-11-30 13:39:03 +03:00
ialbert
3f5fa0433f ExecutionFond#Quantity 2023-11-29 19:59:57 +03:00
ialbert
4e78439e54 ExecutionFond settlementAmount valuation for EQTY 2023-11-29 15:42:27 +03:00
ialbert
673bb48938 запросе сделок из тс, статус запроса (не отвисает кнопка на вебе) 2023-11-29 11:51:29 +03:00
ialbert
0dc90cf828 ExecutionFondComponent valuation flag added to logs 2023-11-28 12:43:28 +03:00
ialbert
afbe819255 changeStatusExtract gateway request 2023-11-28 11:56:51 +03:00
ialbert
9b8e68a94c Merge branch 'dev' into execution_and_deals_status
# Conflicts:
#	clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java
#	clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java
2023-11-27 15:39:16 +03:00
etreshenkov
d5e764131d fix PlannerAllTodayMaker 2023-11-27 12:33:25 +03:00
AKurakin
793171b3da security-util UserRoleVerification поправил логи 2023-11-24 19:04:55 +03:00
AKurakin
4bcc725c26 meta 3.9.0.70 текст для couponPeriod 2023-11-24 17:57:35 +03:00
akulikov
2da0ac042c http://jira.mfd.msk:8088/browse/CLS-598 2023-11-24 17:12:48 +03:00
akulikov
99f4dbe292 http://jira.mfd.msk:8088/browse/CLS-597 fix 2023-11-23 18:58:01 +03:00
akulikov
4bd6dab4b1 http://jira.mfd.msk:8088/browse/CLS-597 fix 2023-11-23 18:11:13 +03:00
akulikov
e028aee516 http://jira.mfd.msk:8088/browse/CLS-597 2023-11-23 14:21:35 +03:00
ialbert
7641b2691c CS_BLKD 2023-11-22 19:07:06 +03:00
akulikov
970da463fc http://jira.mfd.msk:8088/browse/CLS-596 fixes 2023-11-22 15:28:18 +03:00
akulikov
5639f9ff8b http://jira.mfd.msk:8088/browse/CLS-596 fix after review 2023-11-22 15:19:41 +03:00
akulikov
8e948bc27a http://jira.mfd.msk:8088/browse/CLS-596 fix 2023-11-22 14:48:18 +03:00
akulikov
0b2bef797e http://jira.mfd.msk:8088/browse/CLS-596 2023-11-22 14:22:35 +03:00
ialbert
e04460b194 http://jira.mfd.msk:8088/browse/CLS-536 2023-11-21 17:21:16 +03:00
ialbert
0c00c7fdb3 PaymentInstruction grouping for securities 2023-11-21 17:09:08 +03:00
ialbert
494bafbe18 http://jira.mfd.msk:8088/browse/CLS-536 2023-11-21 16:25:31 +03:00
ialbert
4b1b6113f4 http://jira.mfd.msk:8088/browse/CLS-536 2023-11-21 16:25:10 +03:00
ialbert
53198ca9f5 Merge branch 'dev' into execution_and_deals_status 2023-11-20 14:08:05 +03:00
ialbert
3e6b8911c9 http://jira.mfd.msk:8088/browse/CLS-536 2023-11-20 14:07:45 +03:00
ialbert
1d4d831ea7 http://jira.mfd.msk:8088/browse/CLS-590 2023-11-20 13:07:52 +03:00
akulikov
085b0cf4ce http://jira.mfd.msk:8088/browse/CLS-497 KSRepTradesReportBuilder 2023-11-20 12:02:16 +03:00
akulikov
632bdf9e09 http://jira.mfd.msk:8088/browse/CLS-497 KSRepCashNettoReportBuilder 2023-11-20 11:17:53 +03:00
ialbert
866c063b0d http://jira.mfd.msk:8088/browse/CLS-590 2023-11-17 13:29:26 +03:00
ialbert
911c90bc45 Merge branch 'dev' into execution_and_deals_status 2023-11-16 18:08:10 +03:00
ialbert
8ae41b9d16 DS*I fix полей 2023-11-16 18:07:36 +03:00
ialbert
37a741e866 D**I fix полей open_balance/close_balance/plan_balance/created_at(new) 2023-11-16 18:07:36 +03:00
AKurakin
4a0df9bb48 dbf-importer swt-importer Забирать и обрабатывать файлы в порядке времени изменения на sftp (2)) 2023-11-16 16:29:53 +03:00
akulikov
939ea451a1 http://jira.mfd.msk:8088/browse/CLS-497 KSRepTrades 2023-11-16 16:16:35 +03:00
ialbert
ee0f95fcde http://jira.mfd.msk:8088/browse/CLS-591 2023-11-16 16:12:22 +03:00
akulikov
4581592380 http://jira.mfd.msk:8088/browse/CLS-497 KSRepCashNettoReport 2023-11-16 13:22:07 +03:00
akulikov
4e431ee798 http://jira.mfd.msk:8088/browse/CLS-497 KSRepTrades 2023-11-16 13:08:04 +03:00
AKurakin
10d8803651 dbf-importer swt-importer Забирать и обрабатывать файлы в порядке времени изменения на sftp 2023-11-16 12:43:44 +03:00
akulikov
fac5dca462 replace SUM and AGREEMENT_SETTLEMENT_DATE (KSCommissionTradesReport) 2023-11-16 11:58:30 +03:00
ialbert
06b38cc61f Merge branch 'dev' into execution_and_deals_status 2023-11-16 11:34:58 +03:00
AKurakin
4dfb642e1b platform-storage-api поправил RegistryCodeSqlBuilder для случая с множеством or параметров 2023-11-15 18:15:55 +03:00
ialbert
740c138ead http://jira.mfd.msk:8088/browse/CLS-536 DM*V создается для settlementDate == valueDate 2023-11-15 17:58:17 +03:00
akulikov
0d134db9c6 http://jira.mfd.msk:8088/browse/CLS-497 2023-11-15 17:26:30 +03:00
ialbert
deaa77a05c http://jira.mfd.msk:8088/browse/CLS-592 2023-11-15 16:47:16 +03:00
ialbert
c86f1e907a http://jira.mfd.msk:8088/browse/CLS-590
http://jira.mfd.msk:8088/browse/CLS-591
2023-11-15 16:46:36 +03:00
AKurakin
04bc8e9edf db-scripts http://jira.mfd.msk:8088/browse/CLS-594 разделение data.xml 2023-11-15 16:31:10 +03:00
ialbert
e8cba0467a http://jira.mfd.msk:8088/browse/CLS-592 2023-11-15 15:56:43 +03:00
AKurakin
9f988d34c0 swt-importer тест на RDC_KS_DF-20 2023-11-15 15:49:29 +03:00
AKurakin
3fbb5931df http://jira.mfd.msk:8088/browse/CLS-593 SDF02 в порядке SDF01 2023-11-15 11:53:09 +03:00
akulikov
15242a0a75 http://jira.mfd.msk:8088/browse/CLS-497 2023-11-14 14:40:17 +03:00
AKurakin
5cd8608584 meta fix 2023-11-13 16:58:50 +03:00
AKurakin
943ec5f762 http://jira.mfd.msk:8088/browse/CLS-585 todo уточнить задание 2023-11-13 16:51:36 +03:00
ialbert
20f6c6a939 mm2-prefixless-policy.jar настройка для репликации кафки 2023-11-13 16:29:00 +03:00
AKurakin
9e9a801bde http://jira.mfd.msk:8088/browse/CLS-497 2023-11-13 15:50:38 +03:00
akulikov
a8386a9ed9 http://jira.mfd.msk:8088/browse/CLS-497 2023-11-10 19:13:26 +03:00
akulikov
fd25105fe8 http://jira.mfd.msk:8088/browse/CLS-497 2023-11-09 17:12:59 +03:00
AKurakin
858e02084b http://jira.mfd.msk:8088/browse/CLS-586 meta / data 3.9.0.68 2023-11-09 16:27:53 +03:00
ialbert
eb3bed4a1d http://jira.mfd.msk:8088/browse/CLS-479 2023-11-09 15:03:25 +03:00
ialbert
8079ec1fb3 http://jira.mfd.msk:8088/browse/CLS-388 2023-11-09 15:03:25 +03:00
ialbert
cc2f20de3c http://jira.mfd.msk:8088/browse/CLS-584 2023-11-09 15:03:25 +03:00
ialbert
145d3f4c74 kill session command 2023-11-09 15:03:25 +03:00
akulikov
e6ede79021 http://jira.mfd.msk:8088/browse/CLS-497 2023-11-09 14:59:21 +03:00
AKurakin
a2ebfd945b backend-api update meta 3.9.0.67 2023-11-09 11:30:53 +03:00
akulikov
c7ad0a181c http://jira.mfd.msk:8088/browse/CLS-497 2023-11-08 15:47:30 +03:00
etreschenkov
12ff85188f http://jira.mfd.msk:8088/browse/CLS-582 2023-11-04 16:22:33 +03:00
etreschenkov
9c827763de http://jira.mfd.msk:8088/browse/CLS-523 2023-11-06 17:13:38 +03:00
etreschenkov
59d0b000d1 http://jira.mfd.msk:8088/browse/CLS-481 2023-11-06 16:26:27 +03:00
etreshenkov
60e7c6ac39 http://jira.mfd.msk:8088/browse/CLS-522 2023-11-03 13:16:28 +03:00
AKurakin
9b26fb2290 backend-api update meta 3.9.0.65 (fix shortname) 2023-11-02 12:53:44 +03:00
AKurakin
81c4c9fa99 db-scripts обавлен GRANT ALL PRIVILEGES ON TABLE * TO clearing; теперь так в апдейтах также надо писать 2023-11-02 12:03:41 +03:00
AKurakin
9ac71532f7 backend-api update meta 3.9.0.65 2023-11-02 11:44:45 +03:00
AKurakin
79eaffbda6 db-scripts http://jira.mfd.msk:8088/browse/CLS-581 2023-11-01 17:33:51 +03:00
akulikov
8deebfafbb http://jira.mfd.msk:8088/browse/CLS-497 2023-11-01 16:02:44 +03:00
AKurakin
31de64e5bb account-service http://jira.mfd.msk:8088/browse/CLS-577 улучшил текст валидации 2023-11-01 13:57:02 +03:00
AKurakin
afeede8baa backend-api http://jira.mfd.msk:8088/browse/CLS-576 meta 2023-11-01 12:39:48 +03:00
AKurakin
286b3ace2c account-service http://jira.mfd.msk:8088/browse/CLS-577 DATA.sql добавил ошибку 5025 2023-11-01 12:30:50 +03:00
akulikov
2f54dcaccf http://jira.mfd.msk:8088/browse/CLS-497 2023-11-01 12:08:42 +03:00
AKurakin
bcb4307acd account-service http://jira.mfd.msk:8088/browse/CLS-576 улучшил валидацию 2023-11-01 10:31:48 +03:00
AKurakin
0bc0f9461f backend-api http://jira.mfd.msk:8088/browse/CLS-576 добавил тест 2023-10-31 19:01:49 +03:00
AKurakin
681e612bbd backend-api http://jira.mfd.msk:8088/browse/CLS-580 добавил log-warning при отсутствии настроек 2023-10-31 19:01:49 +03:00
akulikov
b5b204bf5f http://jira.mfd.msk:8088/browse/CLS-497 2023-10-31 18:56:12 +03:00
AKurakin
a2dcd21867 account-service http://jira.mfd.msk:8088/browse/CLS-577, imdg http://jira.mfd.msk:8088/browse/CLS-575 добавил AccountSymbolsUpdate в UpdateMapService.java 2023-10-31 17:30:15 +03:00
akulikov
9eff119ff2 http://jira.mfd.msk:8088/browse/CLS-497 part 2 2023-10-31 16:45:14 +03:00
etreshenkov
2a61062eb9 http://jira.mfd.msk:8088/browse/CLS-523 2023-10-31 15:39:41 +03:00
AKurakin
fba4a07513 backend-api http://jira.mfd.msk:8088/browse/CLS-577 AccountSymbols 2023-10-31 14:43:37 +03:00
AKurakin
7b24b1d6ab IMDG DDL http://jira.mfd.msk:8088/browse/CLS-575 DDL 3.9 2023-10-31 14:39:25 +03:00
akulikov
e7c48f17e6 http://jira.mfd.msk:8088/browse/CLS-497 part 1 2023-10-31 10:55:48 +03:00
194 changed files with 5914 additions and 1999 deletions

View file

@ -0,0 +1,101 @@
package ru.spcex.clearing.account.config.validation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.account.AccountSymbols;
import ru.spcex.clearing.account.errors.AccountError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountSymbolsNewRequest;
import ru.spcex.clearing.validation.common.rules.FieldNotBlankRequiredRule;
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.AccountType;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
import ru.spcex.platform.utils.validation.IValidator;
import ru.spcex.platform.utils.validation.ValidatorImpl;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
@Configuration
public class AccountSymbolsValidationConfig {
@Bean("accountSymbolsDepoNewRequest")
public Function<AccountSymbolsNewRequest, IValidator> accountSymbolsDepoNewRequestValidator(
Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation
) {
return accountSymbolsNewRequest -> {
ImdgValidationContext<AccountSymbolsNewRequest> context = new ImdgValidationContext<>();
context.setValidatedObject(accountSymbolsNewRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
addImdg.accept(IMDGDistributedNames.Map_Account);
addImdg.accept(IMDGDistributedNames.Map_AccountSymbols);
return new ValidatorImpl<>(context,
IdPresentRule.instance("accountId",
AccountSymbolsNewRequest::getAccountId,
IMDGDistributedNames.Map_Account,
Account.class,
AccountError.RequiredFieldEmpty,
AccountError.AccountNotFound,
true,
(Account account) -> {
if (AccountType.Depo.equalsByKey(account.getAccountType())) {
return null;
} else {
return AccountError.AccountDepoTypeRequired;
}
}
),
FieldNotBlankRequiredRule.instance("accountSymbolValue",
AccountSymbolsNewRequest::getAccountSymbolValue,
AccountError.RequiredFieldEmpty, true),
new DuplicateAccountSymbolsRule()
);
};
}
static class DuplicateAccountSymbolsRule implements IValidationRule<ImdgValidationContext<AccountSymbolsNewRequest>> {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<AccountSymbolsNewRequest> context) {
AccountSymbolsNewRequest validatedObject = context.getValidatedObject();
Imdg<AccountSymbols> accountSymbolsImdg = context.obtainMap(IMDGDistributedNames.Map_AccountSymbols, AccountSymbols.class);
ImdgPredicateBuilder pb = accountSymbolsImdg.predicateBuilder();
ImdgPredicate query = pb.or(
pb.equals("accountId", validatedObject.getAccountId()),
pb.equals("accountSymbolValue", validatedObject.getAccountSymbolValue())
);
Collection<AccountSymbols> existAccSymbols = accountSymbolsImdg.getCollectionObjectsByPredicate(query);
if (existAccSymbols.isEmpty()) {
return empty();
} else {
AccountSymbols existAS = existAccSymbols.iterator().next();
String duplicateMsg = "";
if (validatedObject.getAccountId() != null && validatedObject.getAccountId().equals(existAS.getAccountId())) {
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
Account linkedAccount = accountImdg.getSingleObjectByID(existAS.getAccountId());
if (linkedAccount != null) {
duplicateMsg = linkedAccount.getAccount();
} else {
duplicateMsg = "" + existAS.getAccountId();
}
}
if (validatedObject.getAccountSymbolValue() != null &&
validatedObject.getAccountSymbolValue().equals(existAS.getAccountSymbolValue())) {
if (!duplicateMsg.isEmpty())
duplicateMsg += ", ";
duplicateMsg += existAS.getAccountSymbolValue();
}
return of(AccountError.AccountAlreadyExist, duplicateMsg);
}
}
}
}

View file

@ -41,6 +41,7 @@ public class ValidationConfig {
addImdg.accept(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); addImdg.accept(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class);
addImdg.accept(IMDGDistributedNames.Map_ServiceStatusDictionary, ServiceStatusDictionary.class); addImdg.accept(IMDGDistributedNames.Map_ServiceStatusDictionary, ServiceStatusDictionary.class);
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
addImdg.accept(IMDGDistributedNames.Map_AccountSymbols, AccountSymbols.class);
//for ClientCodeValidationConfig //for ClientCodeValidationConfig
addImdg.accept(IMDGDistributedNames.Map_ClientCode, ClientCode.class); addImdg.accept(IMDGDistributedNames.Map_ClientCode, ClientCode.class);

View file

@ -22,6 +22,7 @@ public enum AccountError implements IErrorEnumId {
ClearingCompanySymbolNotFound(5022L), // Для компании %s отсутствует клиринговый код». ClearingCompanySymbolNotFound(5022L), // Для компании %s отсутствует клиринговый код».
AccountForTradingClearingRegistryAlreadyUsed(5023L), AccountForTradingClearingRegistryAlreadyUsed(5023L),
AccountFieldNotSet(5024L), AccountFieldNotSet(5024L),
AccountDepoTypeRequired(5025L),
TradingClearingRegistryNotFound(3022L), TradingClearingRegistryNotFound(3022L),
; ;

View file

@ -0,0 +1,122 @@
package ru.spcex.clearing.account.service;
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.Qualifier;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.account.*;
import ru.spcex.clearing.account.errors.AccountError;
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.AccountSymbolsNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
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.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.validation.IValidator;
import java.util.function.Function;
@Service
public class AccountSymbolsService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final ValidationHelper validationHelper;
private final UserRoleVerification userRoleVerification;
private final ImdgProvider imdgProvider;
private final Imdg<AccountSymbols> accountSymbolsImdg;
private final RequestHelper requestHelper;
private final Function<AccountSymbolsNewRequest, IValidator> accountSymbolsNewRequestValidator;
private final IMessageResolver messageResolver;
private final Producer<String, Object> kafkaProducer;
private final KafkaSender kafkaSender;
public AccountSymbolsService(Consumer<String, Object> kafkaQueue,
Producer<String, Object> kafkaProducer,
KafkaSender kafkaSender,
ImdgProvider imdgProvider,
ValidationHelper validationHelper,
UserRoleVerification userRoleVerification,
IMessageResolver messageResolver,
RequestHelper requestHelper,
@Qualifier("accountSymbolsDepoNewRequest")
Function<AccountSymbolsNewRequest, IValidator> accountSymbolsNewRequestValidator
) {
super(kafkaQueue, kafkaProducer);
this.kafkaProducer = kafkaProducer;
this.kafkaSender = kafkaSender;
this.validationHelper = validationHelper;
this.userRoleVerification = userRoleVerification;
this.requestHelper = requestHelper;
this.imdgProvider = imdgProvider;
this.accountSymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountSymbols, AccountSymbols.class);
this.accountSymbolsNewRequestValidator = accountSymbolsNewRequestValidator;
this.messageResolver = messageResolver;
}
@Override
public void afterPropertiesSet() throws Exception {
imdgProvider.waitAvailable();
callback(AccountSymbolsNewRequest.class)
.setFunction(this::accountSymbolsNew)
.forDestination(Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_NEW, callbacks::put);
callback(CommonIdRequest.class)
.setFunction(this::accountSymbolsDelete)
.forDestination(Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_DELETE, callbacks::put);
init();
}
protected RequestInfoUpdate accountSymbolsNew(BaseRequest<AccountSymbolsNewRequest> userRequest) {
log.debug("AccountSymbolsNewRequest received, id={}", userRequest.getId());
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, accountSymbolsNewRequestValidator);
if (requestInfoUpdate != null) return requestInfoUpdate;
AccountSymbolsNewRequest req = userRequest.getRequestPayload();
Long id = accountSymbolsImdg.nextIDSequenceFor();
AccountSymbols accountSymbols = new AccountSymbols();
accountSymbols.setId(id);
accountSymbols.setAccountId(req.getAccountId());
accountSymbols.setAccountSymbolValue(req.getAccountSymbolValue());
accountSymbolsImdg.insert(accountSymbols);
log.debug("successfully processed, id {}. New accountSymbols.id={} was created", id, accountSymbols.getId());
return null;
}
protected RequestInfoUpdate accountSymbolsDelete(BaseRequest<CommonIdRequest> userRequest) {
log.debug("AccountSymbolsDeleteRequest(CommonIdRequest) received, id={}", userRequest.getId());
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
CommonIdRequest req = userRequest.getRequestPayload();
AccountSymbols accountSymbols = accountSymbolsImdg.getSingleObjectByID(req.getId());
if (accountSymbols == null) {
return requestHelper.makeErrorResponse(userRequest, AccountError.AccountNotFound, req.getId());
}
accountSymbolsImdg.delete(accountSymbols);
log.debug("successfully processed, id {}. New accountSymbols.id={} was deleted", userRequest.getId(), accountSymbols.getId());
return null;
}
}

View file

@ -70,6 +70,7 @@ public class ClearingAccountService extends QueueConsumer implements Initializin
private final Function<ClearingAccountUpdateRequest, IValidator> clearingAccountUpdateRequestValidator; private final Function<ClearingAccountUpdateRequest, IValidator> clearingAccountUpdateRequestValidator;
private final Imdg<Account> accountImdg; private final Imdg<Account> accountImdg;
private final Imdg<ClearingAccount> clearingAccountImdg;
private final Imdg<Company> companyImdg; private final Imdg<Company> companyImdg;
private final Imdg<Relation> relationImdg; private final Imdg<Relation> relationImdg;
private final Imdg<ClearingMemberCategory> clearingMemberCategoryImdg; private final Imdg<ClearingMemberCategory> clearingMemberCategoryImdg;
@ -103,6 +104,7 @@ public class ClearingAccountService extends QueueConsumer implements Initializin
this.clearingAccountUpdateRequestValidator = clearingAccountUpdateRequestValidator; this.clearingAccountUpdateRequestValidator = clearingAccountUpdateRequestValidator;
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class);
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
this.relationImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); this.relationImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
this.clearingMemberCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.clearingMemberCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
@ -362,11 +364,16 @@ public class ClearingAccountService extends QueueConsumer implements Initializin
); );
Account account = sDf52.getAccount() == null ? null : accountImdg.getFirstObjectByFieldValues(accountQuery); Account account = sDf52.getAccount() == null ? null : accountImdg.getFirstObjectByFieldValues(accountQuery);
if (account == null) { if (account == null) {
String msg = messageResolver.resolve(new EnumMessage(AccountError.AccountNotFound, sDf52.getAccount())); if (SDFProcessService.SDF52_STATUS_3Open.equals(sDf52.getStatus())) {
log.warn("By generationId={} s_df52[{}] (query: {}) error: {}", groupId, sDf52.getId(), accountQuery, msg); log.debug("By generationId={} s_df52[{}].status={}, but account not found (query: {}). COntinuse with result OK for status 3",
toProcessSDF53.add(new MutableTriple<>(sDf52, null, groupId, sDf52.getId(), sDf52.getStatus(), accountQuery);
makeSdfErrorText(AccountError.AccountNotFound, SDFProcessService.SDF_STATUS_ERROR_COMPANY_NOT_FOUND))); } else {
continue; String msg = messageResolver.resolve(new EnumMessage(AccountError.AccountNotFound, sDf52.getAccount()));
log.warn("By generationId={} s_df52[{}] (query: {}) error: {}", groupId, sDf52.getId(), accountQuery, msg);
toProcessSDF53.add(new MutableTriple<>(sDf52, null,
makeSdfErrorText(AccountError.AccountNotFound, SDFProcessService.SDF_STATUS_ERROR_COMPANY_NOT_FOUND)));
continue;
}
} }
toProcessSDF53.add(new MutableTriple<>(sDf52, account, SDFProcessService.SDF_STATUS_OK)); toProcessSDF53.add(new MutableTriple<>(sDf52, account, SDFProcessService.SDF_STATUS_OK));
toUpdate.add(new Pair<>(sDf52, account)); toUpdate.add(new Pair<>(sDf52, account));

View file

@ -38,6 +38,11 @@ public class SDFProcessService {
public static final String SDF_STATUS_ERROR_NO_TRADE = "4"; // (Ошибка. Торги не идут) public static final String SDF_STATUS_ERROR_NO_TRADE = "4"; // (Ошибка. Торги не идут)
public static final String SDF_STATUS_ERROR = "9"; // (Другие ошибки, выявленные в КС) - если получены другие ошибки (т.е. account НЕ обновлена по sDf52). public static final String SDF_STATUS_ERROR = "9"; // (Другие ошибки, выявленные в КС) - если получены другие ошибки (т.е. account НЕ обновлена по sDf52).
protected static final Long SDF52_STATUS_0Blocked = 0L;
protected static final Long SDF52_STATUS_1Unblocked = 1L;
protected static final Long SDF52_STATUS_2Closed = 2L;
protected static final Long SDF52_STATUS_3Open = 3L;
final protected Logger log = LoggerFactory.getLogger(getClass()); final protected Logger log = LoggerFactory.getLogger(getClass());
protected final Producer<String, Object> kafkaResponseQueue; protected final Producer<String, Object> kafkaResponseQueue;
@ -129,12 +134,12 @@ public class SDFProcessService {
* @return AccountStatus или null * @return AccountStatus или null
*/ */
public AccountStatus parseSdf52Status(Long status) { public AccountStatus parseSdf52Status(Long status) {
if (Long.valueOf(1L).equals(status) || Long.valueOf(3L).equals(status)) { if (SDF52_STATUS_1Unblocked.equals(status) || SDF52_STATUS_3Open.equals(status)) {
return AccountStatus.ACTIVE; return AccountStatus.ACTIVE;
} else if (Long.valueOf(0L).equals(status)) { } else if (SDF52_STATUS_0Blocked.equals(status)) {
return AccountStatus.BLOCKED; return AccountStatus.BLOCKED;
} }
if (Long.valueOf(2L).equals(status)) { if (SDF52_STATUS_2Closed.equals(status)) {
return AccountStatus.CLOSE; return AccountStatus.CLOSE;
} }
return null; return null;

View file

@ -0,0 +1,164 @@
package ru.spcex.clearing.account.service;
import org.apache.kafka.clients.consumer.MockConsumer;
import org.apache.kafka.clients.producer.Producer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import ru.clearing.classes.statics.data.account.*;
import ru.spcex.clearing.account.config.BeanConfiguration;
import ru.spcex.clearing.account.config.validation.AccountSymbolsValidationConfig;
import ru.spcex.clearing.account.config.validation.ValidationConfig;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountSymbolsNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest;
import ru.spcex.clearing.test.MatcherFactory;
import ru.spcex.clearing.test.TestObjectCreator;
import ru.spcex.clearing.test.config.ImdgTestConfig;
import ru.spcex.clearing.test.config.KafkaTestConfig;
import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator;
import static ru.spcex.clearing.test.TestUtils.*;
import static ru.spcex.clearing.test.config.KafkaTestConfig.setMockFuture;
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {
BeanConfiguration.class,
ValidationConfig.class,
AccountSymbolsValidationConfig.class,
AccountSymbolsService.class,
ImdgTestConfig.class,
KafkaTestConfig.class})
class AccountSymbolsServiceTest {
public static final MatcherFactory.Matcher<AccountSymbols> ACCOUNT_SYMBOL_MATCHER = usingIgnoringFieldsComparator();
private static final int PARTITION = 0;
@Autowired
AccountSymbolsService accountSymbolsService;
@Autowired
@Qualifier("hazelcastServiceTest")
private ImdgProvider hazelcastServiceTest;
@Autowired
@Qualifier("mockProducer")
protected Producer<String, Object> mockProducer;
@Autowired
@Qualifier("kafkaTestTemplate")
protected KafkaTemplate<String, Object> kafkaTemplate;
private Imdg<AccountSymbols> accountSymbolsImdg;
private Imdg<Account> accountImdg;
private Long accountId;
private Imdg<ClearingAccount> clearingAccountImdg;
private Long clearingAccountId;
static int newRequestCnt = 0;
@PostConstruct
private void init() {
hazelcastServiceTest.waitAvailable();
accountSymbolsImdg = hazelcastServiceTest.getImdg(
IMDGDistributedNames.Map_AccountSymbols, AccountSymbols.class
);
accountImdg = hazelcastServiceTest.getImdg(
IMDGDistributedNames.Map_Account, Account.class
);
clearingAccountImdg = hazelcastServiceTest.getImdg(
IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class
);
Account account = new Account();
account.setStatus(ServiceStatus.Active.getKey());
account.setAccountType(AccountType.Clrn.getKey());
accountId = accountImdg.insert(account);
ClearingAccount clearingAccount = new ClearingAccount();
clearingAccount.setAccountId(accountId);
clearingAccount.setClearingAccountType("CAT");
clearingAccountId = clearingAccountImdg.insert(clearingAccount);
new TestObjectCreator(hazelcastServiceTest).createUserAdmin(1000L);
}
@PreDestroy
private void destroyTest() {
//clean test data
Account account = accountImdg.getSingleObjectByID(accountId);
if (account != null)
accountImdg.delete(account);
ClearingAccount clearingAccount = clearingAccountImdg.getSingleObjectByID(clearingAccountId);
if (clearingAccount != null)
clearingAccountImdg.delete(clearingAccount);
}
@Test
void tradingClearingRegistryNew_moneyAccount_clearingAccount() {
setMockFuture(kafkaTemplate);
AccountSymbolsNewRequest accountSymbolsNewRequest = new AccountSymbolsNewRequest();
accountSymbolsNewRequest.setAccountId(accountId);
accountSymbolsNewRequest.setAccountSymbolValue("SYMBOL1");
AccountSymbols predictableAccountSymbols = new AccountSymbols();
predictableAccountSymbols.setAccountId(accountId);
predictableAccountSymbols.setAccountSymbolValue("SYMBOL1");
String jsonString = getJsonStringForNew(accountSymbolsNewRequest, 0L);
addRecordToKafka((MockConsumer) accountSymbolsService.getConsumer(),
Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_NEW,
newRequestCnt,
0,
jsonString);
waitingSendAndCheckRecord(0L, mockProducer);
AccountSymbols resultNew = accountSymbolsImdg.getAllValues().iterator().next();
predictableAccountSymbols.setId(resultNew.getId());
ACCOUNT_SYMBOL_MATCHER.assertMatch(resultNew, predictableAccountSymbols);
accountSymbolsImdg.delete(resultNew); // cleanup test
newRequestCnt++;
}
@Test
void tradingClearingRegistryDelete() {
AccountSymbols existAccountSymbols = new AccountSymbols();
existAccountSymbols.setAccountId(accountId);
existAccountSymbols.setAccountSymbolValue("SYMBOL 2");
Long accountSymbolId = accountSymbolsImdg.insert(existAccountSymbols);
CommonDeleteRequest accountSymbolsDeleteRequest = new CommonDeleteRequest();
accountSymbolsDeleteRequest.setId(accountSymbolId);
String jsonString = getJsonStringForDelete(accountSymbolsDeleteRequest, 0);
//ACT
addRecordToKafka((MockConsumer) accountSymbolsService.getConsumer(),
Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_DELETE,
PARTITION,
0,
jsonString);
//ASSERT
waitingSendAndCheckRecord(0L, mockProducer);
AccountSymbols resultUpdating = accountSymbolsImdg.getSingleObjectByID(accountSymbolId);
Assertions.assertNull(resultUpdating, "Должен был удалиться");
}
}

View file

@ -195,6 +195,19 @@
</fileMapper> </fileMapper>
</fileMappers> </fileMappers>
</transformationSet> </transformationSet>
<transformationSet>
<dir>src/main/resources/meta</dir>
<includes>
<include>data_initial.xml</include>
</includes>
<stylesheet>src/main/resources/meta/xsl/data.xsl</stylesheet>
<fileMappers>
<fileMapper
implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
<targetExtension>data_initial.sql</targetExtension>
</fileMapper>
</fileMappers>
</transformationSet>
</transformationSets> </transformationSets>
</configuration> </configuration>
</execution> </execution>

View file

@ -1,5 +1,7 @@
package ru.spcex.clearing.backendapi.config; package ru.spcex.clearing.backendapi.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.annotation.Qualifier;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -11,6 +13,8 @@ import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
@Configuration @Configuration
public class BackEndApiImdgConfig { public class BackEndApiImdgConfig {
Logger log = LoggerFactory.getLogger(getClass());
@Bean(name = "taskExecutorHazelcastClientInitializer") @Bean(name = "taskExecutorHazelcastClientInitializer")
public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() { public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() {
return createThreadPoolTaskExecutor(1, true); return createThreadPoolTaskExecutor(1, true);
@ -38,6 +42,10 @@ public class BackEndApiImdgConfig {
@Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, @Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter,
BackendApiSettings clientSetting BackendApiSettings clientSetting
) { ) {
if (clientSetting.getHazelcast() == null || clientSetting.getHazelcast().getClusterMembers() == null) {
log.warn("Property \"backend-api.hazelcast.cluster-members\" not set!");
throw new IllegalArgumentException("Property \"backend-api.hazelcast.cluster-members\" not set");
}
ImdgProvider imdg = new HazelcastService(taskExecutorHazelcastClientInitializer, ImdgProvider imdg = new HazelcastService(taskExecutorHazelcastClientInitializer,
taskExecutorIdGeneratorAwaiter, taskExecutorIdGeneratorAwaiter,
clientSetting.getHazelcast()); clientSetting.getHazelcast());
@ -52,6 +60,10 @@ public class BackEndApiImdgConfig {
@Qualifier("taskExecutorIdGeneratorAwaiterHist") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, @Qualifier("taskExecutorIdGeneratorAwaiterHist") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter,
BackendApiSettings clientSetting BackendApiSettings clientSetting
) { ) {
if (clientSetting.getHazelcastSearch() == null || clientSetting.getHazelcastSearch().getClusterMembers() == null) {
log.warn("Property \"backend-api.hazelcast-search.cluster-members\" not set!");
// может работать без history, но history будет недоступна
}
ImdgProvider imdg = new HazelcastService(taskExecutorHazelcastClientInitializer, ImdgProvider imdg = new HazelcastService(taskExecutorHazelcastClientInitializer,
taskExecutorIdGeneratorAwaiter, taskExecutorIdGeneratorAwaiter,
clientSetting.getHazelcastSearch()); clientSetting.getHazelcastSearch());

View file

@ -0,0 +1,71 @@
package ru.spcex.clearing.backendapi.controller.queue.account;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import ru.clearing.classes.statics.data.account.AccountSymbols;
import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController;
import ru.spcex.clearing.backendapi.controller.request.cud.account.AccountSymbolsNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.backendapi.service.IOperator;
import ru.spcex.clearing.backendapi.service.IStateLoader;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@Controller
@RequestMapping("/accounting/depo-accounts-symbols")
public class AccountSymbolsController extends AbstractQueueController {
private final IStateLoader stateLoader;
@Autowired
public AccountSymbolsController(IOperator operator, IStateLoader stateLoader) {
super(operator);
this.stateLoader = stateLoader;
}
@ApiOperation(value = "get all accounts-symbols.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)})
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public CommonGetAllResponse getAll() {
Collection<Map<String, Object>> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_AccountSymbols, AccountSymbols.class);
CommonGetAllResponse response = new CommonGetAllResponse();
response.fromEntity(all);
return response;
}
@ApiOperation(value = "create AccountSymbols.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CudResponse add(
@ApiParam(value = "Параметры команды в JSON формате.", required = true)
@RequestBody AccountSymbolsNewAction accountNewAction) throws ExecutionException, InterruptedException {
return processRequest(Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_NEW, accountNewAction);
}
@ApiOperation(value = "delete AccountSymbols.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
@ResponseBody
public CudResponse delete(@ApiParam(value = "Идентификатор удаляемого объекта", required = true, example = "1234")
@PathVariable("id") Long id) throws ExecutionException, InterruptedException {
CommonDeleteAction deleteAction = new CommonDeleteAction();
deleteAction.setId(id);
return processRequest(Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_DELETE, deleteAction);
}
}

View file

@ -46,7 +46,7 @@ public class HistController {
@ApiOperation(value = "Get history") @ApiOperation(value = "Get history")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)}) @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)})
@RequestMapping(path = "/all", method = RequestMethod.GET) @RequestMapping(method = RequestMethod.GET)
@ResponseBody @ResponseBody
public CommonGetAllResponse getHistory( public CommonGetAllResponse getHistory(
@ApiParam(value = "destination сущности по которой запрашивается история", example = "money-balance-registers", required = true) @ApiParam(value = "destination сущности по которой запрашивается история", example = "money-balance-registers", required = true)

View file

@ -0,0 +1,47 @@
package ru.spcex.clearing.backendapi.controller.request.cud.account;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountSymbolsNewRequest;
public class AccountSymbolsNewAction implements IAction<AccountSymbolsNewRequest> {
@ApiModelProperty(value = "Номер счета", example = "1200")
@JsonProperty
private Long accountId;
@ApiModelProperty(value = "Значение реквизита", example = "ABCD")
@JsonProperty
private String accountSymbolValue;
@Override
public AccountSymbolsNewRequest toRequest() {
var req = new AccountSymbolsNewRequest();
req.setAccountId(this.accountId);
req.setAccountSymbolValue(this.accountSymbolValue);
return req;
}
@ApiModelProperty(hidden = true)
@Override
public ActionType getActionType() {
return ActionType.NEW;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountSymbolValue() {
return accountSymbolValue;
}
public void setAccountSymbolValue(String accountSymbolValue) {
this.accountSymbolValue = accountSymbolValue;
}
}

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<meta version="3.5.0.14"> <meta version="3.9.0.68">
<enums> <enums>
<allowed id="1" code="ALWD" name="Разрешено"/> <allowed id="1" code="ALWD" name="Разрешено"/>
<allowed id="2" code="DEND" name="Запрещено"/> <allowed id="2" code="DEND" name="Запрещено"/>
@ -156,7 +156,7 @@
<registryUnit id="5" code="U" name="Невыясненные"/> <registryUnit id="5" code="U" name="Невыясненные"/>
<registryUnit id="5" code="I" name="Списания/зачисления"/> <registryUnit id="5" code="I" name="Списания/зачисления"/>
<registryUnit id="7" code="V" name="Выписка"/> <registryUnit id="7" code="V" name="Выписка"/>
<registryCode id="1" code="AMAT" name="Денежные средства - общие"/> <registryCode id="1" code="AMAT" name="Денежные средства Участника клиринга, зарезервированные на торги"/>
<registryCode id="2" code="AMAF" name="Денежные средства - свободные"/> <registryCode id="2" code="AMAF" name="Денежные средства - свободные"/>
<registryCode id="3" code="AMAB" name="Денежные средства - блокированные"/> <registryCode id="3" code="AMAB" name="Денежные средства - блокированные"/>
<registryCode id="4" code="TMAT" name="Требования по деньгам"/> <registryCode id="4" code="TMAT" name="Требования по деньгам"/>
@ -167,7 +167,7 @@
<registryCode id="9" code="LSAT" name="Рассчитанные обязательства по бумагам"/> <registryCode id="9" code="LSAT" name="Рассчитанные обязательства по бумагам"/>
<registryCode id="10" code="LMAT" name="Рассчитанные обязательства по деньгам"/> <registryCode id="10" code="LMAT" name="Рассчитанные обязательства по деньгам"/>
<registryCode id="11" code="CSAT" name="Рассчитанные требования по бумагам"/> <registryCode id="11" code="CSAT" name="Рассчитанные требования по бумагам"/>
<registryCode id="12" code="AMBT" name="Денежные средства клиента - общие"/> <registryCode id="12" code="AMBT" name="Денежные средства Участника клиринга, зарезервированные на торги клиенты"/>
<registryCode id="13" code="AMBF" name="Денежные средства клиента - свободные"/> <registryCode id="13" code="AMBF" name="Денежные средства клиента - свободные"/>
<registryCode id="14" code="AMBB" name="Денежные средства клиента - блокированные"/> <registryCode id="14" code="AMBB" name="Денежные средства клиента - блокированные"/>
<registryCode id="15" code="TMBT" name="Требования по деньгам (кл)"/> <registryCode id="15" code="TMBT" name="Требования по деньгам (кл)"/>
@ -180,14 +180,18 @@
<registryCode id="22" code="CSBT" name="Рассчитанные требования по бумагам (кл)"/> <registryCode id="22" code="CSBT" name="Рассчитанные требования по бумагам (кл)"/>
<registryCode id="23" code="DMAT" name="Возврат депозита"/> <registryCode id="23" code="DMAT" name="Возврат депозита"/>
<registryCode id="24" code="DMBT" name="Возврат депозита (кл)"/> <registryCode id="24" code="DMBT" name="Возврат депозита (кл)"/>
<registryCode id="25" code="ASAT" name="Ценные бумаги - общие"/> <registryCode id="25" code="ASAT" name="Ценные бумаги Участника клиринга свои"/>
<registryCode id="26" code="ASAF" name="Ценные бумаги - свободные"/> <registryCode id="26" code="ASAF" name="Ценные бумаги - свободные"/>
<registryCode id="27" code="ASAB" name="Ценные бумаги - блокированные"/> <registryCode id="27" code="ASAB" name="Ценные бумаги - блокированные"/>
<registryCode id="28" code="DMAX" name="Возврат инициатору"/> <registryCode id="28" code="DMAX" name="Возврат инициатору"/>
<registryCode id="29" code="DMBX" name="Возврат инициатору (кл)"/> <registryCode id="29" code="DMBX" name="Возврат инициатору (кл)"/>
<registryCode id="30" code="DMAU" name="Денежные средства - невыясненные"/> <registryCode id="30" code="DMAU" name="Денежные средства - невыясненные"/>
<registryCode id="31" code="DMAV" name="Треб. выписки"/> <registryCode id="31" code="DMAV" name="Треб. выписки"/>
<registryCode id="32" code="ASZT" name="Ценные бумаги - общие"/> <registryCode id="32" code="ASZT" name="Ценные бумаги для размещения/выкупа"/>
<registryCode id="33" code="ASBT" name="Ценные бумаги Участника клиринга клиенты"/>
<registryCode id="34" code="ASCT" name="Ценные бумаги Участника клиринга клиенты-нерезиденты"/>
<registryCode id="35" code="AMCT" name="Денежные средства Участника клиринга, зарезервированные на торги клиенты"/>
<registryCode id="36" code="ASXT" name="Ценные бумаги Участника клиринга ДУ"/>
<registryStatus id="1" code="OK" name="Рассчитано"/> <registryStatus id="1" code="OK" name="Рассчитано"/>
<registryStatus id="2" code="UNCV" name="Не исполнено"/> <registryStatus id="2" code="UNCV" name="Не исполнено"/>
<registryStatus id="3" code="FAIL" name="Не исполнено контрагентом"/> <registryStatus id="3" code="FAIL" name="Не исполнено контрагентом"/>
@ -249,6 +253,7 @@
<task id="26" code="SDEP" name="Время начала возврата депозитов"/> <task id="26" code="SDEP" name="Время начала возврата депозитов"/>
<task id="27" code="EDEP" name="Время завершения возврата депозитов"/> <task id="27" code="EDEP" name="Время завершения возврата депозитов"/>
<task id="28" code="CHDF" name="Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21"/> <task id="28" code="CHDF" name="Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21"/>
<task id="29" code="CCLR" name="Завершение неудачных клиринговых сессий"/>
<taskStatus id="1" code="ACTV" name="Активна"/> <taskStatus id="1" code="ACTV" name="Активна"/>
<taskStatus id="2" code="BLKD" name="Не активна"/> <taskStatus id="2" code="BLKD" name="Не активна"/>
<taskStatus id="3" code="CNCL" name="Отмена расписания"/> <taskStatus id="3" code="CNCL" name="Отмена расписания"/>
@ -428,7 +433,8 @@
<errorCode id="5019" code="ACNT" name="Для компании %s отсутствует категория %s."/> <errorCode id="5019" code="ACNT" name="Для компании %s отсутствует категория %s."/>
<errorCode id="5022" code="ACNT" name="Для компании %s отсутствует клиринговый код."/> <errorCode id="5022" code="ACNT" name="Для компании %s отсутствует клиринговый код."/>
<errorCode id="5023" code="ACNT" name="Счет %s уже используется."/> <errorCode id="5023" code="ACNT" name="Счет %s уже используется."/>
<errorCode id="5024" code="ACNT" name="Не указан номер счета."/> <errorCode id="5024" code="ACNT" name="Не указан номер счета."/>
<errorCode id="5025" code="ACNT" name="Необходимо указать ДЕПО счет."/>
<!-- error code for balance-service --> <!-- error code for balance-service -->
<errorCode id="5200" code="BLNC" name="Общая ошибка модуля balance-service."/> <errorCode id="5200" code="BLNC" name="Общая ошибка модуля balance-service."/>
<errorCode id="5210" code="BLNC" name="Клиринговая сессия неактивна."/> <errorCode id="5210" code="BLNC" name="Клиринговая сессия неактивна."/>
@ -526,90 +532,6 @@
</enums> </enums>
<objects> <objects>
<company id="1" fullName="АО Санкт-Петербургская Валютная Биржа" shortName="СПВБ" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<company id="2" fullName="ЗАО «Петербургский Расчетный Центр»" shortName="ПРЦ" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<company id="3" fullName="Торговая организация" shortName="ТС" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<company id="4" fullName="ЗАО «Санкт-Петербургский Расчетно-Депозитарный Центр»" shortName="РДЦ" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<!--company id="5" fullName="Центральный Банк Российской Федерации" shortName="ЦБ РФ" tradingCode="" clearingCode="" workflowStatus="ACTV"/-->
<companySymbols id="1" companyId="1" companySymbol="BIC" companySymbolValue="044030920"/>
<companySymbols id="2" companyId="2" companySymbol="BIC" companySymbolValue="044030505"/>
<currency id="643" currency_code="RUB"/>
<security id="643" instrumentType="CRNC" shortName="RUB" fullName="Российский рубль" securitySymbol="RUB" workflowStatus="ACTV"/>
<account id="1" companyId="1" account="30414810300000006000" accountType="TRAN" status="ACTV" processingSign="ALWD"/>
<account id="2" companyId="1" account="30414810600000007000" accountType="ANLT" status="ACTV" processingSign="ALWD"/>
<account id="3" companyId="1" account="700100000AT0" accountType="DTRN" status="ACTV" processingSign="ALWD"/>
<market id="1" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UESC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Обыкновенные акции"/>
<market id="2" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NESC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Обыкновенные акции"/>
<market id="3" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DESC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Обыкновенные акции"/>
<market id="4" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="AESC" name="Размещение: акции (аукцион по цене)" exchangeId="1" description="Размещение: акции (аукцион по цене): Обыкновенные акции"/>
<market id="5" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WESC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Обыкновенные акции"/>
<market id="6" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UEPC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Привилегированные акции"/>
<market id="7" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NEPC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Привилегированные акции"/>
<market id="8" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DEPC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Привилегированные акции"/>
<market id="9" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="AEPC" name="Размещение: акции (аукцион по цене)" exchangeId="1" description="Размещение: акции (аукцион по цене): Привилегированные акции"/>
<market id="10" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WEPC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Привилегированные акции"/>
<market id="11" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABVC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Купонные облигации с переменным купоном"/>
<market id="12" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBVC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Купонные облигации с переменным купоном"/>
<market id="13" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBVC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Купонные облигации с переменным купоном"/>
<market id="14" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBVC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Купонные облигации с переменным купоном"/>
<market id="15" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBVC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Купонные облигации с переменным купоном"/>
<market id="16" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBVC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Купонные облигации с переменным купоном"/>
<market id="17" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABFC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Купонные облигации с постоянным купоном"/>
<market id="18" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBFC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Купонные облигации с постоянным купоном"/>
<market id="19" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBFC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Купонные облигации с постоянным купоном"/>
<market id="20" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBFC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Купонные облигации с постоянным купоном"/>
<market id="21" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBFC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Купонные облигации с постоянным купоном"/>
<market id="22" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBFC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Купонные облигации с постоянным купоном"/>
<market id="23" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABIC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Облигации с индексированным номиналом"/>
<market id="24" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBIC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Облигации с индексированным номиналом"/>
<market id="25" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBIC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Облигации с индексированным номиналом"/>
<market id="26" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBIC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Облигации с индексированным номиналом"/>
<market id="27" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBIC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Облигации с индексированным номиналом"/>
<market id="28" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBIC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Облигации с индексированным номиналом"/>
<market id="29" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABMC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Облигации с амортизацией долга"/>
<market id="30" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBMC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Облигации с амортизацией долга"/>
<market id="31" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBMC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Облигации с амортизацией долга"/>
<market id="32" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBMC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Облигации с амортизацией долга"/>
<market id="33" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBMC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Облигации с амортизацией долга"/>
<market id="34" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBMC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Облигации с амортизацией долга"/>
<market id="35" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BKVC" name="Размещение: Аукцион БР" exchangeId="1" description="Размещение: Аукцион БР: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="36" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SKVC" name="Доразмещение: Адресные заявки БР" exchangeId="1" description="Доразмещение: Адресные заявки БР: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="37" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UKVC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="38" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NKVC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Облигации Банка России с переменным купоном (КОБР)"/>
<market id="39" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DKVC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="45" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABEC" name="Размещение: Аукцион СПВБ" exchangeId="1" description="Размещение: Аукцион СПВБ: Биржевые облигации"/>
<market id="46" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBEC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Биржевые облигации"/>
<market id="47" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBEC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Биржевые облигации"/>
<market id="48" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBEC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Биржевые облигации"/>
<market id="61" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMVC" name="ОФЗПК-Размещение: Аукцион БР" exchangeId="1" description="ОФЗПК-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="62" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMVC" name="ОФЗПК-Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗПК-Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="63" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMVC" name="ОФЗПК-Режим непрерывных торгов" exchangeId="1" description="ОФЗПК-Режим непрерывных торгов: Облигации Минфина"/>
<market id="64" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMVC" name="ОФЗПК-Дискретный аукцион" exchangeId="1" description="ОФЗПК-Дискретный аукцион: Облигации Минфина"/>
<market id="65" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMVC" name="ОФЗПК-Торги в режиме выкупа" exchangeId="1" description="ОФЗПК-Торги в режиме выкупа: Облигации Минфина"/>
<market id="66" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMFC" name="ОФЗПД-Размещение: Аукцион БР" exchangeId="1" description="ОФЗПД-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="67" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMFC" name="ОФЗПД- Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗПД- Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="68" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMFC" name="ОФЗПД-Режим непрерывных торгов" exchangeId="1" description="ОФЗПД-Режим непрерывных торгов: Облигации Минфина"/>
<market id="69" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMFC" name="ОФЗПД-Дискретный аукцион" exchangeId="1" description="ОФЗПД-Дискретный аукцион: Облигации Минфина"/>
<market id="70" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMFC" name="ОФЗПД-Торги в режиме выкупа" exchangeId="1" description="ОФЗПД-Торги в режиме выкупа: Облигации Минфина"/>
<market id="71" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMMC" name="ОФЗАД-Размещение: Аукцион БР" exchangeId="1" description="ОФЗАД-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="72" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMMC" name="ОФЗАД-Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗАД-Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="73" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMMC" name="ОФЗАД-Режим непрерывных торгов" exchangeId="1" description="ОФЗАД-Режим непрерывных торгов: Облигации Минфина"/>
<market id="74" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMMC" name="ОФЗАД-Дискретный аукцион" exchangeId="1" description="ОФЗАД-Дискретный аукцион: Облигации Минфина"/>
<market id="75" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMMC" name="ОФЗАД-Торги в режиме выкупа" exchangeId="1" description="ОФЗАД-Торги в режиме выкупа: Облигации Минфина"/>
<market id="76" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMIC" name="ОФЗИН-Размещение: Аукцион БР" exchangeId="1" description="ОФЗИН-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="77" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMIC" name="ОФЗИН-Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗИН-Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="78" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMIC" name="ОФЗИН-Режим непрерывных торгов" exchangeId="1" description="ОФЗИН-Режим непрерывных торгов: Облигации Минфина"/>
<market id="79" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMIC" name="ОФЗИН-Дискретный аукцион" exchangeId="1" description="ОФЗИН-Дискретный аукцион: Облигации Минфина"/>
<market id="80" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMIC" name="ОФЗИН-Торги в режиме выкупа" exchangeId="1" description="ОФЗИН-Торги в режиме выкупа: Облигации Минфина"/>
<market id="82" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BBVC" name="ОФЗ-ПК - Аукцион БР" exchangeId="1" description="ОФЗ-ПК - Аукцион БР"/>
<market id="83" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTATSS" name="СПб ГУП АТС Смольного" exchangeId="1" description="СПб ГУП АТС Смольного"/>
<market id="88" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMTTKFSP" name="Комитет финансов СПб" exchangeId="1" description="Комитет финансов СПб"/>
<market id="89" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDSKFLO" name="Комитет финансов ЛО" exchangeId="1" description="Комитет финансов ЛО"/>
<market id="90" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTFSKB" name="ФСКМБ" exchangeId="1" description="ФСКМБ"/>
<market id="91" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDSFGGE" name="ФАУ ГГЭ" exchangeId="1" description="ФАУ ГГЭ"/>
<market id="92" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTVRGO" name="ВВО РГО" exchangeId="1" description="ВВО РГО"/>
<market id="93" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTTDRM" name="ООО Торговый дом РМ-Рейл" exchangeId="1" description="ООО Торговый дом РМ-Рейл"/>
<market id="95" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTRKFN" name="АО РК Финанс" exchangeId="1" description="АО РК Финанс"/>
</objects> </objects>
</meta> </meta>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<meta version="3.9.0.68">
<enums>
</enums>
<objects>
<company id="1" fullName="АО Санкт-Петербургская Валютная Биржа" shortName="СПВБ" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<company id="2" fullName="ЗАО «Петербургский Расчетный Центр»" shortName="ПРЦ" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<company id="3" fullName="Торговая организация" shortName="ТС" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<company id="4" fullName="ЗАО «Санкт-Петербургский Расчетно-Депозитарный Центр»" shortName="РДЦ" tradingCode="" clearingCode="" workflowStatus="ACTV"/>
<!--company id="5" fullName="Центральный Банк Российской Федерации" shortName="ЦБ РФ" tradingCode="" clearingCode="" workflowStatus="ACTV"/-->
<companySymbols id="1" companyId="1" companySymbol="BIC" companySymbolValue="044030920"/>
<companySymbols id="2" companyId="2" companySymbol="BIC" companySymbolValue="044030505"/>
<currency id="643" currency_code="RUB"/>
<security id="643" instrumentType="CRNC" shortName="RUB" fullName="Российский рубль" securitySymbol="RUB" workflowStatus="ACTV"/>
<account id="1" companyId="1" account="30414810300000006000" accountType="TRAN" status="ACTV" processingSign="ALWD"/>
<account id="2" companyId="1" account="30414810600000007000" accountType="ANLT" status="ACTV" processingSign="ALWD"/>
<account id="3" companyId="1" account="700100000AT0" accountType="DTRN" status="ACTV" processingSign="ALWD"/>
<market id="1" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UESC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Обыкновенные акции"/>
<market id="2" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NESC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Обыкновенные акции"/>
<market id="3" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DESC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Обыкновенные акции"/>
<market id="4" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="AESC" name="Размещение: акции (аукцион по цене)" exchangeId="1" description="Размещение: акции (аукцион по цене): Обыкновенные акции"/>
<market id="5" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WESC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Обыкновенные акции"/>
<market id="6" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UEPC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Привилегированные акции"/>
<market id="7" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NEPC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Привилегированные акции"/>
<market id="8" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DEPC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Привилегированные акции"/>
<market id="9" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="AEPC" name="Размещение: акции (аукцион по цене)" exchangeId="1" description="Размещение: акции (аукцион по цене): Привилегированные акции"/>
<market id="10" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WEPC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Привилегированные акции"/>
<market id="11" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABVC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Купонные облигации с переменным купоном"/>
<market id="12" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBVC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Купонные облигации с переменным купоном"/>
<market id="13" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBVC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Купонные облигации с переменным купоном"/>
<market id="14" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBVC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Купонные облигации с переменным купоном"/>
<market id="15" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBVC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Купонные облигации с переменным купоном"/>
<market id="16" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBVC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Купонные облигации с переменным купоном"/>
<market id="17" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABFC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Купонные облигации с постоянным купоном"/>
<market id="18" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBFC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Купонные облигации с постоянным купоном"/>
<market id="19" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBFC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Купонные облигации с постоянным купоном"/>
<market id="20" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBFC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Купонные облигации с постоянным купоном"/>
<market id="21" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBFC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Купонные облигации с постоянным купоном"/>
<market id="22" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBFC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Купонные облигации с постоянным купоном"/>
<market id="23" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABIC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Облигации с индексированным номиналом"/>
<market id="24" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBIC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Облигации с индексированным номиналом"/>
<market id="25" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBIC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Облигации с индексированным номиналом"/>
<market id="26" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBIC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Облигации с индексированным номиналом"/>
<market id="27" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBIC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Облигации с индексированным номиналом"/>
<market id="28" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBIC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Облигации с индексированным номиналом"/>
<market id="29" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABMC" name="Размещение: Аукцион по цене" exchangeId="1" description="Размещение: Аукцион по цене: Облигации с амортизацией долга"/>
<market id="30" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="KBMC" name="Размещение: Аукцион по ставке" exchangeId="1" description="Размещение: Аукцион по ставке: Облигации с амортизацией долга"/>
<market id="31" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBMC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Облигации с амортизацией долга"/>
<market id="32" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBMC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Облигации с амортизацией долга"/>
<market id="33" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBMC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Облигации с амортизацией долга"/>
<market id="34" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="WBMC" name="Размещение: адресные заявки (подписка)" exchangeId="1" description="Размещение: адресные заявки (подписка): Облигации с амортизацией долга"/>
<market id="35" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BKVC" name="Размещение: Аукцион БР" exchangeId="1" description="Размещение: Аукцион БР: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="36" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SKVC" name="Доразмещение: Адресные заявки БР" exchangeId="1" description="Доразмещение: Адресные заявки БР: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="37" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UKVC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="38" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NKVC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Облигации Банка России с переменным купоном (КОБР)"/>
<market id="39" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DKVC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Облигации Банка России с переменным купоном (КОБР)"/>
<market id="45" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="ABEC" name="Размещение: Аукцион СПВБ" exchangeId="1" description="Размещение: Аукцион СПВБ: Биржевые облигации"/>
<market id="46" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UBEC" name="Режим непрерывных торгов" exchangeId="1" description="Режим непрерывных торгов: Биржевые облигации"/>
<market id="47" marketType="SCND" section="FOND" settlementCurrency="RUB" code="NBEC" name="Режим переговорных сделок (РПС)" exchangeId="1" description="Режим переговорных сделок (РПС): Биржевые облигации"/>
<market id="48" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DBEC" name="Дискретный аукцион" exchangeId="1" description="Дискретный аукцион: Биржевые облигации"/>
<market id="61" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMVC" name="ОФЗПК-Размещение: Аукцион БР" exchangeId="1" description="ОФЗПК-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="62" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMVC" name="ОФЗПК-Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗПК-Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="63" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMVC" name="ОФЗПК-Режим непрерывных торгов" exchangeId="1" description="ОФЗПК-Режим непрерывных торгов: Облигации Минфина"/>
<market id="64" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMVC" name="ОФЗПК-Дискретный аукцион" exchangeId="1" description="ОФЗПК-Дискретный аукцион: Облигации Минфина"/>
<market id="65" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMVC" name="ОФЗПК-Торги в режиме выкупа" exchangeId="1" description="ОФЗПК-Торги в режиме выкупа: Облигации Минфина"/>
<market id="66" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMFC" name="ОФЗПД-Размещение: Аукцион БР" exchangeId="1" description="ОФЗПД-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="67" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMFC" name="ОФЗПД- Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗПД- Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="68" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMFC" name="ОФЗПД-Режим непрерывных торгов" exchangeId="1" description="ОФЗПД-Режим непрерывных торгов: Облигации Минфина"/>
<market id="69" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMFC" name="ОФЗПД-Дискретный аукцион" exchangeId="1" description="ОФЗПД-Дискретный аукцион: Облигации Минфина"/>
<market id="70" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMFC" name="ОФЗПД-Торги в режиме выкупа" exchangeId="1" description="ОФЗПД-Торги в режиме выкупа: Облигации Минфина"/>
<market id="71" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMMC" name="ОФЗАД-Размещение: Аукцион БР" exchangeId="1" description="ОФЗАД-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="72" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMMC" name="ОФЗАД-Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗАД-Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="73" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMMC" name="ОФЗАД-Режим непрерывных торгов" exchangeId="1" description="ОФЗАД-Режим непрерывных торгов: Облигации Минфина"/>
<market id="74" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMMC" name="ОФЗАД-Дискретный аукцион" exchangeId="1" description="ОФЗАД-Дискретный аукцион: Облигации Минфина"/>
<market id="75" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMMC" name="ОФЗАД-Торги в режиме выкупа" exchangeId="1" description="ОФЗАД-Торги в режиме выкупа: Облигации Минфина"/>
<market id="76" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BMIC" name="ОФЗИН-Размещение: Аукцион БР" exchangeId="1" description="ОФЗИН-Размещение: Аукцион БР: Облигации Минфина"/>
<market id="77" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="SMIC" name="ОФЗИН-Доразмещение: Адресные заявки БР" exchangeId="1" description="ОФЗИН-Доразмещение: Адресные заявки БР: Облигации Минфина"/>
<market id="78" marketType="SCND" section="FOND" settlementCurrency="RUB" code="UMIC" name="ОФЗИН-Режим непрерывных торгов" exchangeId="1" description="ОФЗИН-Режим непрерывных торгов: Облигации Минфина"/>
<market id="79" marketType="SCND" section="FOND" settlementCurrency="RUB" code="DMIC" name="ОФЗИН-Дискретный аукцион" exchangeId="1" description="ОФЗИН-Дискретный аукцион: Облигации Минфина"/>
<market id="80" marketType="SCND" section="FOND" settlementCurrency="RUB" code="MMIC" name="ОФЗИН-Торги в режиме выкупа" exchangeId="1" description="ОФЗИН-Торги в режиме выкупа: Облигации Минфина"/>
<market id="82" marketType="PRMR" section="FOND" settlementCurrency="RUB" code="BBVC" name="ОФЗ-ПК - Аукцион БР" exchangeId="1" description="ОФЗ-ПК - Аукцион БР"/>
<market id="83" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTATSS" name="СПб ГУП АТС Смольного" exchangeId="1" description="СПб ГУП АТС Смольного"/>
<market id="88" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMTTKFSP" name="Комитет финансов СПб" exchangeId="1" description="Комитет финансов СПб"/>
<market id="89" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDSKFLO" name="Комитет финансов ЛО" exchangeId="1" description="Комитет финансов ЛО"/>
<market id="90" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTFSKB" name="ФСКМБ" exchangeId="1" description="ФСКМБ"/>
<market id="91" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDSFGGE" name="ФАУ ГГЭ" exchangeId="1" description="ФАУ ГГЭ"/>
<market id="92" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTVRGO" name="ВВО РГО" exchangeId="1" description="ВВО РГО"/>
<market id="93" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTTDRM" name="ООО Торговый дом РМ-Рейл" exchangeId="1" description="ООО Торговый дом РМ-Рейл"/>
<market id="95" marketType="PRMR" section="MKR" settlementCurrency="RUB" code="XMDTRKFN" name="АО РК Финанс" exchangeId="1" description="АО РК Финанс"/>
</objects>
</meta>

View file

@ -1,6 +1,6 @@
{ {
"version": "3.8.0.58", "version": "3.9.0.71",
"enums": { "enums": {
@ -3328,11 +3328,11 @@
"type": 3,"name": "Номер купона","shortname": "Номер","searchable": true,"sortable": true,"visible": true "type": 3,"name": "Номер купона","shortname": "Номер","searchable": true,"sortable": true,"visible": true
} }
, ,
{"code": "periodEndDate", {"code": "periodStartDate",
"type": 6,"name": "Начало периода действия","shortname": "Начало","searchable": true,"sortable": true,"visible": true "type": 6,"name": "Начало периода действия","shortname": "Начало","searchable": true,"sortable": true,"visible": true
} }
, ,
{"code": "periodStartDate", {"code": "periodEndDate",
"type": 6,"name": "Окончание периода действия","shortname": "Окончание","searchable": true,"sortable": true,"visible": true "type": 6,"name": "Окончание периода действия","shortname": "Окончание","searchable": true,"sortable": true,"visible": true
} }
, ,
@ -4132,6 +4132,10 @@
{"code": "balance", {"code": "balance",
"type": 10,"name": "Сумма","shortname": "Сумма","required": true "type": 10,"name": "Сумма","shortname": "Сумма","required": true
} }
,
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
}
, ,
{"code": "tradingClearingRegistryId", {"code": "tradingClearingRegistryId",
"type": 1,"name": "Торгово-клиринговый регистр","shortname": "Торгово-клиринговый регистр","link": "tradingClearingRegistry","linkCode": "code","required": true "type": 1,"name": "Торгово-клиринговый регистр","shortname": "Торгово-клиринговый регистр","link": "tradingClearingRegistry","linkCode": "code","required": true
@ -4664,6 +4668,66 @@
} }
] ]
}
,
"accountSymbols": {
"name": "Депо КС - РДЦ",
"destination": "accounting/depo-accounts-symbols",
"class": "ru.clearing.classes.statics.data.account.AccountSymbols",
"logUpdates": "true",
"table": "depo_account_symbols",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true
}
,
{"code": "accountId",
"type": 1,"dbname": "Идентификатор счета","name": "Счет депо КС","shortname": "Счет депо КС","searchable": true,"sortable": true,"visible": true,"link": "account","linkCode": "account"
}
,
{"code": "accountSymbolValue",
"type": 2,"length": 255,"name": "Счет РДЦ","shortname": "Счет РДЦ","searchable": true,"sortable": true,"visible": true
}
]
,"actions":[
{"method":"post",
"name": "Добавление депо КС - РДЦ",
"confirmation": "accountId,accountSymbolValue",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountSymbolsNewAction",
"fields": [
{"code": "accountId",
"type": 1,"dbname": "Идентификатор счета","name": "Счет депо КС","shortname": "Счет депо КС","link": "account","linkCode": "account","required": true
}
,
{"code": "accountSymbolValue",
"type": 2,"length": 255,"name": "Счет РДЦ","shortname": "Счет РДЦ","required": true
}
]
}
,
{"method":"delete",
"name": "Удаление депо КС - РДЦ",
"confirmation": "accountId,accountSymbolValue",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
}
]
}
]
} }
, ,
"clearingAccount": { "clearingAccount": {
@ -5270,11 +5334,15 @@
"group": "Обмен с расчетной организацией", "group": "Обмен с расчетной организацией",
"name": "Вывод свободных средств инициаторов В (отправка ДФ-54 для получения ответа ДФ-55)", "name": "Вывод свободных средств с клирингового регистра (отправка ДФ-54 для получения ответа ДФ-55)",
"fields": [ "fields": [
{"code": "fullBalance",
"type": 10,"name": "Текущий баланс (всего)","shortname": "Текущие средства (всего)","enabled": false
}
,
{"code": "balance", {"code": "balance",
"type": 10,"name": "Текущий баланс","shortname": "Текущие средства","enabled": false "type": 10,"name": "Текущий баланс (свободно)","shortname": "Текущие средства (свободно)","enabled": false
} }
, ,
{"code": "securitySymbol", {"code": "securitySymbol",
@ -5290,7 +5358,7 @@
} }
, ,
{"code": "senderId", {"code": "senderId",
"type": 1,"group": "Отправитель","name": "Участник отправитель","shortname": "Отправитель","link": "company","linkCode": "shortName","required": true,"enabled": false "type": 1,"group": "Отправитель","name": "Участник отправитель","shortname": "Отправитель","link": "company","linkCode": "shortName","required": true
} }
, ,
{"code": "creditLeg_accountId", {"code": "creditLeg_accountId",
@ -5509,6 +5577,28 @@
"name": "Формирование ДФ-05 с кодом 9 (финальный)", "name": "Формирование ДФ-05 с кодом 9 (финальный)",
"fields": []
}
,
{"method":"post",
"destination": "CHDF",
"group": "Общее",
"name": "Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21",
"fields": []
}
,
{"method":"post",
"destination": "CCLR",
"group": "Клиринг",
"name": "Завершение неудачных клиринговых сессий",
"fields": [] "fields": []
} }
] ]
@ -5544,7 +5634,7 @@
} }
, ,
{"code": "sessionStatus", {"code": "sessionStatus",
"type": 12,"dbname": "Код статуса клиринговой сессии","name": "Статус клиринговой сессии","shortname": "Статус","searchable": true,"sortable": true,"visible": true,"link": "sessionStatus" "type": 12,"dbname": "Код статуса клиринговой сессии","name": "Статус клиринговой сессии","shortname": "Шаг","searchable": true,"sortable": true,"visible": true,"link": "sessionStatus"
} }
, ,
{"code": "companyId", {"code": "companyId",
@ -5776,10 +5866,12 @@
, ,
"executionDeposit": { "executionDeposit": {
"name": "Сделки", "name": "Сделки на секции МКР",
"destination": "execution-deposits", "destination": "execution-deposits",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.execution.ExecutionDeposit", "class": "ru.clearing.classes.statics.data.execution.ExecutionDeposit",
"logUpdates": "true", "logUpdates": "true",
@ -5932,6 +6024,8 @@
"destination": "execution-fonds", "destination": "execution-fonds",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.execution.ExecutionFond", "class": "ru.clearing.classes.statics.data.execution.ExecutionFond",
"logUpdates": "true", "logUpdates": "true",
@ -6080,17 +6174,19 @@
"destination": "depo-balance-registers", "destination": "depo-balance-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.DepoBalanceRegister", "class": "ru.clearing.classes.statics.data.register.DepoBalanceRegister",
"table": "balance_depo_register", "table": "balance_depo_register",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true "type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "createdAt", {"code": "createdAt",
"field": "created","type": 4,"webtype": "5","dbname": "Дата-время создания записи","name": "Время создания записи","shortname": "Создано","searchable": true,"sortable": true,"ignore": true "field": "created","type": 4,"webtype": "5","dbname": "Дата-время создания записи","name": "Время создания записи","shortname": "Создано","searchable": true,"sortable": true
} }
, ,
{"code": "updatedAt", {"code": "updatedAt",
@ -6102,7 +6198,7 @@
} }
, ,
{"code": "sessionId", {"code": "sessionId",
"type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session" "type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session","ignore": true
} }
, ,
{"code": "depoCode", {"code": "depoCode",
@ -6126,6 +6222,8 @@
"destination": "money-balance-registers", "destination": "money-balance-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.MoneyBalanceRegister", "class": "ru.clearing.classes.statics.data.register.MoneyBalanceRegister",
"table": "money_balance_register", "table": "money_balance_register",
@ -6140,7 +6238,7 @@
} }
, ,
{"code": "infoAccount", {"code": "infoAccount",
"type": 2,"length": 50,"name": "Номер счета внутреннего учета СПВБ","shortname": "Номер счета внутреннего учета СПВБ","searchable": true,"sortable": true,"visible": true "type": 2,"length": 50,"name": "Номер счета внутреннего учета СПВБ","shortname": "Номер счета внутреннего учета СПВБ","searchable": true,"sortable": true,"visible": true,"ignore": true
} }
, ,
{"code": "remainderSum", {"code": "remainderSum",
@ -6148,23 +6246,23 @@
} }
, ,
{"code": "blockedSum", {"code": "blockedSum",
"type": 10,"name": "Сумма блокированных денежных средств","shortname": "Блокированные","searchable": true,"sortable": true "type": 10,"name": "Сумма блокированных денежных средств","shortname": "Блокированные","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "unblockedSum", {"code": "unblockedSum",
"type": 10,"name": "Сумма свободных денежных средств","shortname": "Свободные","searchable": true,"sortable": true "type": 10,"name": "Сумма свободных денежных средств","shortname": "Свободные","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "inn", {"code": "inn",
"type": 2,"length": 255,"name": "Идентификационный номер налогоплательщика (ИНН)","shortname": "ИНН","searchable": true,"sortable": true,"visible": true "type": 2,"length": 255,"name": "Идентификационный номер налогоплательщика (ИНН)","shortname": "ИНН","searchable": true,"sortable": true,"visible": true,"ignore": true
} }
, ,
{"code": "sessionId", {"code": "sessionId",
"type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session" "type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session","ignore": true
} }
, ,
{"code": "companyFullName", {"code": "companyFullName",
"type": 2,"length": 255,"name": "Полное наименование компании","shortname": "Полное наименование компании","searchable": true,"sortable": true,"visible": true "type": 2,"length": 255,"name": "Полное наименование компании","shortname": "Полное наименование компании","searchable": true,"sortable": true,"visible": true,"ignore": true
} }
, ,
{"code": "companyId", {"code": "companyId",
@ -6172,7 +6270,7 @@
} }
, ,
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true "type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "createdAt", {"code": "createdAt",
@ -6180,7 +6278,7 @@
} }
, ,
{"code": "updatedAt", {"code": "updatedAt",
"field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true "field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true,"ignore": true
} }
] ]
@ -6192,6 +6290,8 @@
"destination": "admitted-liabilities-registers", "destination": "admitted-liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.AdmittedLiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.AdmittedLiabilitiesRegister",
"table": "admitted_liabilities_register", "table": "admitted_liabilities_register",
@ -6254,6 +6354,8 @@
"destination": "covered-liabilities-registers", "destination": "covered-liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.CoveredLiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.CoveredLiabilitiesRegister",
"table": "covered_Liabilities_register", "table": "covered_Liabilities_register",
@ -6316,6 +6418,8 @@
"destination": "money-payment-instruction-registers", "destination": "money-payment-instruction-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.MoneyPaymentInstructionRegister", "class": "ru.clearing.classes.statics.data.register.MoneyPaymentInstructionRegister",
"table": "money_payment_instruction_register", "table": "money_payment_instruction_register",
@ -6370,6 +6474,8 @@
"destination": "depo-payment-instruction-registers", "destination": "depo-payment-instruction-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.DepoPaymentInstructionRegister", "class": "ru.clearing.classes.statics.data.register.DepoPaymentInstructionRegister",
"table": "depo_payment_instruction_register", "table": "depo_payment_instruction_register",
@ -6424,6 +6530,8 @@
"destination": "exclude-liabilities-registers", "destination": "exclude-liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.ExcludeLiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.ExcludeLiabilitiesRegister",
"table": "exclude_liabilities_register", "table": "exclude_liabilities_register",
@ -6502,6 +6610,8 @@
"destination": "liabilities-registers", "destination": "liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.LiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.LiabilitiesRegister",
"table": "liabilities_register", "table": "liabilities_register",
@ -6580,6 +6690,8 @@
"destination": "execution-registers", "destination": "execution-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.ExecutionRegister", "class": "ru.clearing.classes.statics.data.register.ExecutionRegister",
"table": "execution_register", "table": "execution_register",

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?--> <!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?-->
<meta version="3.8.0.63"> <meta version="3.9.0.71">
<!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" --> <!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" -->
<!--Здесь словари--> <!--Здесь словари-->
<enums> <enums>
@ -772,8 +772,8 @@
<securityId type="1" dbname="Идентификатор инструмента" name="Наименование инструмента" shortname="Инструмент" searchable="true" sortable="true" link="security" linkCode="shortName"/> <securityId type="1" dbname="Идентификатор инструмента" name="Наименование инструмента" shortname="Инструмент" searchable="true" sortable="true" link="security" linkCode="shortName"/>
<couponRate type="11" name="Купонная ставка" shortname="Ставка" searchable="true" sortable="true" visible="true"/> <couponRate type="11" name="Купонная ставка" shortname="Ставка" searchable="true" sortable="true" visible="true"/>
<number type="3" name="Номер купона" shortname="Номер" searchable="true" sortable="true" visible="true"/> <number type="3" name="Номер купона" shortname="Номер" searchable="true" sortable="true" visible="true"/>
<periodEndDate type="6" name="Начало периода действия" shortname="Начало" searchable="true" sortable="true" visible="true"/> <periodStartDate type="6" name="Начало периода действия" shortname="Начало" searchable="true" sortable="true" visible="true"/>
<periodStartDate type="6" name="Окончание периода действия" shortname="Окончание" searchable="true" sortable="true" visible="true"/> <periodEndDate type="6" name="Окончание периода действия" shortname="Окончание" searchable="true" sortable="true" visible="true"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
</couponPeriod> </couponPeriod>
<listing name="Инструменты на режимах" destination="listings" class="ru.clearing.classes.statics.data.misc.Listing" logUpdates="true" table="listing"> <listing name="Инструменты на режимах" destination="listings" class="ru.clearing.classes.statics.data.misc.Listing" logUpdates="true" table="listing">
@ -1084,6 +1084,20 @@
<serviceStatus field="accountId" type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" linkKeyCode="id" linkCode="status" link="account" extends="account" /> <serviceStatus field="accountId" type="12" dbname="Код статуса" name="Наименование статуса" shortname="Статус" searchable="true" sortable="true" visible="true" linkKeyCode="id" linkCode="status" link="account" extends="account" />
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
</depoAccount> </depoAccount>
<accountSymbols name="Депо КС - РДЦ" destination="accounting/depo-accounts-symbols" class="ru.clearing.classes.statics.data.account.AccountSymbols" logUpdates="true" table="depo_account_symbols">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<accountId type="1" dbname="Идентификатор счета" name="Счет депо КС" shortname= "Счет депо КС" searchable="true" sortable="true" visible="true" link="account" linkCode="account"/>
<accountSymbolValue type="2" length="255" name="Счет РДЦ" shortname="Счет РДЦ" searchable="true" sortable="true" visible="true"/>
<actions>
<post name="Добавление депо КС - РДЦ" confirmation="accountId,accountSymbolValue" class="ru.spcex.clearing.backendapi.controller.request.cud.account.AccountSymbolsNewAction">
<accountId type="1" dbname="Идентификатор счета" name="Счет депо КС" shortname= "Счет депо КС" link="account" linkCode="account" required="true"/>
<accountSymbolValue type="2" length="255" name="Счет РДЦ" shortname="Счет РДЦ" required="true"/>
</post>
<delete name="Удаление депо КС - РДЦ" confirmation="accountId,accountSymbolValue">
<id type="1" name="Идентификатор записи" shortname="ID" link="account" linkCode="id" required="true"/>
</delete>
</actions>
</accountSymbols>
<clearingAccount name="Торгово-Банковские счета" destination="accounting/clearing-accounts" class="ru.clearing.classes.statics.data.account.ClearingAccount" logUpdates="true" table="clearing_account"> <clearingAccount name="Торгово-Банковские счета" destination="accounting/clearing-accounts" class="ru.clearing.classes.statics.data.account.ClearingAccount" logUpdates="true" table="clearing_account">
<accountId type="1" dbname="Идентификатор счета" name="Номер счета" shortname="Счет" searchable="true" sortable="true" visible="true" link="account" linkCode="account"/> <accountId type="1" dbname="Идентификатор счета" name="Номер счета" shortname="Счет" searchable="true" sortable="true" visible="true" link="account" linkCode="account"/>
<clearingAccountType type="12" dbname="Код типа счета" name="Наименование типа счета" shortname="Тип" searchable="true" sortable="true" visible="true" link="clearingAccountType" linkCode="name"/> <clearingAccountType type="12" dbname="Код типа счета" name="Наименование типа счета" shortname="Тип" searchable="true" sortable="true" visible="true" link="clearingAccountType" linkCode="name"/>
@ -1274,6 +1288,8 @@
</post> </post>
<post destination="CHDF" group="Общее" name="Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21"> <post destination="CHDF" group="Общее" name="Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21">
</post> </post>
<post destination="CCLR" group="Клиринг" name="Завершение неудачных клиринговых сессий">
</post>
</actions> </actions>
</launcher> </launcher>
@ -1282,7 +1298,7 @@
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<clearingDate type="6" name="Дата" shortname="Дата" searchable="true" sortable="true" visible="true"/> <clearingDate type="6" name="Дата" shortname="Дата" searchable="true" sortable="true" visible="true"/>
<sessionStatus type="12" dbname="Код статуса клиринговой сессии" name="Статус клиринговой сессии" shortname="Статус" searchable="true" sortable="true" visible="true" link="sessionStatus"/> <sessionStatus type="12" dbname="Код статуса клиринговой сессии" name="Статус клиринговой сессии" shortname="Шаг" searchable="true" sortable="true" visible="true" link="sessionStatus"/>
<companyId type="1" dbname="Идентификатор инициатора торгов" name="Наименование инициатора торгов" shortname="Инициатор" visible="false" searchable="true" sortable="true" link="company" linkCode="shortName"/> <companyId type="1" dbname="Идентификатор инициатора торгов" name="Наименование инициатора торгов" shortname="Инициатор" visible="false" searchable="true" sortable="true" link="company" linkCode="shortName"/>
<securityId type="1" dbname="Идентификатор инструмента" name="Наименование инструмента" shortname="Инструмент" searchable="false" sortable="true" visible="true" link="security" linkCode="shortName"/> <securityId type="1" dbname="Идентификатор инструмента" name="Наименование инструмента" shortname="Инструмент" searchable="false" sortable="true" visible="true" link="security" linkCode="shortName"/>
<userId type="1" dbname="Идентификатор пользователя" name="Наименование пользователя" shortname="Пользователь" searchable="true" sortable="true" visible="true" link="userCls" linkCode="identifier"/> <userId type="1" dbname="Идентификатор пользователя" name="Наименование пользователя" shortname="Пользователь" searchable="true" sortable="true" visible="true" link="userCls" linkCode="identifier"/>
@ -1339,7 +1355,7 @@
<bankAccId type="2" length="12" name="Идентификатор расчетного счета/кода в клиринговой организации" shortname="Код позиции" searchable="true" sortable="true"/> <bankAccId type="2" length="12" name="Идентификатор расчетного счета/кода в клиринговой организации" shortname="Код позиции" searchable="true" sortable="true"/>
<section type="12" dbname="Код наименования секции" name="Наименование секции" shortname="Секция" searchable="true" sortable="true" visible="true" link="section"/> <section type="12" dbname="Код наименования секции" name="Наименование секции" shortname="Секция" searchable="true" sortable="true" visible="true" link="section"/>
</sTrades> </sTrades>
<executionDeposit name="Сделки" destination="execution-deposits" historyDestination="history" class="ru.clearing.classes.statics.data.execution.ExecutionDeposit" logUpdates="true" table="execution_deposit"> <executionDeposit name="Сделки на секции МКР" destination="execution-deposits" historyDestination="history" class="ru.clearing.classes.statics.data.execution.ExecutionDeposit" logUpdates="true" table="execution_deposit">
<exchangeExecutionId type="1" name="Идентификационный номер сделки в Торговой системе" shortname="Номер сделки" visible="true" searchable="true" sortable="true"/> <exchangeExecutionId type="1" name="Идентификационный номер сделки в Торговой системе" shortname="Номер сделки" visible="true" searchable="true" sortable="true"/>
<exchangeExecutionTime type="4" name="Время заключения сделки в Торговой системе" shortname="Время заключения сделки" visible="true" searchable="true" sortable="true"/> <exchangeExecutionTime type="4" name="Время заключения сделки в Торговой системе" shortname="Время заключения сделки" visible="true" searchable="true" sortable="true"/>
<tradingDate type="6" name="Дата заключения сделки" shortname="Дата заключения сделки" visible="true" searchable="true" sortable="true"/> <tradingDate type="6" name="Дата заключения сделки" shortname="Дата заключения сделки" visible="true" searchable="true" sortable="true"/>
@ -1411,11 +1427,11 @@
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/> <sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
</executionFond> </executionFond>
<depoBalanceRegister name="Реестр остатков ценных бумаг" destination="depo-balance-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.DepoBalanceRegister" table="balance_depo_register"> <depoBalanceRegister name="Реестр остатков ценных бумаг" destination="depo-balance-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.DepoBalanceRegister" table="balance_depo_register">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true" ignore="true"/>
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
<companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" visible="true" searchable="true" sortable="true" link="company" linkCode="shortName"/> <companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" visible="true" searchable="true" sortable="true" link="company" linkCode="shortName"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/> <sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session" ignore="true"/>
<depoCode type="2" length="50" name="Код раздела субсчета/счета депо" shortname="Код счета депо" searchable="true" sortable="true"/> <depoCode type="2" length="50" name="Код раздела субсчета/счета депо" shortname="Код счета депо" searchable="true" sortable="true"/>
<quantity type="11" name="Количество" shortname="Количество" searchable="true" sortable="true"/> <quantity type="11" name="Количество" shortname="Количество" searchable="true" sortable="true"/>
<securitySymbol type="2" length="255" name="Код ценной бумаги" shortname="Ценная бумага" searchable="true" sortable="true"/> <securitySymbol type="2" length="255" name="Код ценной бумаги" shortname="Ценная бумага" searchable="true" sortable="true"/>
@ -1423,17 +1439,17 @@
<moneyBalanceRegister name="Реестр остатков денежных средств" destination="money-balance-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.MoneyBalanceRegister" table="money_balance_register"> <moneyBalanceRegister name="Реестр остатков денежных средств" destination="money-balance-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.MoneyBalanceRegister" table="money_balance_register">
<setHouseName type="2" length="255" name="Наименование РО" shortname="Наименование РО" searchable="true" sortable="true" visible="true"/> <setHouseName type="2" length="255" name="Наименование РО" shortname="Наименование РО" searchable="true" sortable="true" visible="true"/>
<account type="2" length="50" name="Номер торгового/клирингового счета" shortname="Номер торгового/клирингового счета" searchable="true" sortable="true" visible="true"/> <account type="2" length="50" name="Номер торгового/клирингового счета" shortname="Номер торгового/клирингового счета" searchable="true" sortable="true" visible="true"/>
<infoAccount type="2" length="50" name="Номер счета внутреннего учета СПВБ" shortname="Номер счета внутреннего учета СПВБ" searchable="true" sortable="true" visible="true"/> <infoAccount type="2" length="50" name="Номер счета внутреннего учета СПВБ" shortname="Номер счета внутреннего учета СПВБ" searchable="true" sortable="true" visible="true" ignore="true"/>
<remainderSum type="10" name="Остаток денежных средств" shortname="Остаток" searchable="true" sortable="true"/> <remainderSum type="10" name="Остаток денежных средств" shortname="Остаток" searchable="true" sortable="true"/>
<blockedSum type="10" name="Сумма блокированных денежных средств" shortname="Блокированные" searchable="true" sortable="true"/> <blockedSum type="10" name="Сумма блокированных денежных средств" shortname="Блокированные" searchable="true" sortable="true" ignore="true"/>
<unblockedSum type="10" name="Сумма свободных денежных средств" shortname="Свободные" searchable="true" sortable="true"/> <unblockedSum type="10" name="Сумма свободных денежных средств" shortname="Свободные" searchable="true" sortable="true" ignore="true"/>
<inn type="2" length="255" name="Идентификационный номер налогоплательщика (ИНН)" shortname="ИНН" searchable="true" sortable="true" visible="true"/> <inn type="2" length="255" name="Идентификационный номер налогоплательщика (ИНН)" shortname="ИНН" searchable="true" sortable="true" visible="true" ignore="true"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/> <sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session" ignore="true"/>
<companyFullName type="2" length="255" name="Полное наименование компании" shortname="Полное наименование компании" searchable="true" sortable="true" visible="true"/> <companyFullName type="2" length="255" name="Полное наименование компании" shortname="Полное наименование компании" searchable="true" sortable="true" visible="true" ignore="true"/>
<companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" searchable="true" sortable="true" visible="true" link="company" linkCode="shortName"/> <companyId type="1" dbname="Идентификатор компании" name="Наименование компании" shortname="Компания" searchable="true" sortable="true" visible="true" link="company" linkCode="shortName"/>
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true" ignore="true"/>
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>
</moneyBalanceRegister> </moneyBalanceRegister>
<admittedLiabilitiesRegister name="Реестр обязательств, допущенных к клирингу" destination="admitted-liabilities-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.AdmittedLiabilitiesRegister" table="admitted_liabilities_register"> <admittedLiabilitiesRegister name="Реестр обязательств, допущенных к клирингу" destination="admitted-liabilities-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.AdmittedLiabilitiesRegister" table="admitted_liabilities_register">
<companyFullName type="2" length="255" name="Полное наименование компании" shortname="Полное наименование компании" searchable="true" sortable="true" visible="true"/> <companyFullName type="2" length="255" name="Полное наименование компании" shortname="Полное наименование компании" searchable="true" sortable="true" visible="true"/>
@ -1487,7 +1503,7 @@
<direction type="1" name="Направление" shortname="Направление" searchable="true" sortable="true" link="inOutDirection" ignore="true"/> <direction type="1" name="Направление" shortname="Направление" searchable="true" sortable="true" link="inOutDirection" ignore="true"/>
<sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/> <sessionId type="1" dbname="Идентификатор клиринговой сессии" name="Клиринговая сессия" shortname="Сессия" visible="true" searchable="true" sortable="true" link="session"/>
</depoPaymentInstructionRegister> </depoPaymentInstructionRegister>
<excludeLiabilitiesRegister name="Реестр обязательств, исключенных из клирингового пула" destination="exclude-liabilities-registers" class="ru.clearing.classes.statics.data.register.ExcludeLiabilitiesRegister" table="exclude_liabilities_register"> <excludeLiabilitiesRegister name="Реестр обязательств, исключенных из клирингового пула" destination="exclude-liabilities-registers" historyDestination="history" class="ru.clearing.classes.statics.data.register.ExcludeLiabilitiesRegister" table="exclude_liabilities_register">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/> <id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true"/>
<createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/> <createdAt field="created" type="4" webtype="5" dbname="Дата-время создания записи" name="Время создания записи" shortname="Создано" searchable="true" sortable="true" ignore="true"/>
<updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/> <updatedAt field="updated" type="4" webtype="5" dbname="Дата-время изменения записи" name="Время изменения записи" shortname="Изменено" searchable="true" sortable="true" ignore="true"/>

View file

@ -43,6 +43,7 @@ DROP TABLE IF EXISTS <xsl:value-of select="$dbTableName"/>;
CREATE TABLE <xsl:value-of select="$dbTableName"/>(<xsl:apply-templates select="*" mode="field"/>); CREATE TABLE <xsl:value-of select="$dbTableName"/>(<xsl:apply-templates select="*" mode="field"/>);
COMMENT ON TABLE <xsl:value-of select="$dbTableName"/> IS '<xsl:value-of select="$dbNameComment"/>'; COMMENT ON TABLE <xsl:value-of select="$dbTableName"/> IS '<xsl:value-of select="$dbNameComment"/>';
<xsl:apply-templates select="*" mode="comment-enums"/> <xsl:apply-templates select="*" mode="comment-enums"/>
GRANT ALL PRIVILEGES ON TABLE <xsl:value-of select="$dbTableName"/> TO clearing;
</xsl:template> </xsl:template>
<xsl:template match="*" mode="objects"> <xsl:template match="*" mode="objects">
@ -53,6 +54,7 @@ DROP TABLE IF EXISTS <xsl:value-of select="$dbTableName"/>;
CREATE TABLE <xsl:value-of select="$dbTableName"/>(<xsl:apply-templates select="*[@name or @dbname or @type]" mode="field"/>); CREATE TABLE <xsl:value-of select="$dbTableName"/>(<xsl:apply-templates select="*[@name or @dbname or @type]" mode="field"/>);
COMMENT ON TABLE <xsl:value-of select="$dbTableName"/> IS '<xsl:value-of select="$dbNameTComment"/>'; COMMENT ON TABLE <xsl:value-of select="$dbTableName"/> IS '<xsl:value-of select="$dbNameTComment"/>';
<xsl:apply-templates select="*[@name or @dbname or @type]" mode="comment-objects"/> <xsl:apply-templates select="*[@name or @dbname or @type]" mode="comment-objects"/>
GRANT ALL PRIVILEGES ON TABLE <xsl:value-of select="$dbTableName"/> TO clearing;
<xsl:if test="@logUpdates"> <xsl:if test="@logUpdates">
-- History log of <xsl:value-of select="name()"/> - <xsl:value-of select="$dbNameTComment"/> -- History log of <xsl:value-of select="name()"/> - <xsl:value-of select="$dbNameTComment"/>
@ -65,6 +67,7 @@ COMMENT ON COLUMN <xsl:value-of select="$dbTableName"/>_HISTORY.EVENT_TIME IS '
COMMENT ON COLUMN <xsl:value-of select="$dbTableName"/>_HISTORY.EVENT_USER_ID IS 'Инициатор изменения'; COMMENT ON COLUMN <xsl:value-of select="$dbTableName"/>_HISTORY.EVENT_USER_ID IS 'Инициатор изменения';
COMMENT ON COLUMN <xsl:value-of select="$dbTableName"/>_HISTORY.EVENT_TYPE IS 'Тип изменения'; COMMENT ON COLUMN <xsl:value-of select="$dbTableName"/>_HISTORY.EVENT_TYPE IS 'Тип изменения';
<xsl:apply-templates select="*[@name or @dbname or @type]" mode="comment-history-objects"/> <xsl:apply-templates select="*[@name or @dbname or @type]" mode="comment-history-objects"/>
GRANT ALL PRIVILEGES ON TABLE <xsl:value-of select="$dbTableName"/>_HISTORY TO clearing;
</xsl:if> </xsl:if>
</xsl:template> </xsl:template>

View file

@ -0,0 +1,68 @@
package ru.spcex.clearing.backendapi.controller.config;
import com.hazelcast.config.*;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
import java.util.List;
import java.util.Random;
@Configuration
public class HazelcastServiceTestConfiguration {
private HazelcastInstance hazelcastInstance;
private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
if (maxPoolSz > 2) {
pool.setKeepAliveSeconds(60);
pool.setAllowCoreThreadTimeOut(true);
}
pool.setCorePoolSize(maxPoolSz);
pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion);
return pool;
}
@Bean(name = "hazelcastServiceTest")
public HazelcastService hazelcastService(@Qualifier("taskExecutorHazelcastClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer, @Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, HazelcastClientParams params) {
Config cfg = new Config();
cfg.setInstanceName("localhost");
NetworkConfig networkConfig = new NetworkConfig();
JoinConfig joinConfig = new JoinConfig();
joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false));
joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(true).setMembers(List.of("127.0.0.1")));
networkConfig.setJoin(joinConfig);
cfg.setNetworkConfig(networkConfig);
hazelcastInstance = Hazelcast.newHazelcastInstance(cfg);
HazelcastHelper.imdgSystem_setStorageState(true, hazelcastInstance);
return new HazelcastService(taskExecutorHazelcastClientInitializer, taskExecutorIdGeneratorAwaiter, params);
}
@Bean(name = "taskExecutorHazelcastClientInitializer")
public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() {
return createThreadPoolTaskExecutor(1, true);
}
@Bean(name = "taskExecutorIdGeneratorAwaiter")
public ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter() {
return createThreadPoolTaskExecutor(1, false);
}
@Bean(name = "hazelcastClientParams")
public HazelcastClientParams getHazelcastClientParams() {
HazelcastClientParams params = new HazelcastClientParams();
params.setLogin("dev");
params.setPassword("dev-pass");
params.setClusterMembers("127.0.0.1");
params.setInstanceName("hzTestClient" + new Random().nextInt());
params.setNearCacheConfig(new NearCacheConfig());
return params;
}
}

View file

@ -9,18 +9,18 @@ import ru.spcex.clearing.backendapi.meta.MetaServer;
import ru.spcex.clearing.backendapi.service.impl.OperatorImpl; import ru.spcex.clearing.backendapi.service.impl.OperatorImpl;
import ru.spcex.clearing.backendapi.service.validation.ActionMetaValidation; import ru.spcex.clearing.backendapi.service.validation.ActionMetaValidation;
import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider; import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
@Configuration @Configuration
public class IOperatorTest { public class IOperatorTest {
@Autowired @Autowired
@Qualifier("hazelcastServiceTest") @Qualifier("hazelcastServiceTest")
private ImdgProvider hazelcastServiceTest; private HazelcastService hazelcastServiceTest;
@Autowired @Autowired
@Bean("iOperatorTest") @Bean("iOperatorTest")
public OperatorImpl createIOperator(@Qualifier("mockProducer") Producer<String, Object> kafka, public OperatorImpl createIOperator(Producer<String, Object> kafka,
ActionMetaValidation actionMetaValidation, ActionValidationProvider validationProvider) { ActionMetaValidation actionMetaValidation, ActionValidationProvider validationProvider) {
return new OperatorImpl(kafka, hazelcastServiceTest, actionMetaValidation, validationProvider); return new OperatorImpl(kafka, hazelcastServiceTest, actionMetaValidation, validationProvider);
} }

View file

@ -0,0 +1,18 @@
package ru.spcex.clearing.backendapi.controller.config;
import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ru.spcex.clearing.platform.messaging.serialization.JsonSerializer;
@Configuration
public class KafkaTestConfig {
@Bean
public Producer<String, Object> createProducer() {
return new MockProducer<>(true, new StringSerializer(), new JsonSerializer());
}
}

View file

@ -1,12 +0,0 @@
package ru.spcex.clearing.backendapi.controller.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import ru.spcex.clearing.backendapi.controller.queue.QueueExceptionHandler;
@Configuration
@ComponentScan(basePackages = {"ru.spcex.clearing.backendapi.controller.queue"},
excludeFilters = @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value = QueueExceptionHandler.class))
public class TestConfig {
}

View file

@ -1,6 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue; package ru.spcex.clearing.backendapi.controller.queue;
import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakPrincipal;
@ -9,9 +9,11 @@ import org.keycloak.adapters.spi.KeycloakAccount;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
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.annotation.Qualifier;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
@ -26,6 +28,23 @@ import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter; import org.springframework.web.filter.CharacterEncodingFilter;
import ru.clearing.classes.statics.data.user.User; import ru.clearing.classes.statics.data.user.User;
import ru.spcex.clearing.backendapi.controller.config.*; import ru.spcex.clearing.backendapi.controller.config.*;
import ru.spcex.clearing.backendapi.controller.queue.account.*;
import ru.spcex.clearing.backendapi.controller.queue.company.*;
import ru.spcex.clearing.backendapi.controller.queue.execution.ExecutionDepositController;
import ru.spcex.clearing.backendapi.controller.queue.execution.ExecutionFondController;
import ru.spcex.clearing.backendapi.controller.queue.journal.InDocumentJournalController;
import ru.spcex.clearing.backendapi.controller.queue.journal.ManagementJournalController;
import ru.spcex.clearing.backendapi.controller.queue.journal.OutDocumentJournalController;
import ru.spcex.clearing.backendapi.controller.queue.misc.*;
import ru.spcex.clearing.backendapi.controller.queue.payment.PaymentInstructionController;
import ru.spcex.clearing.backendapi.controller.queue.register.*;
import ru.spcex.clearing.backendapi.controller.queue.registry.TradingClearingRegistryController;
import ru.spcex.clearing.backendapi.controller.queue.scheduler.*;
import ru.spcex.clearing.backendapi.controller.queue.securities.*;
import ru.spcex.clearing.backendapi.controller.queue.user.UserController;
import ru.spcex.clearing.backendapi.controller.queue.user.UserRoleSessionController;
import ru.spcex.clearing.backendapi.controller.queue.utilities.StatementController;
import ru.spcex.clearing.backendapi.controller.queue.utilities.UserSettingsController;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse; import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse;
import ru.spcex.clearing.backendapi.controller.response.cud.CudResponseTest; import ru.spcex.clearing.backendapi.controller.response.cud.CudResponseTest;
@ -36,12 +55,11 @@ import ru.spcex.clearing.backendapi.meta.GetResponseFactory;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.test.config.ImdgTestConfig; import ru.spcex.clearing.test.TestUtils;
import ru.spcex.clearing.test.config.KafkaTestConfig;
import ru.spcex.clearing.test.json.MatcherFactoryWithJson; import ru.spcex.clearing.test.json.MatcherFactoryWithJson;
import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.SpcexObjectBase;
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.iml.hazelcast.service.HazelcastService;
import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.IMessageResolver;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -53,34 +71,98 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.*;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static ru.spcex.clearing.test.TestUtils.clearImdg;
import static ru.spcex.clearing.test.config.KafkaTestConfig.getCaptor;
import static ru.spcex.clearing.test.config.KafkaTestConfig.setMockFuture;
import static ru.spcex.clearing.test.json.JsonUtil.readValue; import static ru.spcex.clearing.test.json.JsonUtil.readValue;
import static ru.spcex.clearing.test.json.JsonUtil.writeValue; import static ru.spcex.clearing.test.json.JsonUtil.writeValue;
import static ru.spcex.clearing.test.json.MatcherFactoryWithJson.usingIgnoringFieldsComparatorForClass; import static ru.spcex.clearing.test.json.MatcherFactoryWithJson.usingIgnoringFieldsComparatorForClass;
@ContextConfiguration(classes = { @ContextConfiguration(classes = {
TestConfig.class, //account
AccountController.class,
BankAccountController.class,
ClearingAccountController.class,
DepoAccountController.class,
//account misc
ClientCodeController.class,
AccountSymbolsController.class,
//company
CompanyRoleSetController.class,
CompanyController.class,
ClearingMemberCategoryController.class,
CompanyInfoController.class,
CompanySymbolController.class,
ContactController.class,
ProfileDocumentController.class,
RelationController.class,
//execution
ExecutionDepositController.class,
ExecutionFondController.class,
//journal
InDocumentJournalController.class,
ManagementJournalController.class,
OutDocumentJournalController.class,
//liabilities
//misc
CurrencyController.class,
ErrorTextController.class,
ListingController.class,
MarketController.class,
NotificationController.class,
SessionController.class,
//payment
PaymentInstructionController.class,
//register
AdmittedLiabilitiesRegisterController.class,
CoveredLiabilitiesRegisterController.class,
DepoBalanceRegisterController.class,
DepoPaymentInstructionRegisterController.class,
ExcludeLiabilitiesRegisterController.class,
ExecutionRegisterController.class,
LiabilitiesRegisterController.class,
MoneyBalanceRegisterController.class,
ContractRegisterController.class,
ReportRegisterController.class,
//registry
RegistryController.class,
TradingClearingRegistryController.class,
//scheduler
ClearingCalendarController.class,
LauncherController.class,
PlannerAllTodayController.class,
PlannerController.class,
PlannerTemplateController.class,
//securities
MoneyMarketSecurityController.class,
CouponPeriodController.class,
EquitySecurityController.class,
FixedIncomeCashFlowController.class,
FixedIncomeSecurityController.class,
InformationAccountController.class,
SecurityController.class,
//user
UserController.class,
UserRoleSessionController.class,
//utilities
StatementController.class,
UserSettingsController.class,
//******* common configs *******
WebTestConfig.class, WebTestConfig.class,
IOperatorTest.class, IOperatorTest.class,
ImdgTestConfig.class, HazelcastServiceTestConfiguration.class,
KafkaTestConfig.class,
StateLoaderImplTestConfig.class, StateLoaderImplTestConfig.class,
WebSecurityTestConfigurer.class, WebSecurityTestConfigurer.class,
MessagesTestConfig.class, MessagesTestConfig.class,
Jackson2HttpConverterTestConfig.class}) Jackson2HttpConverterTestConfig.class})
//todo может быть указать пакедж а не список контроллеров
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@WebMvcTest @WebMvcTest
//@TestPropertySource(properties = "spring.config.location=D:/repo/mfd/clearing/clearing-parent/backend-api/src/main/resources/") //@TestPropertySource(properties = "spring.config.location=D:/repo/mfd/clearing/clearing-parent/backend-api/src/main/resources/")
public abstract class AbstractControllerTest { public abstract class AbstractControllerTest {
protected static final MatcherFactoryWithJson.Matcher<BaseRequest> BASE_REQUEST_MATCHER = usingIgnoringFieldsComparatorForClass(BaseRequest.class, "userId"); protected static final MatcherFactoryWithJson.Matcher<BaseRequest> BASE_REQUEST_MATCHER = usingIgnoringFieldsComparatorForClass(BaseRequest.class,"userId");
protected static final MatcherFactoryWithJson.Matcher<CudResponse> CUD_RESPONSE_MATCHER = usingIgnoringFieldsComparatorForClass(CudResponse.class); protected static final MatcherFactoryWithJson.Matcher<CudResponse> CUD_RESPONSE_MATCHER = usingIgnoringFieldsComparatorForClass(CudResponse.class);
protected static final AtomicLong currentId = new AtomicLong(); protected static final AtomicLong currentId = new AtomicLong();
private static final CharacterEncodingFilter CHARACTER_ENCODING_FILTER = new CharacterEncodingFilter(); private static final CharacterEncodingFilter CHARACTER_ENCODING_FILTER = new CharacterEncodingFilter();
@ -100,16 +182,15 @@ public abstract class AbstractControllerTest {
@Autowired @Autowired
@Qualifier("hazelcastServiceTest") @Qualifier("hazelcastServiceTest")
protected ImdgProvider hazelcastServiceTest; protected HazelcastService hazelcastServiceTest;
@Autowired @Autowired
@Qualifier("responseFactoryTest") @Qualifier("responseFactoryTest")
protected GetResponseFactory responseFactory; protected GetResponseFactory responseFactory;
@Captor
@Autowired protected ArgumentCaptor<ProducerRecord> producerRecord;
@Qualifier("mockProducer") @MockBean
protected Producer<String, Object> producer; protected MockProducer<String, Object> producer;
protected Imdg<User> userImdg; protected Imdg<User> userImdg;
@Autowired @Autowired
private WebApplicationContext webApplicationContext; private WebApplicationContext webApplicationContext;
@ -122,6 +203,8 @@ public abstract class AbstractControllerTest {
.addFilter(CHARACTER_ENCODING_FILTER) .addFilter(CHARACTER_ENCODING_FILTER)
// .apply(springSecurity()) // .apply(springSecurity())
.build(); .build();
TestUtils.FutureRecordMetadata future = spy(TestUtils.FutureRecordMetadata.class);
doReturn(future).when(producer).send(producerRecord.capture());
userImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_User, User.class); userImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_User, User.class);
} }
@ -133,7 +216,6 @@ public abstract class AbstractControllerTest {
BaseRequest<Object> predictableBaseRequest = new BaseRequest<>(); BaseRequest<Object> predictableBaseRequest = new BaseRequest<>();
predictableBaseRequest.setActionType(action.getActionType()); predictableBaseRequest.setActionType(action.getActionType());
predictableBaseRequest.setRequestPayload(action.toRequest()); predictableBaseRequest.setRequestPayload(action.toRequest());
ArgumentCaptor<ProducerRecord> producerRecord = getCaptor(producer);
assertEquals(topic, producerRecord.getValue().topic()); assertEquals(topic, producerRecord.getValue().topic());
BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value(); BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value();
predictableBaseRequest.setId(baseRequestResult.getId()); predictableBaseRequest.setId(baseRequestResult.getId());
@ -141,7 +223,6 @@ public abstract class AbstractControllerTest {
} }
protected void checkAddingByRestApi(String REST_URL, IAction action) throws Exception { protected void checkAddingByRestApi(String REST_URL, IAction action) throws Exception {
setMockFuture(producer);
CudResponse expected = new CudResponse(); CudResponse expected = new CudResponse();
expected.setCode(0L); expected.setCode(0L);
expected.setMessage("success"); expected.setMessage("success");
@ -161,7 +242,6 @@ public abstract class AbstractControllerTest {
} }
protected void checkUpdatingByRestApi(String REST_URL, IAction action, Long existsId) throws Exception { protected void checkUpdatingByRestApi(String REST_URL, IAction action, Long existsId) throws Exception {
setMockFuture(producer);
CudResponse expected = new CudResponse(); CudResponse expected = new CudResponse();
expected.setCode(0L); expected.setCode(0L);
expected.setMessage("success"); expected.setMessage("success");
@ -190,7 +270,6 @@ public abstract class AbstractControllerTest {
} }
protected void checkUpdatingWithoutIdByRestApi(String REST_URL, IAction action) throws Exception { protected void checkUpdatingWithoutIdByRestApi(String REST_URL, IAction action) throws Exception {
setMockFuture(producer);
CudResponse expected = new CudResponse(); CudResponse expected = new CudResponse();
expected.setCode(0L); expected.setCode(0L);
expected.setMessage("success"); expected.setMessage("success");
@ -212,7 +291,6 @@ public abstract class AbstractControllerTest {
} }
protected void checkDeletingByRestApi(String REST_URL, Long existsId) throws Exception { protected void checkDeletingByRestApi(String REST_URL, Long existsId) throws Exception {
setMockFuture(producer);
CudResponse expected = new CudResponse(); CudResponse expected = new CudResponse();
expected.setCode(0L); expected.setCode(0L);
expected.setMessage("success"); expected.setMessage("success");
@ -234,7 +312,6 @@ public abstract class AbstractControllerTest {
} }
protected <T extends SpcexObjectBase> void checkDeletingWithIdVolidationByRestApi(String imdgDistributedNames, T existsObj, String REST_URL, Long existsId) throws Exception { protected <T extends SpcexObjectBase> void checkDeletingWithIdVolidationByRestApi(String imdgDistributedNames, T existsObj, String REST_URL, Long existsId) throws Exception {
setMockFuture(producer);
Class<T> clazz = (Class<T>) existsObj.getClass(); Class<T> clazz = (Class<T>) existsObj.getClass();
Imdg<T> inDocumentJournalImdg = hazelcastServiceTest.getImdg(imdgDistributedNames, clazz); Imdg<T> inDocumentJournalImdg = hazelcastServiceTest.getImdg(imdgDistributedNames, clazz);
inDocumentJournalImdg.insert(existsObj); inDocumentJournalImdg.insert(existsObj);
@ -242,10 +319,9 @@ public abstract class AbstractControllerTest {
} }
protected <T extends SpcexObjectBase> void checkGettingAllFromRestApi(String imdgDistributedNames, T existsObj, String restUrl) throws Exception { protected <T extends SpcexObjectBase> void checkGettingAllFromRestApi(String imdgDistributedNames, T existsObj, String restUrl) throws Exception {
setMockFuture(producer);
Class<T> clazz = (Class<T>) existsObj.getClass(); Class<T> clazz = (Class<T>) existsObj.getClass();
Imdg<T> testingImdg = hazelcastServiceTest.getImdg(imdgDistributedNames, clazz); Imdg<T> testingImdg = hazelcastServiceTest.getImdg(imdgDistributedNames, clazz);
clearImdg(testingImdg); // ((ImdgHazelcast<T>)testingImdg).clear(); // предварительная очистка
testingImdg.insert(existsObj); testingImdg.insert(existsObj);
Collection<T> values = testingImdg.getAllValues(); Collection<T> values = testingImdg.getAllValues();

View file

@ -0,0 +1,66 @@
package ru.spcex.clearing.backendapi.controller.queue.account;
import org.junit.jupiter.api.Test;
import ru.clearing.classes.statics.data.account.AccountSymbols;
import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.backendapi.controller.request.cud.account.AccountSymbolsNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.Consts;
class AccountSymbolsControllerTest extends AbstractControllerTest {
private static final String REST_URL = "/accounting/depo-accounts-symbols/";
/**
* {@link AccountSymbolsController#add(AccountSymbolsNewAction)}<br>
* Тест проверяет получение сущности {@link AccountSymbolsNewAction} по REST API и отправку в Apache Kafka.<br>
* Входной запрос {@link AccountSymbolsNewAction}: {111L, "VALUE-1234"}
*/
@Test
void add() throws Exception {
//ARRANGE
AccountSymbolsNewAction accountSymbolsNewAction = new AccountSymbolsNewAction();
accountSymbolsNewAction.setAccountId(111L);
accountSymbolsNewAction.setAccountSymbolValue("VALUE-1234");
//ACT and ASSERT
checkAddingByRestApi(REST_URL, accountSymbolsNewAction);
checkSendedMessegeFromKafka(Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_NEW, accountSymbolsNewAction);
}
/**
* {@link AccountSymbolsController#delete(Long)} <br>
* Тест проверяет получение id сущности {@link Long} по REST API и отправку в Apache Kafka.<br>
* Входной запрос /accounting/depo-accounts-symbols/{@link Long}: - 0L<br>
*/
@Test
void delete() throws Exception {
//ARRANGE
long id = currentId.getAndIncrement();
CommonDeleteAction deleteAction = new CommonDeleteAction();
deleteAction.setId(id);
//ACT and ASSERT
checkDeletingByRestApi(REST_URL, id);
checkSendedMessegeFromKafka(Consts.DESTINATION_DEPO_ACCOUNT_SYMBOLS_DELETE, deleteAction);
}
/**
* {@link ClientCodeController#getAll()} <br>
* Тест проверяет получение запроса по REST API и отправку всех записей из таблицы hazelcast Map_ClientCode.<br>
* Входной запрос /client-codes/ <br>
* Ответ CommonGetAllResponse <br>
*/
@Test
void getAll() throws Exception {
//ARRANGE
AccountSymbols existAccountSymbols = new AccountSymbols();
existAccountSymbols.setAccountId(111L);
existAccountSymbols.setAccountSymbolValue("AAABBBVVCD");
existAccountSymbols.setId(currentId.get());
//ACT and ASSERT
checkGettingAllFromRestApi(IMDGDistributedNames.Map_AccountSymbols, existAccountSymbols, REST_URL);
}
}

View file

@ -9,6 +9,7 @@ import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction; import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction; import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountUpdateAction;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetByIdResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetByIdResponse;
import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.errors.ActionValidationException; import ru.spcex.clearing.backendapi.errors.ActionValidationException;
@ -78,10 +79,15 @@ class BankAccountControllerTest extends AbstractControllerTest {
*/ */
@Test @Test
void addWithException() { void addWithException() {
assertThrowsFor(getBankAccountNewAction(0, null, "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "01", "11111222223333344444")); assertThrowsFor(getBankAccountNewAction(0, "", "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", null, "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "01", "11111222223333344444")); assertThrowsFor(getBankAccountNewAction(0, "044525776", "", "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", null, "destination", "3664011397", "01", "11111222223333344444")); assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "", "correspondent", "RUB", "destination", "3664011397", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "01", null)); assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "", "RUB", "destination", "3664011397", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", "", "destination", "3664011397", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "", "3664011397", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "destination", "", "01", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "", "11111222223333344444"));
assertThrowsFor(getBankAccountNewAction(0, "044525776", "Beta Money Bank", "30101111111111111776", "correspondent", "RUB", "destination", "3664011397", "01", ""));
} }
/** /**

View file

@ -13,7 +13,6 @@ import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.errors.ActionValidationException; import ru.spcex.clearing.backendapi.errors.ActionValidationException;
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.ClientCodeNewRequest;
import java.time.Instant; import java.time.Instant;
@ -61,6 +60,7 @@ class ClientCodeControllerTest extends AbstractControllerTest {
*/ */
@Test @Test
void addWithException() { void addWithException() {
assertThrowsFor(getClientCodeNewAction(0, "", "ACTV", 1000L, 1010L, 1020L, 1030L));
assertThrowsFor(getClientCodeNewAction(0, null, "ACTV", 1000L, 1010L, 1020L, 1030L)); assertThrowsFor(getClientCodeNewAction(0, null, "ACTV", 1000L, 1010L, 1020L, 1030L));
assertThrowsFor(getClientCodeNewAction(0, "044525776", "ACTV", null, 1010L, 1020L, 1030L)); assertThrowsFor(getClientCodeNewAction(0, "044525776", "ACTV", null, 1010L, 1020L, 1030L));
} }
@ -148,7 +148,7 @@ class ClientCodeControllerTest extends AbstractControllerTest {
private ClientCodeNewAction getClientCodeNewAction(long id, private ClientCodeNewAction getClientCodeNewAction(long id,
String code, String status, Long companyId, Long depoAccountId, String code, String status, Long companyId, Long depoAccountId,
Long moneyAccountId, Long tradingClearingRegistryId) { Long moneyAccountId, Long tradingClearingRegistryId ) {
ClientCodeNewAction clientCodeNewAction = new ClientCodeNewAction(); ClientCodeNewAction clientCodeNewAction = new ClientCodeNewAction();
clientCodeNewAction.setCode(code); clientCodeNewAction.setCode(code);
clientCodeNewAction.setCompanyId(companyId); clientCodeNewAction.setCompanyId(companyId);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue.misc; package ru.spcex.clearing.backendapi.controller.queue.misc;
import com.hazelcast.core.IMap;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -7,8 +8,8 @@ import ru.clearing.classes.statics.data.misc.Notification;
import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest; import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.imdg.api.Imdg;
import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
@ -39,10 +40,10 @@ class NotificationControllerTest extends AbstractControllerTest {
profileDocument.setNotificationStatus("Status"); profileDocument.setNotificationStatus("Status");
profileDocument.setId(currentId.get()); profileDocument.setId(currentId.get());
Imdg<Notification> iMap = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Notification, Notification.class); IMap<Long, Notification> iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_Notification);
iMap.insert(profileDocument); iMap.put(profileDocument.getId(), profileDocument);
Collection<Notification> values = iMap.getAllValues(); Collection<Notification> values = iMap.values();
Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values); Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values);
CommonGetAllResponse expected = new CommonGetAllResponse(); CommonGetAllResponse expected = new CommonGetAllResponse();
expected.fromEntity(all); expected.fromEntity(all);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue.misc; package ru.spcex.clearing.backendapi.controller.queue.misc;
import com.hazelcast.core.IMap;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -7,7 +8,6 @@ import ru.clearing.classes.statics.data.misc.Session;
import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest; import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.imdg.api.Imdg;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Collection; import java.util.Collection;
@ -35,10 +35,10 @@ class SessionControllerTest extends AbstractControllerTest {
session.setSessionStatus("Ok"); session.setSessionStatus("Ok");
session.setId(currentId.get()); session.setId(currentId.get());
Imdg<Session> sessionImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Session, Session.class); IMap<Long, Session> iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_Session);
sessionImdg.insert(session); iMap.put(session.getId(), session);
Collection<Session> values = sessionImdg.getAllValues(); Collection<Session> values = iMap.values();
Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values); Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values);
CommonGetAllResponse expected = new CommonGetAllResponse(); CommonGetAllResponse expected = new CommonGetAllResponse();
expected.fromEntity(all); expected.fromEntity(all);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue.payment; package ru.spcex.clearing.backendapi.controller.queue.payment;
import com.hazelcast.core.IMap;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -9,7 +10,6 @@ import ru.spcex.clearing.backendapi.controller.request.cud.payment.PIClearingOut
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
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.platform.imdg.api.Imdg;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
@ -65,10 +65,10 @@ class PaymentInstructionControllerTest extends AbstractControllerTest {
paymentInstruction.setSessionId(555L); paymentInstruction.setSessionId(555L);
paymentInstruction.setId(currentId.get()); paymentInstruction.setId(currentId.get());
Imdg<PaymentInstruction> paymentInstructionImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); IMap<Long, PaymentInstruction> iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_PaymentInstruction);
paymentInstructionImdg.insert(paymentInstruction); iMap.put(paymentInstruction.getId(), paymentInstruction);
Collection<PaymentInstruction> values = paymentInstructionImdg.getAllValues(); Collection<PaymentInstruction> values = iMap.values();
Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values); Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values);
CommonGetAllResponse expected = new CommonGetAllResponse(); CommonGetAllResponse expected = new CommonGetAllResponse();
expected.fromEntity(all); expected.fromEntity(all);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue.scheduler; package ru.spcex.clearing.backendapi.controller.queue.scheduler;
import com.hazelcast.core.IMap;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
@ -28,7 +29,6 @@ import java.util.Map;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static ru.spcex.clearing.test.config.KafkaTestConfig.setMockFuture;
import static ru.spcex.clearing.test.json.JsonUtil.readValue; import static ru.spcex.clearing.test.json.JsonUtil.readValue;
import static ru.spcex.clearing.test.json.JsonUtil.writeValue; import static ru.spcex.clearing.test.json.JsonUtil.writeValue;
@ -52,10 +52,10 @@ class LauncherControllerTest extends AbstractControllerTest {
taskRunner.setSenderId(10210L); taskRunner.setSenderId(10210L);
taskRunner.setId(currentId.get()); taskRunner.setId(currentId.get());
Imdg<Launcher> iMap = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Launcher, Launcher.class); IMap<Long, Launcher> iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_Launcher);
iMap.insert(taskRunner); iMap.put(taskRunner.getId(), taskRunner);
Collection<Launcher> values = iMap.getAllValues(); Collection<Launcher> values = iMap.values();
Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values); Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values);
CommonGetAllResponse expected = new CommonGetAllResponse(); CommonGetAllResponse expected = new CommonGetAllResponse();
expected.fromEntity(all); expected.fromEntity(all);
@ -76,7 +76,6 @@ class LauncherControllerTest extends AbstractControllerTest {
@Test @Test
void add() throws Exception { void add() throws Exception {
//ARRANGE //ARRANGE
setMockFuture(producer);
TaskDictionary taskDictionary = new TaskDictionary(); TaskDictionary taskDictionary = new TaskDictionary();
taskDictionary.setCode(CODE); taskDictionary.setCode(CODE);
taskDictionary.setId(ID); taskDictionary.setId(ID);
@ -136,7 +135,6 @@ class LauncherControllerTest extends AbstractControllerTest {
@Test @Test
void addSpecific() throws Exception { void addSpecific() throws Exception {
//ARRANGE //ARRANGE
setMockFuture(producer);
LauncherNew launcherCommand = new LauncherNew(); LauncherNew launcherCommand = new LauncherNew();
launcherCommand.setTask(START_OF_CLEARING); launcherCommand.setTask(START_OF_CLEARING);
launcherCommand.setUserId(ID); launcherCommand.setUserId(ID);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue.scheduler; package ru.spcex.clearing.backendapi.controller.queue.scheduler;
import com.hazelcast.core.IMap;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -7,7 +8,6 @@ import ru.clearing.classes.statics.data.scheduler.PlannerAllToday;
import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest; import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.imdg.api.Imdg;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime; import java.time.LocalTime;
@ -42,10 +42,10 @@ class PlannerAllTodayControllerTest extends AbstractControllerTest {
schedulerAllToday.setParentId(1010L); schedulerAllToday.setParentId(1010L);
schedulerAllToday.setId(currentId.get()); schedulerAllToday.setId(currentId.get());
Imdg<PlannerAllToday> plannerAllTodayImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_PlannerAllToday, PlannerAllToday.class); IMap<Long, PlannerAllToday> iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_PlannerAllToday);
plannerAllTodayImdg.insert(schedulerAllToday); iMap.put(schedulerAllToday.getId(), schedulerAllToday);
Collection<PlannerAllToday> values = plannerAllTodayImdg.getAllValues(); Collection<PlannerAllToday> values = iMap.values();
Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values); Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values);
CommonGetAllResponse expected = new CommonGetAllResponse(); CommonGetAllResponse expected = new CommonGetAllResponse();
expected.fromEntity(all); expected.fromEntity(all);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.backendapi.controller.queue.scheduler; package ru.spcex.clearing.backendapi.controller.queue.scheduler;
import com.hazelcast.core.IMap;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -7,7 +8,6 @@ import ru.clearing.classes.statics.data.scheduler.Planner;
import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest; import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.imdg.api.Imdg;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalTime; import java.time.LocalTime;
@ -40,10 +40,10 @@ class PlannerControllerTest extends AbstractControllerTest {
scheduler.setSecurityId(10210L); scheduler.setSecurityId(10210L);
scheduler.setId(currentId.get()); scheduler.setId(currentId.get());
Imdg<Planner> plannerImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Planner, Planner.class); IMap<Long, Planner> iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_Planner);
plannerImdg.insert(scheduler); iMap.put(scheduler.getId(), scheduler);
Collection<Planner> values = plannerImdg.getAllValues(); Collection<Planner> values = iMap.values();
Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values); Collection<Map<String, Object>> all = responseFactory.responseFromObjectCollection(values);
CommonGetAllResponse expected = new CommonGetAllResponse(); CommonGetAllResponse expected = new CommonGetAllResponse();
expected.fromEntity(all); expected.fromEntity(all);

View file

@ -1,9 +1,7 @@
package ru.spcex.clearing.backendapi.controller.queue.securities; package ru.spcex.clearing.backendapi.controller.queue.securities;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity; import ru.clearing.classes.statics.data.security.Security;
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
import ru.clearing.classes.statics.data.security.MoneyMarketSecurity;
import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest; import ru.spcex.clearing.backendapi.controller.queue.AbstractControllerTest;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
@ -19,7 +17,7 @@ class SecurityControllerTest extends AbstractControllerTest {
@Test @Test
void getAll() throws Exception { void getAll() throws Exception {
//ARRANGE //ARRANGE
MoneyMarketSecurity security = new MoneyMarketSecurity(); Security security = new Security();
security.setId(currentId.get()); security.setId(currentId.get());
security.setInstrumentType("name"); security.setInstrumentType("name");
security.setIssuerId(currentId.get()); security.setIssuerId(currentId.get());
@ -29,9 +27,7 @@ class SecurityControllerTest extends AbstractControllerTest {
security.setFullNameEng("name"); security.setFullNameEng("name");
security.setSecuritySymbol("name"); security.setSecuritySymbol("name");
security.setWorkflowStatus("name"); security.setWorkflowStatus("name");
clearAll(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class); clearAll(IMDGDistributedNames.Map_MoneyMarketSecurity, Security.class);
clearAll(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class);
clearAll(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class);
//ACT and ASSERT //ACT and ASSERT
checkGettingAllFromRestApi(IMDGDistributedNames.Map_MoneyMarketSecurity, security, REST_URL); checkGettingAllFromRestApi(IMDGDistributedNames.Map_MoneyMarketSecurity, security, REST_URL);

View file

@ -19,13 +19,9 @@ class UserSettingsControllerTest extends AbstractControllerTest {
@Test @Test
void getAll() throws Exception { void getAll() throws Exception {
//ARRANGE //ARRANGE
Long id = currentId.getAndIncrement();
String identifier = "usersIdentifier";
setUserNameInMockSecurityContextAndMapUser(identifier, id);
UserSettings userSettings = new UserSettings(); UserSettings userSettings = new UserSettings();
userSettings.setId(id); userSettings.setId(currentId.get());
userSettings.setUserId(id); // отдаются по userId CLS-64, todo в тесте null userSettings.setUserId(currentId.get()); // отдаются по userId CLS-64, todo в тесте null
userSettings.setJson("json"); userSettings.setJson("json");
userSettings.setVersion("version"); userSettings.setVersion("version");

View file

@ -7,10 +7,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import ru.clearing.classes.statics.data.profile.CompanyInfo;
import java.util.*; import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@ -18,9 +16,6 @@ import java.util.stream.Collectors;
public class GetResponseFactoryTest { public class GetResponseFactoryTest {
private final MetaServer meta; private final MetaServer meta;
private final Map<Class, List<String>> nonCheckerFields = Map.of(
CompanyInfo.class, List.of("shortName", "fullName", "tradingCode", "clearingCode", "registrationCode", "workflowStatus")
);
@Autowired @Autowired
public GetResponseFactoryTest(@Qualifier("metaJsonTest") MetaServer meta) { public GetResponseFactoryTest(@Qualifier("metaJsonTest") MetaServer meta) {
this.meta = meta; this.meta = meta;
@ -38,8 +33,6 @@ public class GetResponseFactoryTest {
if (className == null) { if (className == null) {
error.computeIfAbsent(ent.getKey(), v -> new ArrayList<>()).add(ent.getKey() + " no class property"); error.computeIfAbsent(ent.getKey(), v -> new ArrayList<>()).add(ent.getKey() + " no class property");
continue; continue;
} else if (ent.getKey().equals("dbVersion")) {
continue;
} }
try { try {
classByName = Class.forName(className); classByName = Class.forName(className);
@ -49,16 +42,8 @@ public class GetResponseFactoryTest {
} }
Object object = classByName.newInstance(); Object object = classByName.newInstance();
ObjectExtracted objectExtracted = meta.getObjectsExtractedByClazz().get(className); ObjectExtracted objectExtracted = meta.getObjectsExtractedByClazz().get(className);
BiFunction<Class, FieldExtracted, Boolean> fieldNonChecked = (clazz, fieldExtracted) -> {
List<String> fields = nonCheckerFields.get(clazz);
if (fields == null) return false;
return fields.contains(fieldExtracted.getMemberName());
};
for (FieldExtracted fieldExtracted : objectExtracted.getFields()) { for (FieldExtracted fieldExtracted : objectExtracted.getFields()) {
try { try {
if(fieldNonChecked.apply(classByName, fieldExtracted)) continue;
fieldExtracted.extractValue(object); fieldExtracted.extractValue(object);
} catch (Exception e) { } catch (Exception e) {
error.computeIfAbsent(ent.getKey(), v -> new ArrayList<>()).add( error.computeIfAbsent(ent.getKey(), v -> new ArrayList<>()).add(

View file

@ -8,12 +8,15 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction; import ru.spcex.clearing.backendapi.controller.request.cud.account.BankAccountNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction;
import ru.spcex.clearing.backendapi.controller.request.cud.company.ListingNewAction;
import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.meta.GetResponseFactoryTestConfiguration; import ru.spcex.clearing.backendapi.meta.GetResponseFactoryTestConfiguration;
import ru.spcex.clearing.backendapi.meta.MetaServer; import ru.spcex.clearing.backendapi.meta.MetaServer;
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.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -30,6 +33,12 @@ class ActionMetaValidationTest {
ActionMetaValidation metaValidator = new ActionMetaValidation(meta); ActionMetaValidation metaValidator = new ActionMetaValidation(meta);
metaValidator.afterPropertiesSet(); metaValidator.afterPropertiesSet();
{
IAction<?> action = new ListingNewAction();
assertTrue(action.validate().isEmpty());
IValidator v = metaValidator.getValidator(null, action);
assertNull(v, "Пока не прописан в мете");
}
{ {
IAction<?> action = new CommonDeleteAction(); IAction<?> action = new CommonDeleteAction();
assertFalse(action.validate().isEmpty()); // стандартный валидатор - требуется id assertFalse(action.validate().isEmpty()); // стандартный валидатор - требуется id

View file

@ -1,6 +1,6 @@
{ {
"version": "3.8.0.58", "version": "3.9.0.71",
"enums": { "enums": {
@ -3328,11 +3328,11 @@
"type": 3,"name": "Номер купона","shortname": "Номер","searchable": true,"sortable": true,"visible": true "type": 3,"name": "Номер купона","shortname": "Номер","searchable": true,"sortable": true,"visible": true
} }
, ,
{"code": "periodEndDate", {"code": "periodStartDate",
"type": 6,"name": "Начало периода действия","shortname": "Начало","searchable": true,"sortable": true,"visible": true "type": 6,"name": "Начало периода действия","shortname": "Начало","searchable": true,"sortable": true,"visible": true
} }
, ,
{"code": "periodStartDate", {"code": "periodEndDate",
"type": 6,"name": "Окончание периода действия","shortname": "Окончание","searchable": true,"sortable": true,"visible": true "type": 6,"name": "Окончание периода действия","shortname": "Окончание","searchable": true,"sortable": true,"visible": true
} }
, ,
@ -4132,6 +4132,10 @@
{"code": "balance", {"code": "balance",
"type": 10,"name": "Сумма","shortname": "Сумма","required": true "type": 10,"name": "Сумма","shortname": "Сумма","required": true
} }
,
{"code": "companyId",
"type": 1,"name": "Наименование компании","shortname": "Компания","link": "company","linkCode": "shortName","required": true
}
, ,
{"code": "tradingClearingRegistryId", {"code": "tradingClearingRegistryId",
"type": 1,"name": "Торгово-клиринговый регистр","shortname": "Торгово-клиринговый регистр","link": "tradingClearingRegistry","linkCode": "code","required": true "type": 1,"name": "Торгово-клиринговый регистр","shortname": "Торгово-клиринговый регистр","link": "tradingClearingRegistry","linkCode": "code","required": true
@ -4664,6 +4668,66 @@
} }
] ]
}
,
"accountSymbols": {
"name": "Депо КС - РДЦ",
"destination": "accounting/depo-accounts-symbols",
"class": "ru.clearing.classes.statics.data.account.AccountSymbols",
"logUpdates": "true",
"table": "depo_account_symbols",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true
}
,
{"code": "accountId",
"type": 1,"dbname": "Идентификатор счета","name": "Счет депо КС","shortname": "Счет депо КС","searchable": true,"sortable": true,"visible": true,"link": "account","linkCode": "account"
}
,
{"code": "accountSymbolValue",
"type": 2,"length": 255,"name": "Счет РДЦ","shortname": "Счет РДЦ","searchable": true,"sortable": true,"visible": true
}
]
,"actions":[
{"method":"post",
"name": "Добавление депо КС - РДЦ",
"confirmation": "accountId,accountSymbolValue",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.account.AccountSymbolsNewAction",
"fields": [
{"code": "accountId",
"type": 1,"dbname": "Идентификатор счета","name": "Счет депо КС","shortname": "Счет депо КС","link": "account","linkCode": "account","required": true
}
,
{"code": "accountSymbolValue",
"type": 2,"length": 255,"name": "Счет РДЦ","shortname": "Счет РДЦ","required": true
}
]
}
,
{"method":"delete",
"name": "Удаление депо КС - РДЦ",
"confirmation": "accountId,accountSymbolValue",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "account","linkCode": "id","required": true
}
]
}
]
} }
, ,
"clearingAccount": { "clearingAccount": {
@ -5270,11 +5334,15 @@
"group": "Обмен с расчетной организацией", "group": "Обмен с расчетной организацией",
"name": "Вывод свободных средств инициаторов В (отправка ДФ-54 для получения ответа ДФ-55)", "name": "Вывод свободных средств с клирингового регистра (отправка ДФ-54 для получения ответа ДФ-55)",
"fields": [ "fields": [
{"code": "fullBalance",
"type": 10,"name": "Текущий баланс (всего)","shortname": "Текущие средства (всего)","enabled": false
}
,
{"code": "balance", {"code": "balance",
"type": 10,"name": "Текущий баланс","shortname": "Текущие средства","enabled": false "type": 10,"name": "Текущий баланс (свободно)","shortname": "Текущие средства (свободно)","enabled": false
} }
, ,
{"code": "securitySymbol", {"code": "securitySymbol",
@ -5290,7 +5358,7 @@
} }
, ,
{"code": "senderId", {"code": "senderId",
"type": 1,"group": "Отправитель","name": "Участник отправитель","shortname": "Отправитель","link": "company","linkCode": "shortName","required": true,"enabled": false "type": 1,"group": "Отправитель","name": "Участник отправитель","shortname": "Отправитель","link": "company","linkCode": "shortName","required": true
} }
, ,
{"code": "creditLeg_accountId", {"code": "creditLeg_accountId",
@ -5509,6 +5577,28 @@
"name": "Формирование ДФ-05 с кодом 9 (финальный)", "name": "Формирование ДФ-05 с кодом 9 (финальный)",
"fields": []
}
,
{"method":"post",
"destination": "CHDF",
"group": "Общее",
"name": "Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21",
"fields": []
}
,
{"method":"post",
"destination": "CCLR",
"group": "Клиринг",
"name": "Завершение неудачных клиринговых сессий",
"fields": [] "fields": []
} }
] ]
@ -5544,7 +5634,7 @@
} }
, ,
{"code": "sessionStatus", {"code": "sessionStatus",
"type": 12,"dbname": "Код статуса клиринговой сессии","name": "Статус клиринговой сессии","shortname": "Статус","searchable": true,"sortable": true,"visible": true,"link": "sessionStatus" "type": 12,"dbname": "Код статуса клиринговой сессии","name": "Статус клиринговой сессии","shortname": "Шаг","searchable": true,"sortable": true,"visible": true,"link": "sessionStatus"
} }
, ,
{"code": "companyId", {"code": "companyId",
@ -5776,10 +5866,12 @@
, ,
"executionDeposit": { "executionDeposit": {
"name": "Сделки", "name": "Сделки на секции МКР",
"destination": "execution-deposits", "destination": "execution-deposits",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.execution.ExecutionDeposit", "class": "ru.clearing.classes.statics.data.execution.ExecutionDeposit",
"logUpdates": "true", "logUpdates": "true",
@ -5932,6 +6024,8 @@
"destination": "execution-fonds", "destination": "execution-fonds",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.execution.ExecutionFond", "class": "ru.clearing.classes.statics.data.execution.ExecutionFond",
"logUpdates": "true", "logUpdates": "true",
@ -6080,17 +6174,19 @@
"destination": "depo-balance-registers", "destination": "depo-balance-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.DepoBalanceRegister", "class": "ru.clearing.classes.statics.data.register.DepoBalanceRegister",
"table": "balance_depo_register", "table": "balance_depo_register",
"fields": [ "fields": [
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true "type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "createdAt", {"code": "createdAt",
"field": "created","type": 4,"webtype": "5","dbname": "Дата-время создания записи","name": "Время создания записи","shortname": "Создано","searchable": true,"sortable": true,"ignore": true "field": "created","type": 4,"webtype": "5","dbname": "Дата-время создания записи","name": "Время создания записи","shortname": "Создано","searchable": true,"sortable": true
} }
, ,
{"code": "updatedAt", {"code": "updatedAt",
@ -6102,7 +6198,7 @@
} }
, ,
{"code": "sessionId", {"code": "sessionId",
"type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session" "type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session","ignore": true
} }
, ,
{"code": "depoCode", {"code": "depoCode",
@ -6126,6 +6222,8 @@
"destination": "money-balance-registers", "destination": "money-balance-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.MoneyBalanceRegister", "class": "ru.clearing.classes.statics.data.register.MoneyBalanceRegister",
"table": "money_balance_register", "table": "money_balance_register",
@ -6140,7 +6238,7 @@
} }
, ,
{"code": "infoAccount", {"code": "infoAccount",
"type": 2,"length": 50,"name": "Номер счета внутреннего учета СПВБ","shortname": "Номер счета внутреннего учета СПВБ","searchable": true,"sortable": true,"visible": true "type": 2,"length": 50,"name": "Номер счета внутреннего учета СПВБ","shortname": "Номер счета внутреннего учета СПВБ","searchable": true,"sortable": true,"visible": true,"ignore": true
} }
, ,
{"code": "remainderSum", {"code": "remainderSum",
@ -6148,23 +6246,23 @@
} }
, ,
{"code": "blockedSum", {"code": "blockedSum",
"type": 10,"name": "Сумма блокированных денежных средств","shortname": "Блокированные","searchable": true,"sortable": true "type": 10,"name": "Сумма блокированных денежных средств","shortname": "Блокированные","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "unblockedSum", {"code": "unblockedSum",
"type": 10,"name": "Сумма свободных денежных средств","shortname": "Свободные","searchable": true,"sortable": true "type": 10,"name": "Сумма свободных денежных средств","shortname": "Свободные","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "inn", {"code": "inn",
"type": 2,"length": 255,"name": "Идентификационный номер налогоплательщика (ИНН)","shortname": "ИНН","searchable": true,"sortable": true,"visible": true "type": 2,"length": 255,"name": "Идентификационный номер налогоплательщика (ИНН)","shortname": "ИНН","searchable": true,"sortable": true,"visible": true,"ignore": true
} }
, ,
{"code": "sessionId", {"code": "sessionId",
"type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session" "type": 1,"dbname": "Идентификатор клиринговой сессии","name": "Клиринговая сессия","shortname": "Сессия","visible": true,"searchable": true,"sortable": true,"link": "session","ignore": true
} }
, ,
{"code": "companyFullName", {"code": "companyFullName",
"type": 2,"length": 255,"name": "Полное наименование компании","shortname": "Полное наименование компании","searchable": true,"sortable": true,"visible": true "type": 2,"length": 255,"name": "Полное наименование компании","shortname": "Полное наименование компании","searchable": true,"sortable": true,"visible": true,"ignore": true
} }
, ,
{"code": "companyId", {"code": "companyId",
@ -6172,7 +6270,7 @@
} }
, ,
{"code": "id", {"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true "type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"ignore": true
} }
, ,
{"code": "createdAt", {"code": "createdAt",
@ -6180,7 +6278,7 @@
} }
, ,
{"code": "updatedAt", {"code": "updatedAt",
"field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true "field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true,"ignore": true
} }
] ]
@ -6192,6 +6290,8 @@
"destination": "admitted-liabilities-registers", "destination": "admitted-liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.AdmittedLiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.AdmittedLiabilitiesRegister",
"table": "admitted_liabilities_register", "table": "admitted_liabilities_register",
@ -6254,6 +6354,8 @@
"destination": "covered-liabilities-registers", "destination": "covered-liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.CoveredLiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.CoveredLiabilitiesRegister",
"table": "covered_Liabilities_register", "table": "covered_Liabilities_register",
@ -6316,6 +6418,8 @@
"destination": "money-payment-instruction-registers", "destination": "money-payment-instruction-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.MoneyPaymentInstructionRegister", "class": "ru.clearing.classes.statics.data.register.MoneyPaymentInstructionRegister",
"table": "money_payment_instruction_register", "table": "money_payment_instruction_register",
@ -6370,6 +6474,8 @@
"destination": "depo-payment-instruction-registers", "destination": "depo-payment-instruction-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.DepoPaymentInstructionRegister", "class": "ru.clearing.classes.statics.data.register.DepoPaymentInstructionRegister",
"table": "depo_payment_instruction_register", "table": "depo_payment_instruction_register",
@ -6424,6 +6530,8 @@
"destination": "exclude-liabilities-registers", "destination": "exclude-liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.ExcludeLiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.ExcludeLiabilitiesRegister",
"table": "exclude_liabilities_register", "table": "exclude_liabilities_register",
@ -6502,6 +6610,8 @@
"destination": "liabilities-registers", "destination": "liabilities-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.LiabilitiesRegister", "class": "ru.clearing.classes.statics.data.register.LiabilitiesRegister",
"table": "liabilities_register", "table": "liabilities_register",
@ -6580,6 +6690,8 @@
"destination": "execution-registers", "destination": "execution-registers",
"historyDestination": "history",
"class": "ru.clearing.classes.statics.data.register.ExecutionRegister", "class": "ru.clearing.classes.statics.data.register.ExecutionRegister",
"table": "execution_register", "table": "execution_register",

View file

@ -45,11 +45,6 @@
<artifactId>platform-enum</artifactId> <artifactId>platform-enum</artifactId>
</dependency> </dependency>
<!-- TEST --> <!-- TEST -->
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>test-clearing</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>

View file

@ -0,0 +1,75 @@
package ru.spcex.clearing.balance.config;
import com.hazelcast.config.*;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
import java.util.List;
import java.util.Random;
@Configuration
public class ImdgTestConfig {
private HazelcastInstance hazelcastInstance;
private static ThreadPoolTaskExecutor createThreadPoolTestTaskExecutor(int maxPoolSz, boolean waitForCompletion) {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
if (maxPoolSz > 2) {
pool.setKeepAliveSeconds(60);
pool.setAllowCoreThreadTimeOut(true);
}
pool.setCorePoolSize(maxPoolSz);
pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion);
return pool;
}
@Bean(name = "taskExecutorHazelcastTestClientInitializer")
public ThreadPoolTaskExecutor taskExecutorHazelcastTestClientInitializer() {
return createThreadPoolTestTaskExecutor(1, true);
}
@Bean(name = "taskExecutorTestIdGeneratorAwaiter")
public ThreadPoolTaskExecutor taskExecutorTestIdGeneratorAwaiter() {
return createThreadPoolTestTaskExecutor(1, false);
}
@Autowired
@Bean(name = "hazelcastServiceTest")
public ImdgProvider imdgTestProvider(
@Qualifier("taskExecutorHazelcastTestClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer,
@Qualifier("taskExecutorTestIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter,
HazelcastClientParams params) {
Config cfg = new Config();
cfg.setInstanceName("localhost");
NetworkConfig networkConfig = new NetworkConfig();
JoinConfig joinConfig = new JoinConfig();
joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false));
joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(true).setMembers(List.of("127.0.0.1")));
networkConfig.setJoin(joinConfig);
cfg.setNetworkConfig(networkConfig);
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance(cfg);
HazelcastHelper.imdgSystem_setStorageState(true, hazelcastInstance);
return new HazelcastService(taskExecutorHazelcastClientInitializer, taskExecutorIdGeneratorAwaiter, params);
}
@Bean(name = "hazelcastClientParams")
public HazelcastClientParams getHazelcastClientParams() {
HazelcastClientParams params = new HazelcastClientParams();
params.setLogin("dev");
params.setPassword("dev-pass");
params.setClusterMembers("127.0.0.1");
params.setInstanceName("hzTestClient" + new Random().nextInt());
params.setNearCacheConfig(new NearCacheConfig());
return params;
}
}

View file

@ -0,0 +1,42 @@
package ru.spcex.clearing.balance.config;
import org.apache.kafka.clients.consumer.MockConsumer;
import org.apache.kafka.clients.consumer.OffsetResetStrategy;
import org.apache.kafka.clients.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.service.RequestInfo;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
@Configuration
public class KafkaTestConfig {
@Autowired
@Bean
public KafkaSender kafkaSender(Producer<String, Object> kafkaProducer,
ImdgProvider imdgProvider) {
ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator();
return KafkaSender
.setup()
.producer(kafkaProducer)
.idGenerator(imdgIdGenerator::nextId)
.imdgProvider(s -> {
Imdg<RequestInfo> imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class);
return imdg::insert;
})
.build();
}
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean
public MockConsumer<String, Object> createTestConsumer() {
return new MockConsumer<>(OffsetResetStrategy.EARLIEST);
}
}

View file

@ -12,14 +12,10 @@ import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.sdf.*; import ru.clearing.classes.statics.data.sdf.*;
import ru.clearing.classes.statics.data.statement.Statement; import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.balance.config.MessagesConfig; import ru.spcex.clearing.balance.config.*;
import ru.spcex.clearing.balance.config.SdfExecutorsConfig;
import ru.spcex.clearing.balance.config.ValidationConfig;
import ru.spcex.clearing.balance.utils.MatcherFactory; import ru.spcex.clearing.balance.utils.MatcherFactory;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.service.RequestInfo; import ru.spcex.clearing.platform.messaging.service.RequestInfo;
import ru.spcex.clearing.test.config.ImdgTestConfig;
import ru.spcex.clearing.test.config.KafkaTestConfig;
import ru.spcex.platform.enumeration.*; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast; import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast;

View file

@ -3,12 +3,13 @@ package ru.spcex.clearing.balance.service;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.kafka.clients.consumer.MockConsumer; import org.apache.kafka.clients.consumer.MockConsumer;
import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.kafka.core.KafkaTemplate;
import ru.clearing.classes.statics.data.sdf.SDf08; import ru.clearing.classes.statics.data.sdf.SDf08;
import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
@ -24,7 +25,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static ru.spcex.clearing.balance.utils.MockKafkaUtils.addRecordToKafka; import static ru.spcex.clearing.balance.utils.MockKafkaUtils.addRecordToKafka;
import static ru.spcex.clearing.test.config.KafkaTestConfig.getCaptor;
class Sdf08ServiceTest extends AbstractServiceTest { class Sdf08ServiceTest extends AbstractServiceTest {
// private static final MatcherFactory.Matcher<SDf08> SDF_08_MATCHER = usingIgnoringFieldsComparator("created", "comment", "outSDfId", "generationTime", "generationId", "id"); // private static final MatcherFactory.Matcher<SDf08> SDF_08_MATCHER = usingIgnoringFieldsComparator("created", "comment", "outSDfId", "generationTime", "generationId", "id");
@ -32,12 +32,11 @@ class Sdf08ServiceTest extends AbstractServiceTest {
private static final int PARTITION = 1; private static final int PARTITION = 1;
@Autowired @Autowired
Sdf08Service sdf08Service; Sdf08Service sdf08Service;
@Captor
ArgumentCaptor<ProducerRecord> producerRecord;
private MockConsumer<String, Object> mockConsumer; private MockConsumer<String, Object> mockConsumer;
@SpyBean
@Autowired private MockProducer<String, Object> producer;
@Qualifier("kafkaTestTemplate")
private KafkaTemplate<String, Object> producer;
@PostConstruct @PostConstruct
void init() { void init() {
@ -67,7 +66,6 @@ class Sdf08ServiceTest extends AbstractServiceTest {
addRecordToKafka(mockConsumer, TOPIC, PARTITION, 0, jsonBaseNewRequest); addRecordToKafka(mockConsumer, TOPIC, PARTITION, 0, jsonBaseNewRequest);
//waiting for kafka producer send message (finale event) //waiting for kafka producer send message (finale event)
ArgumentCaptor<ProducerRecord> producerRecord = getCaptor(producer);
verify(producer, timeout(30_000L).times(1)) verify(producer, timeout(30_000L).times(1))
.send(producerRecord.capture()); .send(producerRecord.capture());

View file

@ -1,11 +1,12 @@
package ru.spcex.clearing.balance.service; package ru.spcex.clearing.balance.service;
import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.kafka.core.KafkaTemplate;
import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.account.AccountBalance; import ru.clearing.classes.statics.data.account.AccountBalance;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
@ -15,6 +16,7 @@ import ru.clearing.classes.statics.data.sdf.SDf17;
import ru.clearing.classes.statics.data.statement.Statement; import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.balance.errors.BalanceError; import ru.spcex.clearing.balance.errors.BalanceError;
import ru.spcex.clearing.balance.utils.MatcherFactory; import ru.spcex.clearing.balance.utils.MatcherFactory;
import ru.spcex.clearing.balance.utils.MockKafkaUtils;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
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.sdf01.AccountSdfRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart;
@ -32,8 +34,9 @@ import java.util.Collections;
import java.util.Map; import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static ru.spcex.clearing.balance.utils.MatcherFactory.usingIgnoringFieldsComparator; import static ru.spcex.clearing.balance.utils.MatcherFactory.usingIgnoringFieldsComparator;
import static ru.spcex.clearing.test.config.KafkaTestConfig.getCaptor;
class Sdf16ExecutorTest extends AbstractServiceTest { class Sdf16ExecutorTest extends AbstractServiceTest {
private static final MatcherFactory.Matcher<SDf17> SDF_17_MATCHER = usingIgnoringFieldsComparator("created", "comment", "outSDfId", "generationTime", "generationId", "id"); private static final MatcherFactory.Matcher<SDf17> SDF_17_MATCHER = usingIgnoringFieldsComparator("created", "comment", "outSDfId", "generationTime", "generationId", "id");
@ -41,14 +44,13 @@ class Sdf16ExecutorTest extends AbstractServiceTest {
private final String acc = "323456789"; private final String acc = "323456789";
@Autowired @Autowired
Sdf16Executor sdf16Executor; Sdf16Executor sdf16Executor;
@Captor
@Autowired ArgumentCaptor<ProducerRecord> producerRecord;
@Qualifier("kafkaTestTemplate")
private KafkaTemplate<String, Object> producer;
private SDf16 sdf16; private SDf16 sdf16;
private StatementRequest statementRequest; private StatementRequest statementRequest;
@MockBean
private MockProducer<String, Object> producer;
@PostConstruct @PostConstruct
void init() { void init() {
@ -92,9 +94,9 @@ class Sdf16ExecutorTest extends AbstractServiceTest {
SDf17 predictableSdf17 = getTestSdf17(currentId.getAndIncrement(), sdf16, ID); SDf17 predictableSdf17 = getTestSdf17(currentId.getAndIncrement(), sdf16, ID);
predictableStatement.setOutSDfId(predictableSdf17.getId()); predictableStatement.setOutSDfId(predictableSdf17.getId());
AccountResult predictableNewResult = getTestAccountResult(currentId.getAndIncrement(), account, company); AccountResult predictableNewResult = getTestAccountResult(currentId.getAndIncrement(), account, company);
predictableNewResult.getAccount().setCurrencyCode(null);
ArgumentCaptor<ProducerRecord> producerRecord = getCaptor(producer); MockKafkaUtils.FutureRecordMetadata future = spy(MockKafkaUtils.FutureRecordMetadata.class);
doReturn(future).when(producer).send(producerRecord.capture());
Result result = sdf16Executor.execute(Collections.singletonList(sdf16), statementRequest); Result result = sdf16Executor.execute(Collections.singletonList(sdf16), statementRequest);
BaseRequest<Object> baseRequest = (BaseRequest<Object>) producerRecord.getValue().value(); BaseRequest<Object> baseRequest = (BaseRequest<Object>) producerRecord.getValue().value();

View file

@ -0,0 +1,33 @@
package ru.clearing.classes.statics.data.account;
import ru.clearing.classes.ConstSerializable;
import ru.spcex.platform.classes.base.SpcexObjectBase;
/**
* Депо КС - РДЦ
* <p>
* DB table: ACCOUNT_SYMBOLS
**/
public class AccountSymbols extends SpcexObjectBase {
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
private Long accountId;
private String accountSymbolValue;
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long value) {
this.accountId = value;
}
public String getAccountSymbolValue() {
return accountSymbolValue;
}
public void setAccountSymbolValue(String value) {
this.accountSymbolValue = value;
}
}

View file

@ -0,0 +1,28 @@
package ru.clearing.classes.statics.data.account;
import ru.clearing.classes.ConstSerializable;
import ru.clearing.classes.objects.BusinessEvent;
import java.io.Serial;
/**
* Изменение состояния объекта Депо КС - РДЦ
* <p>
* DB table: ACCOUNT_SYMBOLS_HISTORY
**/
public class AccountSymbolsHistory extends BusinessEvent<AccountSymbols> {
@Serial
private static final long serialVersionUID = ConstSerializable.serialVersionUID;
private AccountSymbols object;
@Override
public AccountSymbols getObject() {
return object;
}
@Override
public void setObject(AccountSymbols object) {
this.object = object;
}
}

View file

@ -73,11 +73,6 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>test-clearing</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<resources> <resources>

View file

@ -2,6 +2,8 @@ package ru.spcex.clearing.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
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;
@ -26,19 +28,31 @@ import java.util.function.Supplier;
@Configuration @Configuration
public class KafkaConfig { public class KafkaConfig {
@Autowired private final Logger log = LoggerFactory.getLogger(getClass());
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) private final KafkaConsumerSettings kafkaSettings;
@Bean("kafkaConsumer")
public Consumer<String, Object> createConsumer(ClearingServiceSettings settings) { public KafkaConfig(ClearingServiceSettings settings) {
return KafkaConsumerFactory.consumer(settings.getKafkaConsumer()); this.kafkaSettings = settings.getKafkaConsumer();
Integer gtwTimeout = settings.getSessionStage().getInspectionGatewayTimeout();
if (gtwTimeout != null) {
int maxPollIntervalMs = gtwTimeout * 1000 + 1000;
log.debug("setting max.poll.interval.ms {}", maxPollIntervalMs);
this.kafkaSettings.setManuallyMaxPollIntervalMs(maxPollIntervalMs);
}
}
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean("kafkaConsumer")
public Consumer<String, Object> createConsumer() {
return KafkaConsumerFactory.consumer(kafkaSettings);
} }
@Autowired
@Bean("kafkaConsumerGateway") @Bean("kafkaConsumerGateway")
public Supplier<Consumer<String, Object>> getwaySessionConsumer(ClearingServiceSettings settings) { public Supplier<Consumer<String, Object>> getwaySessionConsumer() {
AtomicInteger groupId = new AtomicInteger(1); AtomicInteger groupId = new AtomicInteger(1);
return () -> { return () -> {
KafkaConsumerSettings consumer = settings.getKafkaConsumer(); KafkaConsumerSettings consumer = kafkaSettings;
KafkaConsumerSettings gatewayConsumer = new KafkaConsumerSettings(); KafkaConsumerSettings gatewayConsumer = new KafkaConsumerSettings();
gatewayConsumer.setBootstrapServers(consumer.getBootstrapServers()); gatewayConsumer.setBootstrapServers(consumer.getBootstrapServers());
gatewayConsumer.setSessionTimeoutMs(consumer.getSessionTimeoutMs()); gatewayConsumer.setSessionTimeoutMs(consumer.getSessionTimeoutMs());

View file

@ -46,6 +46,7 @@ import ru.spcex.platform.utils.validation.ValidatorImpl;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
@Configuration @Configuration
public class ValidationConfig { public class ValidationConfig {
@ -367,6 +368,7 @@ public class ValidationConfig {
new PresentById(IMDGDistributedNames.Map_Registry, ClearingError.RecordNotFound, true), new PresentById(IMDGDistributedNames.Map_Registry, ClearingError.RecordNotFound, true),
StatusExtractValidationRule.RegistryCodeCheck, StatusExtractValidationRule.RegistryCodeCheck,
StatusExtractValidationRule.ContractCheck, StatusExtractValidationRule.ContractCheck,
StatusExtractValidationRule.RequestStatusValid,
StatusExtractValidationRule.RegistryStatusValid StatusExtractValidationRule.RegistryStatusValid
); );
}; };
@ -490,6 +492,19 @@ public class ValidationConfig {
}; };
} }
@Bean("terminateSessionValidator")
public Supplier<IValidator> terminateSessionValidator() {
return () -> {
ImdgValidationContext<Session> ctx = new ImdgValidationContext<>();
ctx.setLogPrefix(LogPrefixId.INSTANCE);
ctx.addImdg(IMDGDistributedNames.Map_Session, imdgSession);
return new ValidatorImpl<>(ctx,
SessionTerminationValidationRule.SessionPresent,
SessionTerminationValidationRule.StatusCheck
);
};
}
@Bean("userRoleVerification") @Bean("userRoleVerification")
public UserRoleVerification userRoleVerification(ImdgProvider imdgProvider, IMessageResolver msgs) { public UserRoleVerification userRoleVerification(ImdgProvider imdgProvider, IMessageResolver msgs) {
return new UserRoleVerification(imdgProvider, msgs, ClearingError.UserVerifyDenial); return new UserRoleVerification(imdgProvider, msgs, ClearingError.UserVerifyDenial);

View file

@ -15,6 +15,7 @@ public class ClearingServiceSettings {
private KafkaConsumerSettings kafkaConsumer; private KafkaConsumerSettings kafkaConsumer;
private KafkaProducerSettings kafkaProducer; private KafkaProducerSettings kafkaProducer;
private SessionStageSettings sessionStage; private SessionStageSettings sessionStage;
private TradeSettings trade = new TradeSettings();
public HazelcastClientParams getHazelcast() { public HazelcastClientParams getHazelcast() {
return hazelcast; return hazelcast;
@ -47,4 +48,12 @@ public class ClearingServiceSettings {
public void setSessionStage(SessionStageSettings sessionStage) { public void setSessionStage(SessionStageSettings sessionStage) {
this.sessionStage = sessionStage; this.sessionStage = sessionStage;
} }
public TradeSettings getTrade() {
return trade;
}
public void setTrade(TradeSettings trade) {
this.trade = trade;
}
} }

View file

@ -0,0 +1,14 @@
package ru.spcex.clearing.config.element;
public class TradeSettings {
private Boolean valuation = false;
public Boolean getValuation() {
return valuation;
}
public void setValuation(Boolean valuation) {
this.valuation = valuation;
}
}

View file

@ -54,6 +54,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
private final BalanceRevise balanceRevise; private final BalanceRevise balanceRevise;
private final Sdf05Sender sdf05Sender; private final Sdf05Sender sdf05Sender;
private final StatementServiceV2 statementService; private final StatementServiceV2 statementService;
private final SessionTerminator sessionTerminator;
private final PaymentInstructionOutboundService pmtOutboundService; private final PaymentInstructionOutboundService pmtOutboundService;
@Autowired @Autowired
@ -65,7 +66,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
SecondaryAuctionT0Session secondaryAuctionT0Session, SecondaryAuctionT0Session secondaryAuctionT0Session,
PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager, PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager,
Sdf06Executor sdf06Executor, Sdf06Executor sdf06Executor,
Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender, StatementServiceV2 statementService, PaymentInstructionOutboundService pmtOutboundService) { Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender, StatementServiceV2 statementService, SessionTerminator sessionTerminator, PaymentInstructionOutboundService pmtOutboundService) {
super(kafkaQueue, kafkaResponseQueue); super(kafkaQueue, kafkaResponseQueue);
this.errorResolver = errorResolver; this.errorResolver = errorResolver;
this.clearingService = clearingService; this.clearingService = clearingService;
@ -83,6 +84,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
this.balanceRevise = balanceRevise; this.balanceRevise = balanceRevise;
this.sdf05Sender = sdf05Sender; this.sdf05Sender = sdf05Sender;
this.statementService = statementService; this.statementService = statementService;
this.sessionTerminator = sessionTerminator;
this.pmtOutboundService = pmtOutboundService; this.pmtOutboundService = pmtOutboundService;
} }
@ -184,6 +186,11 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
callback(LauncherCommandRequest.class) callback(LauncherCommandRequest.class)
.setConsumer(task -> sdf05Sender.sendSdf05("9")) .setConsumer(task -> sdf05Sender.sendSdf05("9"))
.forDestination(Task.sdf05WithCode9Final.topic(), callbacks::put); .forDestination(Task.sdf05WithCode9Final.topic(), callbacks::put);
callback(Object.class)
.setFunction(sessionTerminator::stopCurrentSession)
.forDestination(Consts.KILL_SESSION, callbacks::put);
init(); init();
} }

View file

@ -48,11 +48,9 @@ import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Collection; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
@ -287,24 +285,12 @@ public class RegistryService {
return reqHelp.error(req.getId(), err.get()); return reqHelp.error(req.getId(), err.get());
} }
Registry rgs = validator.getStored(Stored.PresentById); Registry rgs = validator.getStored(Stored.PresentById);
//Supplier<AssetOperationRequest> gtwBuilder = () -> GatewayRequestCreator.from(rgs, InOutDirection.in); if (trdTime.isTradingTime()) {
//Optional<Boolean> gatewayOk; Long gtwReqId = kafkaSender.sendRequestToQueue(Consts.ASSET_OPERATION, gtwReq(rgs));
//if (trdTime.isTradingTime()) { log.debug("send request to {} id={}", Consts.ASSET_OPERATION, gtwReqId);
// gatewayOk = gateway.gatewayRequestAndWait(gtwBuilder); } else {
//} else { log.debug("RegistryChangeStatusExtractRequest rgs.id={} not sending gateway request", rgs.getId());
// log.debug("RegistryChangeStatusExtractRequest rgs.id={} not sending gateway request", rgs.getId()); }
// gatewayOk = Optional.of(true);
//}
//if (gatewayOk.isEmpty() || !gatewayOk.get()) {
// String gtwErr = msgResolver.resolve(mapError(gatewayOk));
// log.error("{}.id={} {}",
// rgs.getRegistryCode(),
// rgs.getId(),
// gtwErr);
// notification.sendNotification(ObjectType.rgst,
// "Отметка о получении выписки: %s".formatted(gtwErr),
// Priority.HIGH);
//}
rgs.setRegistryStatus(payload.getRegistryStatus()); rgs.setRegistryStatus(payload.getRegistryStatus());
log.debug("changing registry.id={} status to {}", rgs.getId(), payload.getRegistryStatus()); log.debug("changing registry.id={} status to {}", rgs.getId(), payload.getRegistryStatus());
registryImdg.update(rgs); registryImdg.update(rgs);
@ -318,6 +304,13 @@ public class RegistryService {
return reqHelp.success(req.getId()); return reqHelp.success(req.getId());
} }
private AssetOperationListRequest gtwReq(Registry rgs) {
AssetOperationRequest item = GatewayRequestCreator.from(rgs, InOutDirection.in);
AssetOperationListRequest gtwReq = new AssetOperationListRequest();
gtwReq.setAssetOperationRequests(Collections.singletonList(item));
return gtwReq;
}
public RequestInfoUpdate identificationFunds(BaseRequest<IdentificationFundsRequest> req) { public RequestInfoUpdate identificationFunds(BaseRequest<IdentificationFundsRequest> req) {
if (!rights.userHasRole(req.getUserId(), UserRole.Admin)) { if (!rights.userHasRole(req.getUserId(), UserRole.Admin)) {
return reqHelp.error(req.getId(), ClearingError.UserVerifyDenial); return reqHelp.error(req.getId(), ClearingError.UserVerifyDenial);
@ -454,56 +447,70 @@ public class RegistryService {
} }
public record RgsKey (Long companyId, Long accountId, Long securityId) {
public static RgsKey fromRgs(Registry rgs) {
return new RgsKey(rgs.getCompanyId(), rgs.getAccountId(), rgs.getSecurityId());
}
}
private Optional<Registry> find(List<Registry> group, RegistryTradingParams rgsCode) {
List<Registry> byCodeRes = group.stream()
.filter(rgs -> RegistryManager.equalsByCode(rgsCode, rgs))
.toList();
if (byCodeRes.size() > 1) {
Optional<Registry> any = group.stream().findFirst();
if (any.isEmpty()) throw new IllegalStateException(); //never
String err = "FATAL: found %d entries by code %s in group %s".formatted(
byCodeRes.size(),
rgsCode,
RgsKey.fromRgs(any.get()).toString()
);
throw new IllegalStateException(err);
}
return byCodeRes.stream().findFirst();
}
public void resetBalances() { public void resetBalances() {
Collection<Registry> registriesA = registryImdg.getCollectionObjectsByFieldValues(Map.of( Collection<Registry> registriesA = registryImdg.getCollectionObjectsByFieldValues(Map.of(
"registryDesignation", RegistryDesignation.A.getKey()) "registryDesignation", RegistryDesignation.A.getKey())
); );
for (Registry registry : registriesA) { Map<RgsKey, List<Registry>> allAssets = registriesA
if (RegistryUnit.B.equalsByKey(registry.getRegistryUnit())) { .stream()
registry.setBalance(BigDecimal.ZERO); .collect(Collectors.groupingBy(RgsKey::fromRgs));
}
if (RegistryUnit.F.equalsByKey(registry.getRegistryUnit())) {
Optional<Registry> registryBOptional = registriesA.stream().filter(rgs ->
rgs.getAccount() != null && rgs.getSecurityId() != null &&
rgs.getTradingClearingRegistryId() != null && rgs.getCompanyId() != null &&
RegistryUnit.B.equalsByKey(rgs.getRegistryUnit()) &&
rgs.getSecurityId() != null && rgs.getSecurityId().equals(registry.getSecurityId()) &&
rgs.getCompanyId() != null && rgs.getCompanyId().equals(registry.getCompanyId()) &&
rgs.getAccount() != null && rgs.getAccount().equals(registry.getAccount()) &&
rgs.getTradingClearingRegistryId() != null && rgs.getTradingClearingRegistryId().equals(registry.getTradingClearingRegistryId())
).findFirst();
Optional<Registry> registryTOptional = registriesA.stream().filter(rgs ->
rgs.getAccount() != null && rgs.getSecurityId() != null &&
rgs.getTradingClearingRegistryId() != null && rgs.getCompanyId() != null &&
RegistryUnit.T.equalsByKey(rgs.getRegistryUnit()) &&
rgs.getSecurityId() != null && rgs.getSecurityId().equals(registry.getSecurityId()) &&
rgs.getCompanyId() != null && rgs.getCompanyId().equals(registry.getCompanyId()) &&
rgs.getAccount() != null && rgs.getAccount().equals(registry.getAccount()) &&
rgs.getTradingClearingRegistryId() != null && rgs.getTradingClearingRegistryId().equals(registry.getTradingClearingRegistryId())
).findFirst();
BigDecimal balanceB;
if (registryBOptional.isPresent()) {
balanceB = registryBOptional.get().getBalance();
} else {
balanceB = BigDecimal.ZERO;
}
registryTOptional.ifPresent(rgsT -> registry.setBalance(rgsT.getBalance().subtract(balanceB)));
}
if (RegistryUnit.T.equalsByKey(registry.getRegistryUnit())) {
registry.setOpenBalance(registry.getBalance());
}
registry.setDebit(BigDecimal.ZERO); Instant timestamp = Instant.now();
registry.setSettledDebit(BigDecimal.ZERO); for (Map.Entry<RgsKey, List<Registry>> entry : allAssets.entrySet()) {
registry.setCredit(BigDecimal.ZERO); RgsKey key = entry.getKey();
registry.setSettledCredit(BigDecimal.ZERO); List<Registry> group = entry.getValue();
registry.setPlanBalance(BigDecimal.ZERO); Registry a__f = find(group, RegistryTradingParams.A__F).orElse(null);
registry.setCloseBalance(registry.getBalance()); Registry a__t = find(group, RegistryTradingParams.A__T).orElse(null);
Registry a__b = find(group, RegistryTradingParams.A__B).orElse(null);
registry.setUpdated(Instant.now()); if (a__t == null) {
registryImdg.update(registry); log.warn("registry group {}: no A**T registry found.", key);
continue;
}
BigDecimal a__tBalance = safeBD(a__t.getBalance());
a__t.setOpenBalance(a__tBalance);
a__t.setCloseBalance(a__tBalance);
a__t.setCredit(BigDecimal.ZERO);
a__t.setDebit(BigDecimal.ZERO);
a__t.setSettledCredit(BigDecimal.ZERO);
a__t.setSettledDebit(BigDecimal.ZERO);
a__t.setUpdated(timestamp);
registryImdg.update(a__t);
if (a__f == null) {
a__f = assets.copy(a__t, RegistryUnit.F);
registryImdg.insert(a__f);
}
if (a__b != null) {
a__b.setBalance(BigDecimal.ZERO);
registryImdg.update(a__b);
}
assets.process(a__b, a__t, a__f, BigDecimal.ZERO);
} }
} }

View file

@ -1,42 +0,0 @@
package ru.spcex.clearing.service.builder;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.math.BigDecimal;
public class PaymentInstructionBuilderDepositReturn {
private ImdgProvider imdgProvider;
private Long sessionId;
private BigDecimal amount;
private Registry lm_tRgs;
public static PaymentInstructionBuilderDepositReturn builder(ImdgProvider imdgProvider) {
return new PaymentInstructionBuilderDepositReturn(imdgProvider);
}
private PaymentInstructionBuilderDepositReturn(ImdgProvider imdgProvider) {
this.imdgProvider = imdgProvider;
}
public PaymentInstructionBuilderDepositReturn sessionId(Long sessionId) {
this.sessionId = sessionId;
return this;
}
public PaymentInstructionBuilderDepositReturn amount(BigDecimal amount) {
this.amount = amount;
return this;
}
public PaymentInstructionBuilderDepositReturn lm_tRgs(Registry rgs) {
this.lm_tRgs = rgs;
return this;
}
public PaymentInstruction build() {
return null;
}
}

View file

@ -4,7 +4,9 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.company.CompanyRoleSet;
import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.CompanySymbols;
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.clearing.classes.statics.data.registry.Registry;
@ -12,12 +14,17 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames;
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.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.time.TimeUtil; import ru.spcex.platform.utils.time.TimeUtil;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
@ -27,6 +34,9 @@ public class PaymentInstructionBuilderV2 {
private ImdgProvider imdgProvider; private ImdgProvider imdgProvider;
private Imdg<Company> companyImdg; private Imdg<Company> companyImdg;
private Imdg<CompanySymbols> companySymbolsImdg; private Imdg<CompanySymbols> companySymbolsImdg;
private Imdg<Registry> rgsImdg;
private final Imdg<ClearingMemberCategory> clearingCategoryImdg;
private final Imdg<CompanyRoleSet> cmpRoleImdg;
private Long sessionId; private Long sessionId;
private BigDecimal amount; private BigDecimal amount;
private Account creditLegAccount; private Account creditLegAccount;
@ -37,6 +47,9 @@ public class PaymentInstructionBuilderV2 {
private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy"); private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy");
private Long senderId; private Long senderId;
private Long addresseeId; private Long addresseeId;
private boolean useCS_BLKD = false;
private Registry am_b;
public static PaymentInstructionBuilderV2 builder(ImdgProvider imdgProvider) { public static PaymentInstructionBuilderV2 builder(ImdgProvider imdgProvider) {
return new PaymentInstructionBuilderV2(imdgProvider); return new PaymentInstructionBuilderV2(imdgProvider);
@ -46,6 +59,18 @@ public class PaymentInstructionBuilderV2 {
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
this.companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); this.companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class);
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
this.cmpRoleImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanyRoleSet, CompanyRoleSet.class);
}
public PaymentInstructionBuilderV2 checkBLKD(Registry rgs) {
if (rgs == null) {
return this;
}
this.useCS_BLKD = true;
this.am_b = rgs;
return this;
} }
public PaymentInstructionBuilderV2 sessionId(Long sessionId) { public PaymentInstructionBuilderV2 sessionId(Long sessionId) {
@ -128,7 +153,12 @@ public class PaymentInstructionBuilderV2 {
payment.setPaymentDate(Instant.now()); payment.setPaymentDate(Instant.now());
payment.setSettlementDate(LocalDate.now()); payment.setSettlementDate(LocalDate.now());
} }
payment.setPaymentPurpose(purpose);
if (useCS_BLKD && checkAgent()) {
payment.setPaymentPurpose(SpecifFlag.CS_BLKD.getKey() + "_" + sessionId + " " + purpose);
} else {
payment.setPaymentPurpose(purpose);
}
payment.setCreditLeg_amount(amount); payment.setCreditLeg_amount(amount);
payment.setDebitLeg_amount(amount); payment.setDebitLeg_amount(amount);
@ -193,4 +223,41 @@ public class PaymentInstructionBuilderV2 {
return cSymbol.getCompanySymbolValue(); return cSymbol.getCompanySymbolValue();
} }
} }
private boolean checkAgent() {
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.equals("sessionId", sessionId),
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.CM__).build()),
pb.equals("companyId", addresseeId),
pb.equals("accountId", am_b.getAccountId())
);
Collection<Registry> claims = rgsImdg.getCollectionObjectsByPredicate(prdct);
boolean hasCounterPartyInitiator = false;
for (Registry claim : claims) {
Long counterPartyId = claim.getCounterPartyId();
if (categoryIOrVInitiator(counterPartyId) && companyRoleODEPPresent(counterPartyId)) {
hasCounterPartyInitiator = true;
break;
}
}
return hasCounterPartyInitiator;
}
public boolean categoryIOrVInitiator(Long companyId) {
ClearingMemberCategory category = clearingCategoryImdg.getFirstObjectByFieldValues(
Map.of("companyId", companyId));
ClearingCategory ctg = IEnumKey.getEnumByKey(ClearingCategory.class, category.getClearingMemberCategory());
return ctg != null && (ctg.equals(ClearingCategory.V) || ctg.equals(ClearingCategory.I)) ;
}
public boolean companyRoleODEPPresent(Long companyId) {
return cmpRoleImdg.getFirstObjectBySQL(
"companyId = %d and companyRole = '%s' and workflowStatus = '%s'".formatted(
companyId,
CompanyRole.ODEP.getKey(),
WorkflowStatus.Active.getKey()
)
) != null;
}
} }

View file

@ -133,6 +133,7 @@ public class RegistryBuilder {
rgs.setCredit(BigDecimal.ZERO); rgs.setCredit(BigDecimal.ZERO);
rgs.setDiffBalance(BigDecimal.ZERO); rgs.setDiffBalance(BigDecimal.ZERO);
rgs.setCheckBalance(BigDecimal.ZERO); rgs.setCheckBalance(BigDecimal.ZERO);
rgs.setOpenBalance(BigDecimal.ZERO);
return rgs; return rgs;
} }

View file

@ -133,6 +133,7 @@ public class RegistrySecurityBuilder {
rgs.setCredit(BigDecimal.ZERO); rgs.setCredit(BigDecimal.ZERO);
rgs.setDiffBalance(BigDecimal.ZERO); rgs.setDiffBalance(BigDecimal.ZERO);
rgs.setCheckBalance(BigDecimal.ZERO); rgs.setCheckBalance(BigDecimal.ZERO);
rgs.setOpenBalance(BigDecimal.ZERO);
return rgs; return rgs;
} }

View file

@ -11,29 +11,34 @@ import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.account.ClientCode; import ru.clearing.classes.statics.data.account.ClientCode;
import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.Company;
import ru.clearing.classes.statics.data.execution.ExecutionFond; import ru.clearing.classes.statics.data.execution.ExecutionFond;
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeCashFlow;
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.Listing;
import ru.clearing.classes.statics.data.misc.STrades; import ru.clearing.classes.statics.data.misc.STrades;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.security.Security; import ru.clearing.classes.statics.data.security.Security;
import ru.spcex.clearing.config.element.ClearingServiceSettings;
import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.error.ClearingException; import ru.spcex.clearing.error.ClearingException;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.notification.NotificationSender;
import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.DealRegisterNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.DealRegisterNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.ExecutionType; import ru.spcex.clearing.platform.messaging.domain.cud.registry.ExecutionType;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.platform.enumeration.CurrencyCode; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.Side;
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.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.*; import ru.spcex.platform.utils.enumeration.*;
import ru.spcex.platform.utils.log.ExceptionUtils; import ru.spcex.platform.utils.log.ExceptionUtils;
import ru.spcex.platform.utils.time.TimeUtil; import ru.spcex.platform.utils.time.TimeUtil;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Collection; import java.util.Collection;
@ -41,6 +46,8 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
@Component @Component
@EnableScheduling @EnableScheduling
public class ExecutionFondComponent { public class ExecutionFondComponent {
@ -50,6 +57,7 @@ public class ExecutionFondComponent {
private final Imdg<ExecutionFond> executionFondImdg; private final Imdg<ExecutionFond> executionFondImdg;
private final Imdg<Listing> listingImdg; private final Imdg<Listing> listingImdg;
private final Imdg<ClientCode> clientCodeImdg; private final Imdg<ClientCode> clientCodeImdg;
private final Imdg<FixedIncomeCashFlow> fixedIncomeCashFlowImdg;
private final Imdg<ru.clearing.classes.statics.data.misc.Market> marketImdg; private final Imdg<ru.clearing.classes.statics.data.misc.Market> marketImdg;
//fixme ждать ТЗ //fixme ждать ТЗ
@ -58,19 +66,26 @@ public class ExecutionFondComponent {
private final IMessageResolver msgResolver = new SimpleMessageResolver(); private final IMessageResolver msgResolver = new SimpleMessageResolver();
private final Function<STrades, IValidator> stradesValidator; private final Function<STrades, IValidator> stradesValidator;
private final KafkaSender kafkaSender; private final KafkaSender kafkaSender;
private final NotificationSender notifications;
private final boolean valuation;
@Autowired @Autowired
public ExecutionFondComponent(ImdgProvider imdgProvider, Producer<String, Object> kafka, public ExecutionFondComponent(ImdgProvider imdgProvider,
ClearingServiceSettings settings,
Producer<String, Object> kafka,
@Qualifier("sTradesValidatorFond") Function<STrades, IValidator> stradesValidator, @Qualifier("sTradesValidatorFond") Function<STrades, IValidator> stradesValidator,
@Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafkaSender) { @Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafkaSender, NotificationSender notifications) {
this.sTradeImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_STrades, STrades.class); this.sTradeImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_STrades, STrades.class);
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class); this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
this.clientCodeImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClientCode, ClientCode.class); this.clientCodeImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClientCode, ClientCode.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);
this.fixedIncomeCashFlowImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeCashFlow, FixedIncomeCashFlow.class);
this.valuation = settings.getTrade().getValuation(); //fixme
this.stradesValidator = stradesValidator; this.stradesValidator = stradesValidator;
this.kafkaSender = kafkaSender; this.kafkaSender = kafkaSender;
this.notifications = notifications;
resetTradingDay(); resetTradingDay();
} }
@ -119,7 +134,7 @@ public class ExecutionFondComponent {
log.info("{} strades left after already-added filtering", sTrades.size()); log.info("{} strades left after already-added filtering", sTrades.size());
for (STrades sTrd : sTrades) { for (STrades sTrd : sTrades) {
log.trace("S_TRADE[{}] new", sTrd.getId()); log.info("new S_TRADE[{}], valuation {}", sTrd.getId(), valuation);
//проверки //проверки
IValidator validator = stradesValidator.apply(sTrd); IValidator validator = stradesValidator.apply(sTrd);
@ -165,6 +180,7 @@ public class ExecutionFondComponent {
protected ExecutionFond createExecutionFond(STrades sTrades, protected ExecutionFond createExecutionFond(STrades sTrades,
IValidator validator) throws ClearingException { IValidator validator) throws ClearingException {
Security security = validator.getStored(ValidationStored.STradesSecurity); Security security = validator.getStored(ValidationStored.STradesSecurity);
// Listing listing = listingImdg.getFirstObjectByFieldValues(Map.of("securityId", security.getId()));
Company company = validator.getStored(ValidationStored.STradesCompany); Company company = validator.getStored(ValidationStored.STradesCompany);
Company counterCompany = validator.getStored(ValidationStored.STradesCounterCompany); Company counterCompany = validator.getStored(ValidationStored.STradesCounterCompany);
TradingClearingRegistry rgstr = validator.getStored(ValidationStored.STradesTradingClearingRegistry); TradingClearingRegistry rgstr = validator.getStored(ValidationStored.STradesTradingClearingRegistry);
@ -212,7 +228,57 @@ public class ExecutionFondComponent {
eFond.setSecurityId(security.getId()); eFond.setSecurityId(security.getId());
eFond.setInterestAmount(sTrades.getAccruedint()); eFond.setInterestAmount(sTrades.getAccruedint());
eFond.setExchangeOrderId(sTrades.getOrderNum()); eFond.setExchangeOrderId(sTrades.getOrderNum());
eFond.setSettlementAmount(sTrades.getValue()); if (valuation) {
Listing listing = listingImdg.getFirstObjectBySQL("securityId = %d and market = '%s'".formatted(security.getId(), sTrades.getClassCode()));
BigDecimal lotSize = listing != null ? safeBD(listing.getLotSize()) : BigDecimal.ONE;
BigDecimal qty = safeBD(eFond.getLots()).multiply(lotSize);
eFond.setQuantity(qty);
BigDecimal price = safeBD(sTrades.getPrice());// eFond.setPrice
BigDecimal settlementAmount = BigDecimal.ZERO;
if (InstrumentType.BOND.equalsByKey(security.getInstrumentType())) {
FixedIncomeSecurity fixedIncome = (FixedIncomeSecurity) security;
BigDecimal nominalValue;
ImdgPredicateBuilder pb = fixedIncomeCashFlowImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.equals("securityId", fixedIncome.getId()),
sTrades.getSettleDate() != null ?
pb.equals("valueDate", sTrades.getSettleDate()) : pb.alwaysFalse()
);
FixedIncomeCashFlow cashFlow = fixedIncomeCashFlowImdg.getFirstObjectByPredicate(prdct);
if (cashFlow != null) {
nominalValue = safeBD(cashFlow.getNominalValue());
} else {
nominalValue = safeBD(fixedIncome.getNominalValue());
}
{
settlementAmount = eFond.getQuantity()
.multiply(nominalValue)
.multiply(price)
.divide(new BigDecimal(100), RoundingMode.HALF_UP)
.setScale(2, RoundingMode.HALF_UP);
}
} else if (InstrumentType.EQTY.equalsByKey(security.getInstrumentType())) {
BigDecimal lotsEqty = safeBD(eFond.getQuantity());
settlementAmount = lotsEqty.multiply(price).setScale(2, RoundingMode.HALF_UP);
}
eFond.setSettlementAmount(settlementAmount);
if (settlementAmount.compareTo(safeBD(sTrades.getValue())) != 0) {
log.warn("sTrades.TradeNum={} sTrades.value({}) != eFond({})",
sTrades.getTradeNum(),
safeBD(sTrades.getValue()),
settlementAmount);
notifications.sendNotification(
ObjectType.vfrs,
"Для сделки %s объем сделки в ТС %s не совпадает с расчитанным в КС %s"
.formatted(sTrades.getTradeNum(),
safeBD(sTrades.getValue()).toString(),
settlementAmount.toString()),
Priority.HIGH
);
}
} else {
eFond.setSettlementAmount(sTrades.getValue());
}
eFond.setCounterPartyId(counterCompany.getId()); eFond.setCounterPartyId(counterCompany.getId());
{ {
ImdgPredicateBuilder strPb = sTradeImdg.predicateBuilder(); ImdgPredicateBuilder strPb = sTradeImdg.predicateBuilder();

View file

@ -41,9 +41,7 @@ import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Collection; import java.util.*;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
@Service @Service
@ -112,7 +110,9 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
result.setChildGenerationId(generationIdForGroup); result.setChildGenerationId(generationIdForGroup);
result.setFileName(filenameObtainer.getFilename(sdf, sdf01Imdg, statementRequest.getGroupId())); result.setFileName(filenameObtainer.getFilename(sdf, sdf01Imdg, statementRequest.getGroupId()));
log.info("SDF01 execution: sdf01 file={} number={}, groupId={}", result.getFileName(), sdf.size(), sdf.stream().findFirst().map(SDf01::getGenerationId).orElse(null)); log.info("SDF01 execution: sdf01 file={} number={}, groupId={}", result.getFileName(), sdf.size(), sdf.stream().findFirst().map(SDf01::getGenerationId).orElse(null));
for (SDf01 sdf01 : sdf) { ArrayList<SDf01> orderedSdf = new ArrayList<>(sdf);
orderedSdf.sort(Comparator.comparing(SDf01::getId));// Сортировка по возрастанию id, чтобы сохранить последовательность строк SDF02, как в SDF01
for (SDf01 sdf01 : orderedSdf) {
IValidator validator = sDf01Validator.apply(sdf01); IValidator validator = sDf01Validator.apply(sdf01);
Optional<EnumMessage> error = validator.tillFirstError(); Optional<EnumMessage> error = validator.tillFirstError();
Company company = validator.getStored(ValidationStored.Sdf01Company); Company company = validator.getStored(ValidationStored.Sdf01Company);

View file

@ -22,7 +22,9 @@ import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationRe
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApprovalRequest; import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApprovalRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse; import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.AssetTrio;
import ru.spcex.clearing.service.integration.GatewayRequestCreator; import ru.spcex.clearing.service.integration.GatewayRequestCreator;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.registry.DmiService; import ru.spcex.clearing.service.registry.DmiService;
import ru.spcex.clearing.service.schedule.TradingTimeService; import ru.spcex.clearing.service.schedule.TradingTimeService;
import ru.spcex.clearing.service.validation.Sdf06NewValidationRule; import ru.spcex.clearing.service.validation.Sdf06NewValidationRule;
@ -66,6 +68,7 @@ public class Sdf06Executor {
private final KafkaSender kafkaSender; private final KafkaSender kafkaSender;
private final FilenameObtainer filenameObtainer; private final FilenameObtainer filenameObtainer;
private final DmiService dmiService; private final DmiService dmiService;
private final AssetTBFProcessing assets;
private final static BigDecimal successResult = BigDecimal.ZERO; private final static BigDecimal successResult = BigDecimal.ZERO;
//идет сессия (не возвращаем такую ошибку) //идет сессия (не возвращаем такую ошибку)
@ -87,7 +90,7 @@ public class Sdf06Executor {
public Sdf06Executor(ImdgProvider imdgProvider, public Sdf06Executor(ImdgProvider imdgProvider,
IMessageResolver messageResolver, IMessageResolver messageResolver,
@Qualifier("sdf06ValidatorNew") Function<SDf06, IValidator> sDf06Validator, @Qualifier("sdf06ValidatorNew") Function<SDf06, IValidator> sDf06Validator,
TradingTimeService tradingTimeService, KafkaSender kafkaSender, FilenameObtainer filenameObtainer, DmiService dmiService) { TradingTimeService tradingTimeService, KafkaSender kafkaSender, FilenameObtainer filenameObtainer, DmiService dmiService, AssetTBFProcessing assets) {
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.tradingTimeService = tradingTimeService; this.tradingTimeService = tradingTimeService;
@ -102,6 +105,7 @@ public class Sdf06Executor {
this.sdf07Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf07, SDf07.class); this.sdf07Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf07, SDf07.class);
this.filenameObtainer = filenameObtainer; this.filenameObtainer = filenameObtainer;
this.dmiService = dmiService; this.dmiService = dmiService;
this.assets = assets;
} }
public void execute(BaseRequest<StatementRequest> systemRequest) { public void execute(BaseRequest<StatementRequest> systemRequest) {
@ -160,6 +164,8 @@ public class Sdf06Executor {
CurrencyCode.RUB.getKey(), CurrencyCode.RUB.getKey(),
safeBD(sDf06.getSum()), safeBD(sDf06.getSum()),
sDf06.getNumber().toString()); sDf06.getNumber().toString());
Optional<AssetTrio> asts = assets.searchMoneyByAccAndCompany(company.getId(), tcr.getMoneyAccountId());
asts.ifPresent(ast -> assets.process(ast.a__b(), ast.a__t(), ast.a__f(), BigDecimal.ZERO));
} }
sdf07WasCreated = true; sdf07WasCreated = true;
} }
@ -266,11 +272,16 @@ public class Sdf06Executor {
Instant updatedTime = Instant.now(); Instant updatedTime = Instant.now();
if (gatewayMsg.isApproved()) { if (gatewayMsg.isApproved()) {
processedApproved(stmt, sdf06, updatedTime); processedApproved(stmt, sdf06, updatedTime);
dmiService.setProcContract(searchTcrOnGatewayResponse(sdf06).map(SpcexObjectBase::getId).orElse(null), Optional<TradingClearingRegistry> tcr = searchTcrOnGatewayResponse(sdf06);
dmiService.setProcContract(tcr.map(SpcexObjectBase::getId).orElse(null),
CurrencyCode.RUB.getKey(), CurrencyCode.RUB.getKey(),
safeBD(sdf06.getSum()), safeBD(sdf06.getSum()),
sdf06.getNumber().toString() sdf06.getNumber().toString()
); );
if (tcr.isPresent()) {
Optional<AssetTrio> asts = assets.searchMoneyByAccAndCompany(tcr.get().getCompanyId(), tcr.get().getMoneyAccountId());
asts.ifPresent(a -> assets.process(a.a__b(), a.a__t(), a.a__f(), BigDecimal.ZERO));
}
} else { } else {
log.trace("statement.id={}, sdf07.id={}, sdf06.id={} rejected (by gateway answer)", log.trace("statement.id={}, sdf07.id={}, sdf06.id={} rejected (by gateway answer)",
statementId, statementId,

View file

@ -346,6 +346,7 @@ public class Sdf08Executor extends AbstractExecutor<SDf08> {
rgs.setCredit(BigDecimal.ZERO); rgs.setCredit(BigDecimal.ZERO);
rgs.setDiffBalance(BigDecimal.ZERO); rgs.setDiffBalance(BigDecimal.ZERO);
rgs.setCheckBalance(BigDecimal.ZERO); rgs.setCheckBalance(BigDecimal.ZERO);
rgs.setOpenBalance(BigDecimal.ZERO);
rgs.setBalanceDimension(BalanceDimension.MONY.getKey()); rgs.setBalanceDimension(BalanceDimension.MONY.getKey());
rgs.setTradingDate(statement.getSettlementDate()); rgs.setTradingDate(statement.getSettlementDate());
rgs.setClearingDate(LocalDate.now()); rgs.setClearingDate(LocalDate.now());

View file

@ -25,6 +25,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApp
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse; import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse;
import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest; import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.registry.RegistryManager; import ru.spcex.clearing.service.registry.RegistryManager;
import ru.spcex.clearing.service.schedule.TradingTimeService; import ru.spcex.clearing.service.schedule.TradingTimeService;
import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.service.validation.ValidationStored;
@ -68,6 +69,7 @@ public class Sdf10Executor {
private final TradingTimeService tradingTimeService; private final TradingTimeService tradingTimeService;
private final KafkaSender kafkaSender; private final KafkaSender kafkaSender;
private final SecuritySelector<Security> scrtSlct; private final SecuritySelector<Security> scrtSlct;
private final AssetTBFProcessing assets;
private final static String OK = "OK"; private final static String OK = "OK";
private final static String SYNTAX_ERROR = "Синтаксическая ошибка (файл сформирован неверно)"; private final static String SYNTAX_ERROR = "Синтаксическая ошибка (файл сформирован неверно)";
@ -88,7 +90,7 @@ public class Sdf10Executor {
public Sdf10Executor(ImdgProvider imdgProvider, public Sdf10Executor(ImdgProvider imdgProvider,
RegistryManager rgsMng, IMessageResolver messageResolver, RegistryManager rgsMng, IMessageResolver messageResolver,
@Qualifier("sdf10Validator") Function<SDf10, IValidator> sDf10Validator, @Qualifier("sdf10Validator") Function<SDf10, IValidator> sDf10Validator,
TradingTimeService tradingTimeService, KafkaSender kafkaSender) { TradingTimeService tradingTimeService, KafkaSender kafkaSender, AssetTBFProcessing assets) {
this.imdgProvider = imdgProvider; this.imdgProvider = imdgProvider;
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
@ -102,6 +104,7 @@ public class Sdf10Executor {
this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class); this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class);
this.plannerAllTodayImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PlannerAllToday, PlannerAllToday.class); this.plannerAllTodayImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PlannerAllToday, PlannerAllToday.class);
this.scrtSlct = new SecuritySelector<>(imdgProvider, Security.class); this.scrtSlct = new SecuritySelector<>(imdgProvider, Security.class);
this.assets = assets;
} }
public void execute(BaseRequest<StatementRequest> systemRequest) { public void execute(BaseRequest<StatementRequest> systemRequest) {
@ -166,7 +169,11 @@ public class Sdf10Executor {
SDf11 sDf11 = processedApproved(stmt, sDf10, now, sdf11GroupId); SDf11 sDf11 = processedApproved(stmt, sDf10, now, sdf11GroupId);
BigDecimal amount = InOutDirection.in.equalsByKey(stmt.getInOutDirection()) ? BigDecimal amount = InOutDirection.in.equalsByKey(stmt.getInOutDirection()) ?
stmt.getAmount() : safeBD(stmt.getAmount()).negate(); stmt.getAmount() : safeBD(stmt.getAmount()).negate();
createDs_iWithoutGateway(tcr.getId(), company.getId(), security.getSecuritySymbol(), amount, sDf10.getOutDocument()); createDs_iWithoutGateway(tcr.getId(),
company.getId(),
security.getSecuritySymbol(),
amount,
sDf10.getOutDocument());
sdf11WasCreated = true; sdf11WasCreated = true;
} }
} }
@ -190,6 +197,7 @@ public class Sdf10Executor {
return; return;
} }
createDs_i(as_t.get(), summ, outDocument); createDs_i(as_t.get(), summ, outDocument);
assets.processByA__t(as_t.get(), BigDecimal.ZERO);
} }
private void createDs_iWithoutGateway(Long tcrId, Long companyId, String securitySymobl, BigDecimal summ, String outDocument) { private void createDs_iWithoutGateway(Long tcrId, Long companyId, String securitySymobl, BigDecimal summ, String outDocument) {
@ -203,19 +211,19 @@ public class Sdf10Executor {
return; return;
} }
createDs_i(as_t.get(), summ, outDocument); createDs_i(as_t.get(), summ, outDocument);
assets.processByA__t(as_t.get(), BigDecimal.ZERO);
} }
private void createDs_i(Registry as_t, BigDecimal summ, String outDocument) { private void createDs_i(Registry as_t, BigDecimal summ, String outDocument) {
Registry rgsD = as_t.clone(); Registry rgsD = as_t.clone();
RegistryManager.zeroState(rgsD);
rgsD.setRegistryDesignation(RegistryDesignation.D.getKey()); rgsD.setRegistryDesignation(RegistryDesignation.D.getKey());
rgsD.setRegistryUnit(RegistryUnit.I.getKey()); rgsD.setRegistryUnit(RegistryUnit.I.getKey());
rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD)); rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD));
rgsD.setBalance(summ); rgsD.setBalance(summ);
rgsD.setDebit(BigDecimal.ZERO);
rgsD.setCredit(BigDecimal.ZERO);
rgsD.setDiffBalance(BigDecimal.ZERO);
rgsD.setCheckBalance(BigDecimal.ZERO);
rgsD.setRegistryStatus(RegistryStatus.PROC.getKey()); rgsD.setRegistryStatus(RegistryStatus.PROC.getKey());
rgsD.setOpenBalance(BigDecimal.ZERO);
rgsD.setCloseBalance(BigDecimal.ZERO);
rgsD.setContract(outDocument); rgsD.setContract(outDocument);
registryImdg.insert(rgsD); registryImdg.insert(rgsD);
log.debug("created DS*I.id={}", rgsD.getId()); log.debug("created DS*I.id={}", rgsD.getId());

View file

@ -195,7 +195,7 @@ public class Sdf20Executor {
Long securityId) { Long securityId) {
Statement stmt = new Statement(); Statement stmt = new Statement();
stmt.setAddresseeId(companyId); stmt.setAddresseeId(companyId);
stmt.setSenderId(Sender.Prc.getId()); stmt.setSenderId(Sender.Rdc.getId());
stmt.setStatementType(StatementType.incr.getKey()); stmt.setStatementType(StatementType.incr.getKey());
//fixme stmt.setComment(sdf10.()); //fixme stmt.setComment(sdf10.());
stmt.setAccountId(account.getId()); stmt.setAccountId(account.getId());

View file

@ -137,11 +137,11 @@ public class Sdf21Executor extends AbstractExecutor<SDf21> {
result.setChildGenerationId(generationIdForGroup); result.setChildGenerationId(generationIdForGroup);
log.info("SDF21 execution: sdf21 number={}, groupId={}", sdf.size(), sdf.stream().findFirst().map(SDf21::getGenerationId).orElse(null)); log.info("SDF21 execution: sdf21 number={}, groupId={}", sdf.size(), sdf.stream().findFirst().map(SDf21::getGenerationId).orElse(null));
for (SDf21 sdf21 : sdf) { for (SDf21 sdf21 : sdf) {
LocalDate opDt = operationDateParse(sdf21.getOperationDate()); //LocalDate opDt = operationDateParse(sdf21.getOperationDate());
if (opDt == null || !opDt.equals(LocalDate.now())) { //if (opDt == null || !opDt.equals(LocalDate.now())) {
log.debug("skip sdf21.id={}, operation date {}", sdf21.getId(), sdf21.getOperationDate()); // log.debug("skip sdf21.id={}, operation date {}", sdf21.getId(), sdf21.getOperationDate());
continue; // continue;
} //}
IValidator validator = sDf21Validator.apply(sdf21); IValidator validator = sDf21Validator.apply(sdf21);
Optional<EnumMessage> error = validator.tillFirstError(); Optional<EnumMessage> error = validator.tillFirstError();
if (error.isPresent()) { if (error.isPresent()) {
@ -260,7 +260,7 @@ public class Sdf21Executor extends AbstractExecutor<SDf21> {
private Statement create(SDf21 sdf21, Company cmp, Account acc) { private Statement create(SDf21 sdf21, Company cmp, Account acc) {
Statement statement = new Statement(); Statement statement = new Statement();
statement.setAddresseeId(cmp.getId()); statement.setAddresseeId(cmp.getId());
statement.setSenderId(Sender.Prc.getId()); statement.setSenderId(Sender.Rdc.getId());
statement.setStatementType(StatementType.incr.getKey()); statement.setStatementType(StatementType.incr.getKey());
//fixme statement.setComment(sdf21.()); //fixme statement.setComment(sdf21.());
statement.setAccountId(acc.getId()); statement.setAccountId(acc.getId());

View file

@ -48,6 +48,7 @@ import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
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.log.ExceptionUtils;
import ru.spcex.platform.utils.text.TextUtil; import ru.spcex.platform.utils.text.TextUtil;
import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.IValidator;
@ -62,6 +63,7 @@ import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static ru.spcex.platform.enumeration.RegistryTradingParams.D__V; import static ru.spcex.platform.enumeration.RegistryTradingParams.D__V;
@ -167,6 +169,9 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
result.setChildGenerationId(generationIdForGroup); result.setChildGenerationId(generationIdForGroup);
log.info("SDF57 execution: sdf57 number={}, groupId={}", sdf.size(), sdf.stream().findFirst().map(SDf57::getGenerationId).orElse(null)); log.info("SDF57 execution: sdf57 number={}, groupId={}", sdf.size(), sdf.stream().findFirst().map(SDf57::getGenerationId).orElse(null));
AtomicReference<Boolean> sessionIsNeededFlag = new AtomicReference<>(false); AtomicReference<Boolean> sessionIsNeededFlag = new AtomicReference<>(false);
boolean sessionIsPresent = sessionImdg.getFirstObjectByFieldValues(Map.of(
"workflowStatus", SessionStatus.ACTV.getKey()
)) != null;
for (SDf57 sdf57 : sdf) { for (SDf57 sdf57 : sdf) {
IValidator validator = sDf57Validator.apply(sdf57); IValidator validator = sDf57Validator.apply(sdf57);
Optional<EnumMessage> error = validator.tillFirstError(); Optional<EnumMessage> error = validator.tillFirstError();
@ -363,10 +368,11 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
stmt.getId(), asts.a__t().getRegistryCode(), asts.a__t().getId()); stmt.getId(), asts.a__t().getRegistryCode(), asts.a__t().getId());
} else { } else {
log.trace("sending gateway request for stmt.id={}", stmt.getId()); log.trace("sending gateway request for stmt.id={}", stmt.getId());
kafka.sendRequestToQueue(Consts.ASSET_OPERATION, Optional<AssetOperationListRequest> gtwReq = gatewayRequest(stmt,
gatewayRequest(stmt, company,
company.getTradingCode(), account,
asts.a__t().getTradingClearingRegistry())); asts.a__t().getTradingClearingRegistry());
gtwReq.ifPresent(r -> kafka.sendRequestToQueue(Consts.ASSET_OPERATION, r));
} }
} }
return Optional.of(asts); return Optional.of(asts);
@ -393,10 +399,17 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
searchResult.getCompany().getId()); searchResult.getCompany().getId());
asts = createRegistryIfNeeded.apply(new StmtCmpAcc(stmt, searchResult.getCompany(), searchResult.getAccount())); asts = createRegistryIfNeeded.apply(new StmtCmpAcc(stmt, searchResult.getCompany(), searchResult.getAccount()));
if (OperationStatus.Executed.equalsByKey(stmt.getOperationStatus())) { if (OperationStatus.Executed.equalsByKey(stmt.getOperationStatus())) {
dmiService.setOk(searchResult.getTcr().getId(), Optional<BigDecimal> dmiBalance = dmiService.setOk(searchResult.getTcr().getId(),
CurrencyCode.RUB.getKey(), CurrencyCode.RUB.getKey(),
sdf57.getDbfId().toString()); sdf57.getDbfId().toString());
asts.ifPresent(trio -> assets.process(trio.a__b(), trio.a__t(), trio.a__f(), BigDecimal.ZERO)); asts.ifPresent(trio -> {
if (dmiBalance.isPresent() && sessionIsPresent) {
BigDecimal planBalance = safeBD(trio.a__t().getPlanBalance());
trio.a__t().setPlanBalance(planBalance.add(dmiBalance.get()));
registryImdg.update(trio.a__t());
}
assets.process(trio.a__b(), trio.a__t(), trio.a__f(), BigDecimal.ZERO);
});
} }
} else if (InOutDirection.in.equals(IEnumKey.getEnumByKey(InOutDirection.class, stmt.getInOutDirection()))) { } else if (InOutDirection.in.equals(IEnumKey.getEnumByKey(InOutDirection.class, stmt.getInOutDirection()))) {
log.debug("stmt.id={} comment='{}' error: {}. Operating through DMAU registry", log.debug("stmt.id={} comment='{}' error: {}. Operating through DMAU registry",
@ -430,10 +443,17 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
} }
} else if (OperationStatus.Executed.equalsByKey(stmt.getOperationStatus())) { } else if (OperationStatus.Executed.equalsByKey(stmt.getOperationStatus())) {
if (asts.isPresent()) { if (asts.isPresent()) {
dmiService.setOk(asts.get().a__t().getTradingClearingRegistryId(), Optional<BigDecimal> dmiBalance = dmiService.setOk(asts.get().a__t().getTradingClearingRegistryId(),
CurrencyCode.RUB.getKey(), CurrencyCode.RUB.getKey(),
sdf57.getDbfId().toString()); sdf57.getDbfId().toString());
asts.ifPresent(trio -> assets.process(trio.a__b(), trio.a__t(), trio.a__f(), BigDecimal.ZERO)); asts.ifPresent(trio -> {
if (dmiBalance.isPresent() && sessionIsPresent) {
BigDecimal planBalance = safeBD(trio.a__t().getPlanBalance());
trio.a__t().setPlanBalance(planBalance.add(dmiBalance.get()));
registryImdg.update(trio.a__t());
}
assets.process(trio.a__b(), trio.a__t(), trio.a__f(), BigDecimal.ZERO);
});
} else { } else {
log.error("stmt.id={} operationStatus={} but couldn't extract TCR.id for DM*I update", log.error("stmt.id={} operationStatus={} but couldn't extract TCR.id for DM*I update",
stmt.getId(), stmt.getId(),
@ -734,25 +754,56 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
R apply(T1 arg1, T2 arg2, T3 arg3); R apply(T1 arg1, T2 arg2, T3 arg3);
} }
private AssetOperationListRequest gatewayRequest(Statement stmt, String tradingCode, String tcrCode) { private static final Pattern csBlkd = Pattern.compile(SpecifFlag.CS_BLKD.getKey() + "_(\\d+).*");
private Optional<AssetOperationListRequest> gatewayRequest(Statement stmt, Company company, Account account, String tcrCode) {
if (AccountType.Anlt.equalsByKey(account.getAccountType())) {
return Optional.empty();
}
String tradingCode = company.getTradingCode();
AssetOperationListRequest gatewayRequest = new AssetOperationListRequest(); AssetOperationListRequest gatewayRequest = new AssetOperationListRequest();
AssetOperationRequest req = GatewayRequestCreator.from(stmt, tradingCode, tcrCode); AssetOperationRequest req = GatewayRequestCreator.from(stmt, tradingCode, tcrCode);
Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of( String specif = stmt.getComment();
"workflowStatus", SessionStatus.ACTV.getKey()
)); Matcher m;
if (existActiveSession != null) { if (!TextUtil.isEmpty(specif) && (m = csBlkd.matcher(specif)).find()) {
log.debug("active session.id={} type {}", existActiveSession.getId(), existActiveSession.getSessionType()); try {
List<Registry> d__vs = assets.searchByParams(stmt.getAccount(), CurrencyCode.RUB.getKey(), stmt.getSenderId(), D__V) Long sessionId = Long.valueOf(m.group(1));
.stream() List<Registry> d__vs = assets.searchByParams(account.getAccount(), CurrencyCode.RUB.getKey(), company.getId(), D__V)
.filter(rgs -> existActiveSession.getId().equals(rgs.getSessionId())) .stream()
.toList(); .filter(rgs -> sessionId.equals(rgs.getSessionId()))
BigDecimal d__vSum = d__vs.stream() .toList();
.map(rgs -> safeBD(rgs.getBalance())) BigDecimal d__vSum = d__vs.stream()
.reduce(BigDecimal.ZERO, BigDecimal::add); .map(rgs -> safeBD(rgs.getBalance()))
BigDecimal amount = req.getAmount(); .reduce(BigDecimal.ZERO, BigDecimal::add);
req.setAmount(safeBD(amount).subtract(d__vSum)); BigDecimal amount = req.getAmount();
req.setAmount(safeBD(amount).subtract(d__vSum));
} catch (NumberFormatException e) {
log.error("stmt.id={} failed to parse specif {} {}",
stmt.getId(),
specif,
ExceptionUtils.getStackTrace(e));
}
}
//Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of(
// "workflowStatus", SessionStatus.ACTV.getKey()
//));
//if (existActiveSession != null) {
// log.debug("active session.id={} type {}", existActiveSession.getId(), existActiveSession.getSessionType());
// List<Registry> d__vs = assets.searchByParams(stmt.getAccount(), CurrencyCode.RUB.getKey(), stmt.getSenderId(), D__V)
// .stream()
// .filter(rgs -> existActiveSession.getId().equals(rgs.getSessionId()))
// .toList();
// BigDecimal d__vSum = d__vs.stream()
// .map(rgs -> safeBD(rgs.getBalance()))
// .reduce(BigDecimal.ZERO, BigDecimal::add);
// BigDecimal amount = req.getAmount();
// req.setAmount(safeBD(amount).subtract(d__vSum));
//}
if (req.getAmount().compareTo(BigDecimal.ZERO) == 0) {
return Optional.empty();
} }
gatewayRequest.setAssetOperationRequests(List.of(req)); gatewayRequest.setAssetOperationRequests(List.of(req));
return gatewayRequest; return Optional.of(gatewayRequest);
} }
} }

View file

@ -125,12 +125,13 @@ public class PaymentInstructionOutboundService {
log.debug("all checks passed, accCred.id={}, accDeb.id={}, addressee.id={}, sender.id={}, amount: {}", log.debug("all checks passed, accCred.id={}, accDeb.id={}, addressee.id={}, sender.id={}, amount: {}",
accCred.getId(), accDeb.getId(), addressee.getId(), sender.getId(), amount); accCred.getId(), accDeb.getId(), addressee.getId(), sender.getId(), amount);
String purpose = tcr != null ? "Вывод средств по ТКР " + tcr.getCode() + " ." : "Вывод средств."; String purpose = tcr != null ? "Возврат денежных средств, свободных от обязательств с ТКР " + tcr.getCode() + " ." : "Вывод средств.";
if (payload.getPaymentPurpose() != null) { if (payload.getPaymentPurpose() != null) {
purpose += " " + payload.getPaymentPurpose(); String reqPmtPrpse = payload.getPaymentPurpose();
if (!(purpose.endsWith(".") || purpose.endsWith("!") || purpose.endsWith("?") || purpose.endsWith(";"))) { if (!(reqPmtPrpse.endsWith(".") || reqPmtPrpse.endsWith("!") || reqPmtPrpse.endsWith("?") || reqPmtPrpse.endsWith(";"))) {
purpose += "."; reqPmtPrpse += ".";
} }
purpose = reqPmtPrpse + " " + purpose;
} }
PaymentInstruction pmt = PaymentInstructionBuilderV2.builder(imdgProvider) PaymentInstruction pmt = PaymentInstructionBuilderV2.builder(imdgProvider)
.registry(new Registry()) .registry(new Registry())

View file

@ -45,34 +45,62 @@ public class AssetTBFProcessing {
this.rgsMng = new RegistryManager(rgsImdg); this.rgsMng = new RegistryManager(rgsImdg);
} }
//если нет B ссчитаем что он 0
//если нет F надо его создать...
//если нет T журнал WARN и ничего не делаем
public Registry copy(Registry a__t, RegistryUnit rgsUnit) {
Registry a___ = a__t.clone();
a___.setRegistryUnit(rgsUnit.getKey());
a___.setRegistryCode(RegistryUtil.clearingCode(a___));
RegistryManager.zeroState(a___);
return a___;
}
/**
* пересчитывает A**F = A**T - A**B + D**I - D**V
* учитываются только D**I с отрицательным balance.
* @param am_b регистр блокированных средств
* @param am_t регистр средств под торги
* @param am_f регистр свободных средств
* @param sum отнимается от блокировки.
*/
public void process(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) { public void process(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) {
boolean am_bExists = am_b != null;
if (!am_bExists) {
am_b = new Registry();
}
safeWrapField(am_t::getBalance, am_t::setBalance); safeWrapField(am_t::getBalance, am_t::setBalance);
safeWrapField(am_b::getBalance, am_b::setBalance); safeWrapField(am_b::getBalance, am_b::setBalance);
safeWrapField(am_f::getBalance, am_f::setBalance); safeWrapField(am_f::getBalance, am_f::setBalance);
Collection<Registry> d__is = searchByParams(am_b.getAccount(), Collection<Registry> d__is = searchByParams(am_t.getAccount(),
am_b.getSecuritySymbol(), am_t.getSecuritySymbol(),
am_b.getCompanyId(), am_t.getCompanyId(),
D__I.type(am_b.getRegistryInstrumentType())); D__I.type(am_t.getRegistryInstrumentType()));
BigDecimal d__iSum = d__is.stream() BigDecimal d__iSum = d__is.stream()
.filter(d__i -> safeBD(d__i.getBalance()).compareTo(BigDecimal.ZERO) < 0) .filter(d__i -> safeBD(d__i.getBalance()).compareTo(BigDecimal.ZERO) < 0)
.map(rgs -> safeBD(rgs.getBalance())) .map(rgs -> safeBD(rgs.getBalance()))
.reduce(BigDecimal.ZERO, BigDecimal::add); .reduce(BigDecimal.ZERO, BigDecimal::add);
Collection<Registry> d__vs = searchByParams(am_b.getAccount(), Collection<Registry> d__vs = searchByParams(am_t.getAccount(),
am_b.getSecuritySymbol(), am_t.getSecuritySymbol(),
am_b.getCompanyId(), am_t.getCompanyId(),
D__V.type(am_b.getRegistryInstrumentType())); D__V.type(am_t.getRegistryInstrumentType()));
BigDecimal d__vSum = d__vs.stream() BigDecimal d__vSum = d__vs.stream()
.map(rgs -> safeBD(rgs.getBalance())) .map(rgs -> safeBD(rgs.getBalance()))
.reduce(BigDecimal.ZERO, BigDecimal::add); .reduce(BigDecimal.ZERO, BigDecimal::add);
Instant now = Instant.now(); Instant now = Instant.now();
BigDecimal am_fBalanceForLoging = am_f.getBalance(); BigDecimal am_fBalanceForLoging = am_f.getBalance();
BigDecimal am_bBalanceForLoging = am_b.getBalance(); BigDecimal am_bBalanceForLoging = am_b.getBalance();
if (!am_bExists && sum != null && sum.compareTo(BigDecimal.ZERO) != 0) {
log.error("FATAL: A**F.id={}; A**T.id={} A**B is null, yet #sum={}", am_f.getId(), am_t.getId(), sum);
}
am_b.setBalance(am_b.getBalance().subtract(sum)); am_b.setBalance(am_b.getBalance().subtract(sum));
am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance()).add(d__iSum).subtract(d__vSum)); am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance()).add(d__iSum).subtract(d__vSum));
am_b.setUpdated(now); if (am_bExists) {
am_b.setUpdated(now);
rgsImdg.update(am_b);
}
am_f.setUpdated(now); am_f.setUpdated(now);
rgsImdg.update(am_b);
rgsImdg.update(am_f); rgsImdg.update(am_f);
log.debug("assets processing [{}#id={}#balance={} | {}#id={}#balance={} | {}#id={}#balance={}] " + log.debug("assets processing [{}#id={}#balance={} | {}#id={}#balance={} | {}#id={}#balance={}] " +
"D**I.size={} D**V.size={}. {}.balance -> {}, {}.balance -> {}", "D**I.size={} D**V.size={}. {}.balance -> {}, {}.balance -> {}",
@ -134,6 +162,25 @@ public class AssetTBFProcessing {
} }
} }
public Optional<AssetTrio> processByA__t(Registry a__t, BigDecimal sum) {
Optional<Registry> a__b = rgsMng.findRegByUnit(a__t.getCompanyId(),
a__t.getAccountId(),
a__t.getContract(),
a__t,
RegistryUnit.B);
Optional<Registry> a__f = rgsMng.findRegByUnit(a__t.getCompanyId(),
a__t.getAccountId(),
a__t.getContract(),
a__t,
RegistryUnit.F);
if (a__b.isPresent() && a__f.isPresent()) {
process(a__b.get(), a__t, a__f.get(), sum);
return Optional.of(new AssetTrio(a__t, a__b.get(), a__f.get()));
} else {
return Optional.empty();
}
}
public AssetTrio createSAssets(Account acc, public AssetTrio createSAssets(Account acc,
String securitySymbol, String securitySymbol,
Long securityId, Long securityId,
@ -162,15 +209,10 @@ public class AssetTBFProcessing {
ast.setTradingClearingRegistry(tcr); ast.setTradingClearingRegistry(tcr);
ast.setRegistryStatus(RegistryStatus.OK.getKey()); ast.setRegistryStatus(RegistryStatus.OK.getKey());
ast.setBalanceDimension(BalanceDimension.PICS.getKey()); ast.setBalanceDimension(BalanceDimension.PICS.getKey());
ast.setOpenBalance(BigDecimal.ZERO);
RegistryManager.zeroState(ast); RegistryManager.zeroState(ast);
Registry asf = ast.clone(); Registry asf = copy(ast, RegistryUnit.F);
asf.setRegistryUnit(RegistryUnit.F.getKey()); Registry asb = copy(ast, RegistryUnit.B);
asf.setRegistryCode(RegistryUtil.clearingCode(asf));
RegistryManager.zeroState(asf);
Registry asb = ast.clone();
asb.setRegistryUnit(RegistryUnit.B.getKey());
asb.setRegistryCode(RegistryUtil.clearingCode(asb));
RegistryManager.zeroState(asb);
return new AssetTrio(asf, asb, ast); return new AssetTrio(asf, asb, ast);
} }
@ -202,6 +244,7 @@ public class AssetTBFProcessing {
ast.setTradingClearingRegistry(tcr); ast.setTradingClearingRegistry(tcr);
ast.setRegistryStatus(RegistryStatus.OK.getKey()); ast.setRegistryStatus(RegistryStatus.OK.getKey());
ast.setBalanceDimension(BalanceDimension.MONY.getKey()); ast.setBalanceDimension(BalanceDimension.MONY.getKey());
ast.setOpenBalance(BigDecimal.ZERO);
RegistryManager.zeroState(ast); RegistryManager.zeroState(ast);
Registry asf = ast.clone(); Registry asf = ast.clone();
asf.setRegistryUnit(RegistryUnit.F.getKey()); asf.setRegistryUnit(RegistryUnit.F.getKey());
@ -244,6 +287,23 @@ public class AssetTBFProcessing {
return Optional.empty(); return Optional.empty();
} }
public Optional<AssetTrio> searchSecurityByAccAndCompany(Long companyId, Long accountId, String securitySymbol) {
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
Function<RegistryTradingParams, ImdgPredicate> prdct = rgsCode -> pb.and(
pb.sql(RegistryCodeSqlBuilder.getInstance(rgsCode).build()),
pb.equals("companyId", companyId),
pb.equals("accountId", accountId),
pb.equals("securitySymbol", securitySymbol)
);
Registry amf = rgsImdg.getFirstObjectByPredicate(prdct.apply(AS_F));
Registry amb = rgsImdg.getFirstObjectByPredicate(prdct.apply(AS_B));
Registry amt = rgsImdg.getFirstObjectByPredicate(prdct.apply(AS_T));
if (amf != null && amb != null && amt != null) {
return Optional.of(new AssetTrio(amf, amb, amt));
}
return Optional.empty();
}
public boolean insufficientBalance(Registry registry, BigDecimal amount) { public boolean insufficientBalance(Registry registry, BigDecimal amount) {
return safeBD(registry.getBalance()).compareTo(safeBD(amount)) < 0; return safeBD(registry.getBalance()).compareTo(safeBD(amount)) < 0;
} }

View file

@ -4,17 +4,18 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.sdf.SDf57;
import ru.clearing.classes.statics.data.statement.Statement;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.session.stage.util.RegistryUtil; import ru.spcex.clearing.session.stage.util.RegistryUtil;
import ru.spcex.platform.enumeration.RegistryDesignation; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.enumeration.RegistryStatus;
import ru.spcex.platform.enumeration.RegistryTradingParams;
import ru.spcex.platform.enumeration.RegistryUnit;
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.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; 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.log.ExceptionUtils;
import ru.spcex.platform.utils.number.BigDecimalUtil;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.Instant; import java.time.Instant;
@ -24,10 +25,14 @@ import java.util.Optional;
public class DmiService { public class DmiService {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<Registry> rgsImdg; private final Imdg<Registry> rgsImdg;
private final Imdg<SDf57> sDf57Imdg;
private final Imdg<Statement> statementImdg;
private final RegistryManager rgsMng; private final RegistryManager rgsMng;
public DmiService(ImdgProvider imdgProvider, RegistryManager rgsMng) { public DmiService(ImdgProvider imdgProvider, RegistryManager rgsMng) {
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.sDf57Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf57, SDf57.class);
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
this.rgsMng = rgsMng; this.rgsMng = rgsMng;
} }
@ -86,6 +91,33 @@ public class DmiService {
findDmiByComment(tcrId, securitySymbol, comment).ifPresentOrElse(d__i -> { findDmiByComment(tcrId, securitySymbol, comment).ifPresentOrElse(d__i -> {
d__i.setContract(contract); d__i.setContract(contract);
d__i.setUpdated(Instant.now()); d__i.setUpdated(Instant.now());
try {
Long dbfId = Long.valueOf(contract);
SDf57 sdf57 = sDf57Imdg.getFirstObjectBySQL("dbfId=%d".formatted(dbfId));
if (sdf57 != null) {
ImdgPredicateBuilder pb = statementImdg.predicateBuilder();
ImdgPredicate stmtPrdct = pb.and(
pb.equals("inSDfId", sdf57.getId()),
pb.equals("inOutSDfType", InOutSDfType.type57.getKey())
);
Statement stmt = statementImdg.getFirstObjectByPredicate(stmtPrdct);
if (stmt != null && OperationStatus.Executed.equalsByKey(stmt.getOperationStatus())) {
d__i.setRegistryStatus(RegistryStatus.OK.getKey());
} else {
log.warn("tcrId={} securitySymbol={} comment={} sdf57 dbfId={} found, stmt.id={} status {}. d**i status will not be updated",
tcrId,
securitySymbol,
comment,
dbfId,
stmt != null ? stmt.getId() : null,
stmt != null ? stmt.getOperationStatus() : null);
}
}
} catch (Throwable e) {
log.error("sdf57 search by {}: error {}",
contract,
ExceptionUtils.getStackTrace(e));
}
rgsImdg.update(d__i); rgsImdg.update(d__i);
log.trace("set {}.id={} contract {}", d__i.getRegistryCode(), d__i.getId(), contract); log.trace("set {}.id={} contract {}", d__i.getRegistryCode(), d__i.getId(), contract);
}, () -> log.trace("didn't find DM*I by tcr.id={} securitySymbol={} comment={}", }, () -> log.trace("didn't find DM*I by tcr.id={} securitySymbol={} comment={}",
@ -97,18 +129,21 @@ public class DmiService {
* ищем D**I по tcrId/security/contract * ищем D**I по tcrId/security/contract
* задаем статус ОК * задаем статус ОК
*/ */
public void setOk(Long tcrId, public Optional<BigDecimal> setOk(Long tcrId,
String securitySymbol, String securitySymbol,
String contract) { String contract) {
BigDecimal[] dmiBalance = {null};
findDmiByContract(tcrId, securitySymbol, contract).ifPresentOrElse(d__i -> { findDmiByContract(tcrId, securitySymbol, contract).ifPresentOrElse(d__i -> {
d__i.setRegistryStatus(RegistryStatus.OK.getKey()); d__i.setRegistryStatus(RegistryStatus.OK.getKey());
d__i.setUpdated(Instant.now()); d__i.setUpdated(Instant.now());
log.trace("updating {} status to {}", d__i.getRegistryCode(), d__i.getRegistryStatus()); log.trace("updating {} status to {}", d__i.getRegistryCode(), d__i.getRegistryStatus());
rgsImdg.update(d__i); rgsImdg.update(d__i);
dmiBalance[0] = BigDecimalUtil.safeBD(d__i.getBalance());
}, () -> { }, () -> {
log.trace("didn't find DM*I by tcr.id={} securitySymbol={} contract={}", log.trace("didn't find DM*I by tcr.id={} securitySymbol={} contract={}",
tcrId, securitySymbol, contract); tcrId, securitySymbol, contract);
}); });
return Optional.ofNullable(dmiBalance[0]);
} }
private Optional<Registry> findDmiByContract(Long tcrId, String securitySymbol, String contract) { private Optional<Registry> findDmiByContract(Long tcrId, String securitySymbol, String contract) {
@ -156,15 +191,14 @@ public class DmiService {
return Optional.empty(); return Optional.empty();
} }
Registry rgsD = am_t.clone(); Registry rgsD = am_t.clone();
RegistryManager.zeroState(rgsD);
rgsD.setOpenBalance(BigDecimal.ZERO);
rgsD.setCloseBalance(BigDecimal.ZERO);
rgsD.setRegistryDesignation(RegistryDesignation.D.getKey()); rgsD.setRegistryDesignation(RegistryDesignation.D.getKey());
rgsD.setRegistryUnit(RegistryUnit.I.getKey()); rgsD.setRegistryUnit(RegistryUnit.I.getKey());
rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD)); rgsD.setRegistryCode(RegistryUtil.clearingCode(rgsD));
rgsD.setBalance(summ); rgsD.setBalance(summ);
rgsD.setDebit(BigDecimal.ZERO);
rgsD.setCredit(BigDecimal.ZERO);
rgsD.setDiffBalance(BigDecimal.ZERO);
rgsD.setCheckBalance(BigDecimal.ZERO);
rgsD.setRegistryStatus(RegistryStatus.PROC.getKey()); rgsD.setRegistryStatus(RegistryStatus.PROC.getKey());
return Optional.of(rgsD); return Optional.of(rgsD);
} }

View file

@ -56,7 +56,7 @@ public class PaymentStateMarkService {
.stream() .stream()
.filter(rgs -> rgs.getValueDate() != null) .filter(rgs -> rgs.getValueDate() != null)
.filter(rgs -> rgs.getSettlementDate() != null) .filter(rgs -> rgs.getSettlementDate() != null)
.filter(rgs -> rgs.getSettlementDate().isAfter(rgs.getValueDate())) .filter(rgs -> rgs.getSettlementDate().equals(rgs.getValueDate()))
.collect(Collectors.groupingBy(Registry::getGroupId)); .collect(Collectors.groupingBy(Registry::getGroupId));
log.debug("found {} ({} groups) CM*T/LM*T by {}", claimsAndLiabilities.size(), groups.size(), prdct.toString()); log.debug("found {} ({} groups) CM*T/LM*T by {}", claimsAndLiabilities.size(), groups.size(), prdct.toString());
for (Map.Entry<Long, List<Registry>> group : groups.entrySet()) { for (Map.Entry<Long, List<Registry>> group : groups.entrySet()) {

View file

@ -38,11 +38,17 @@ public class RegistryManager {
public Optional<Registry> searchDmxByCounterParty(Registry rgs) { public Optional<Registry> searchDmxByCounterParty(Registry rgs) {
if (TextUtil.isEmpty(rgs.getContract())) return Optional.empty(); if (TextUtil.isEmpty(rgs.getContract())) return Optional.empty();
String sqlCondition = String.format("(%s) and companyId = %d and contract = '%s'", ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
RegistryCodeSqlBuilder.getInstance(DM_X).build(), ImdgPredicate prdct = pb.and(
rgs.getCounterPartyId(), pb.sql(RegistryCodeSqlBuilder.getInstance(DM_X).build()),
rgs.getContract()); pb.equals("companyId", rgs.getCounterPartyId()),
Registry dmx = rgsImdg.getFirstObjectBySQL(sqlCondition); pb.equals("contract", rgs.getContract()),
pb.or(
pb.equals("registryStatus", RegistryStatus.PROC.getKey()),
pb.equals("registryStatus", RegistryStatus.MNG.getKey())
)
);
Registry dmx = rgsImdg.getFirstObjectByPredicate(prdct);
return Optional.ofNullable(dmx); return Optional.ofNullable(dmx);
} }

View file

@ -131,7 +131,7 @@ public enum Sdf06NewValidationRule implements IValidationRule<ImdgValidationCont
prdctBldr.and( prdctBldr.and(
prdctByRegistryCode.apply(RegistryTradingParams.DM_T), prdctByRegistryCode.apply(RegistryTradingParams.DM_T),
prdctBldr.or( prdctBldr.or(
prdctBldr.equals("registryStatus", RegistryStatus.OK.getKey()), prdctBldr.equals("registryStatus", RegistryStatus.PROC.getKey()),
prdctBldr.equals("registryStatus", RegistryStatus.MNG.getKey()) prdctBldr.equals("registryStatus", RegistryStatus.MNG.getKey())
) )
) )

View file

@ -12,9 +12,7 @@ import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.service.AssetTrio; import ru.spcex.clearing.service.AssetTrio;
import ru.spcex.clearing.service.registry.RegistryManager; import ru.spcex.clearing.service.registry.RegistryManager;
import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.enumeration.*;
import ru.spcex.platform.enumeration.NoRef;
import ru.spcex.platform.enumeration.OperationCode;
import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
@ -67,6 +65,12 @@ public enum Sdf20ValidationRule implements IValidationRule<ImdgValidationContext
if (acc == null) { if (acc == null) {
return of(ClearingError.AccountNotFoundB, depoCodeCl); return of(ClearingError.AccountNotFoundB, depoCodeCl);
} }
ServiceStatus status = IEnumKey.getEnumByKey(ServiceStatus.class, acc.getStatus());
if (!ServiceStatus.Active.equals(status)
&& !ServiceStatus.Reopened.equals(status)
&& !ServiceStatus.Appl.equals(status)) {
return of(ClearingError.AccountNotActive, acc.getId());
}
context.storeObject(ValidationStored.Sdf20Account, acc); context.storeObject(ValidationStored.Sdf20Account, acc);
return empty(); return empty();
} }
@ -86,6 +90,9 @@ public enum Sdf20ValidationRule implements IValidationRule<ImdgValidationContext
if (company == null) { if (company == null) {
return of(ClearingError.CompanyNotFoundB, acc.getCompanyId()); return of(ClearingError.CompanyNotFoundB, acc.getCompanyId());
} }
if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
return of(ClearingError.CompanyNotActive, company.getId());
}
context.storeObject(ValidationStored.Sdf20Company, company); context.storeObject(ValidationStored.Sdf20Company, company);
return empty(); return empty();
} }

View file

@ -0,0 +1,55 @@
package ru.spcex.clearing.service.validation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.misc.Session;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.session.stage.TaskType;
import ru.spcex.platform.enumeration.SessionStatus;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumKey;
import ru.spcex.platform.utils.validation.IValidationRule;
import java.util.Map;
import java.util.Optional;
public enum SessionTerminationValidationRule implements IValidationRule<ImdgValidationContext<Session>> {
SessionPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<Session> context) {
Imdg<Session> sessionImdg = context.obtainMap(IMDGDistributedNames.Map_Session, Session.class);
Session session = sessionImdg.getFirstObjectByFieldValues(Map.of(
"workflowStatus", SessionStatus.ACTV.getKey()
));
if (session == null) {
log.warn("Cannot stop session, failed to find workflowStatus 'ACTV'");
return of(ClearingError.RecordNotFound, "с активной клиринговой сессией для обнуления");
}
context.storeObject(ValidationStored.SessionTerminate, session);
context.setValidatedObject(session);
return empty();
}
},
StatusCheck() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<Session> context) {
Session session = context.getStoredObject(ValidationStored.SessionTerminate);
TaskType status = IEnumKey.getEnumByKey(TaskType.class, session.getSessionStatus());
if (status == null || status.ordinal() >= TaskType.FormingPaymentInstruction.ordinal()) {
log.warn("Cannot stop session.id={}, unknown sessionStatus '{}'",
session.getId(), session.getSessionStatus());
return of(ClearingError.IncorrectValue, "статуса для обнуления клиринговой сессии");
}
return empty();
}
}
;
private final static Logger log = LoggerFactory.getLogger(SessionTerminationValidationRule.class);
@Override
public String ruleName() {
return "SessionTerminationValidationRule." + name();
}
}

View file

@ -63,7 +63,7 @@ public enum StatusExtractValidationRule implements IValidationRule<ImdgValidatio
return empty(); return empty();
} }
}, },
RegistryStatusValid() { RequestStatusValid() {
@Override @Override
public Optional<EnumMessage> validate(ImdgValidationContext<RegistryChangeStatusExtractRequest> context) { public Optional<EnumMessage> validate(ImdgValidationContext<RegistryChangeStatusExtractRequest> context) {
RegistryChangeStatusExtractRequest validatedObject = context.getValidatedObject(); RegistryChangeStatusExtractRequest validatedObject = context.getValidatedObject();
@ -76,6 +76,17 @@ public enum StatusExtractValidationRule implements IValidationRule<ImdgValidatio
} }
return empty(); return empty();
} }
},
RegistryStatusValid() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<RegistryChangeStatusExtractRequest> context) {
Registry rgs = context.getStoredObject(Stored.PresentById);
RegistryStatus status = IEnumKey.getEnumByKey(RegistryStatus.class, rgs.getRegistryStatus());
if (RegistryStatus.OK.equals(status)) {
return of(ClearingError.ObligationsAlreadyCalculated);
}
return empty();
}
} }
; ;
private final static Logger log = LoggerFactory.getLogger(StatusExtractValidationRule.class); private final static Logger log = LoggerFactory.getLogger(StatusExtractValidationRule.class);

View file

@ -32,5 +32,7 @@ public enum ValidationStored {
SecurityBySecurityCode, SecurityBySecurityCode,
SessionTerminate,
RegistrysByContract, SplitDepositMaxNumber RegistrysByContract, SplitDepositMaxNumber
} }

View file

@ -105,6 +105,11 @@ public abstract class AbstractSession {
protected void continueRunning(TaskType t) { protected void continueRunning(TaskType t) {
synchronized (this.currStage) { synchronized (this.currStage) {
//if (WorkflowStatus.Blocked.equalsByKey(this.currSession.getWorkflowStatus())) {
// log.error("cannot run task {}.{}. session.id={} workflowStatus is {}",
// t, t.getKey(), this.currSession.getId(), this.currSession.getWorkflowStatus());
// throw new StageException();
//}
this.currStage.set(t); this.currStage.set(t);
this.currSession.setSessionStatus(t.getKey()); this.currSession.setSessionStatus(t.getKey());
this.currSession.setUpdated(Instant.now()); this.currSession.setUpdated(Instant.now());

View file

@ -112,6 +112,7 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean
inspectionObligations.setSection(section()); inspectionObligations.setSection(section());
formingPaymentInstructionDeals.setSection(section()); formingPaymentInstructionDeals.setSection(section());
formingPaymentInstructionDeals.setSessionType(sessionType()); formingPaymentInstructionDeals.setSessionType(sessionType());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -106,6 +106,7 @@ public class IntermediateMkrSession extends AbstractSession implements Initializ
inspectionObligations.setSection(section()); inspectionObligations.setSection(section());
formingPaymentInstructionDeals.setSection(section()); formingPaymentInstructionDeals.setSection(section());
formingPaymentInstructionDeals.setSessionType(sessionType()); formingPaymentInstructionDeals.setSessionType(sessionType());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -98,6 +98,7 @@ public class PrimaryAuctionB0Session extends AbstractSession implements Initiali
inclusionObligations.setSessionType(sessionType()); inclusionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section()); inspectionObligations.setSection(section());
finishingSession.setSection(section()); finishingSession.setSection(section());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -99,6 +99,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali
inclusionObligations.setSessionType(sessionType()); inclusionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section()); inspectionObligations.setSection(section());
finishingSession.setSection(section()); finishingSession.setSection(section());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -99,6 +99,7 @@ public class PrimaryAuctionT0Session extends AbstractSession implements Initiali
inclusionObligations.setSessionType(sessionType()); inclusionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section()); inspectionObligations.setSection(section());
finishingSession.setSection(section()); finishingSession.setSection(section());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -90,6 +90,7 @@ public class ReturnDepositSession extends AbstractSession implements Initializin
rgsPrctBuilder.less("valueDate", LocalDate.now()) rgsPrctBuilder.less("valueDate", LocalDate.now())
) )
); );
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -93,6 +93,7 @@ public class SecondaryAuctionT0Session extends AbstractSession implements Initia
inclusionObligations.setSessionType(sessionType()); inclusionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section()); inspectionObligations.setSection(section());
finishingSession.setSection(section()); finishingSession.setSection(section());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable(); imdgProvider.waitAvailable();
initSessionIfPresent(); initSessionIfPresent();
} }

View file

@ -66,17 +66,7 @@ public class SessionManager {
return; return;
} }
BaseRequest<?> baseRequest = new BaseRequest<>(); BaseRequest<?> baseRequest = new BaseRequest<>();
AbstractSession session = null; AbstractSession session = sessionByType(sessionType);
switch (sessionType){
case IPOB -> session = primaryAuctionBnSession;
case IPOT -> session = primaryAuctionT0Session;
case IPO0 -> session = primaryAuctionB0Session;
case TRDT -> session = secondaryAuctionT0Session;
case MEDM -> session = intermediateMkrSession;
case FINL -> session = finalMkrSession;
case XDEP -> session = returnDepositSession;
}
if (session != null) { if (session != null) {
//checkActive //checkActive
checkAllowSessionStart(); checkAllowSessionStart();
@ -99,4 +89,30 @@ public class SessionManager {
throw new ValidationException(err); throw new ValidationException(err);
} }
} }
public void endSession(Session session) {
SessionType sessionType = IEnumKey.getEnumByKey(SessionType.class, session.getSessionType());
String err = "failed to stop session.id=%d: unknown sessionType: %s"
.formatted(session.getId(), session.getSessionType());
if (sessionType == null) {
throw new IllegalStateException(err);
}
AbstractSession sessionFlow = sessionByType(sessionType);
if (sessionFlow == null) throw new IllegalStateException(err);
sessionFlow.endSession();
}
private AbstractSession sessionByType(SessionType sessionType) {
AbstractSession session = null;
switch (sessionType){
case IPOB -> session = primaryAuctionBnSession;
case IPOT -> session = primaryAuctionT0Session;
case IPO0 -> session = primaryAuctionB0Session;
case TRDT -> session = secondaryAuctionT0Session;
case MEDM -> session = intermediateMkrSession;
case FINL -> session = finalMkrSession;
case XDEP -> session = returnDepositSession;
}
return session;
}
} }

View file

@ -0,0 +1,151 @@
package ru.spcex.clearing.session.stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
import ru.clearing.classes.statics.data.execution.ExecutionFond;
import ru.clearing.classes.statics.data.misc.Session;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.notification.NotificationSender;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.validation.ValidationStored;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.ObjectType;
import ru.spcex.platform.enumeration.Priority;
import ru.spcex.platform.enumeration.RegistryTradingParams;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.imdg.api.Imdg;
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.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.validation.IValidator;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.Collection;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
@Service
public class SessionTerminator {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<ExecutionDeposit> execDpstImdg;
private final Imdg<ExecutionFond> execFondImdg;
private final Imdg<Registry> rgsImdg;
private final NotificationSender notification;
private final AssetTBFProcessing assets;
private final IMessageResolver msgs;
private final RequestHelper reqInfo;
private final Supplier<IValidator> validation;
private final SessionManager sessionMng;
public SessionTerminator(ImdgProvider imdgProvider,
NotificationSender notification,
AssetTBFProcessing assets, IMessageResolver msgs,
RequestHelper reqInfo,
@Qualifier("terminateSessionValidator") Supplier<IValidator> validation, SessionManager sessionMng) {
this.notification = notification;
this.assets = assets;
this.msgs = msgs;
this.execDpstImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
this.execFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.reqInfo = reqInfo;
this.validation = validation;
this.sessionMng = sessionMng;
}
public RequestInfoUpdate stopCurrentSession(BaseRequest<?> req) {
IValidator validator = validation.get();
Optional<EnumMessage> err = validator.tillFirstError();
if (err.isPresent()) {
notification.sendNotification(ObjectType.session, msgs.resolve(err.get()), Priority.HIGH);
return reqInfo.error(req.getId(), err.get());
}
Session session = validator.getStored(ValidationStored.SessionTerminate);
rollbackExecutions(session);
rollbackAssetBalances(session.getId());
deleteLiabilitiesAndClaims(session.getId());
sessionMng.endSession(session);
return reqInfo.success(session.getId());
}
private void rollbackExecutions(Session session) {
Instant now = Instant.now();
Consumer<Imdg<ExecutionCommon>> nullifier = imdg -> {
Collection<ExecutionCommon> execs = imdg.getCollectionObjectsBySQL(
"sessionId = " + session.getId()
);
for (ExecutionCommon exec : execs) {
exec.setSessionId(null);
exec.setCoverageStatus(null);
exec.setUpdated(now);
imdg.update(exec);
}
log.info("updated {} executions with sessionId={}", execs.size(), session.getId());
};
log.debug("session.id={} section {}", session.getId(), session.getSection());
if (Section.FOND.equalsByKey(session.getSection())) {
nullifier.accept(upcastImdg(execFondImdg));
} else if (Section.MKR.equalsByKey(session.getSection())) {
nullifier.accept(upcastImdg(execDpstImdg));
} else throw new IllegalStateException("unknown section.");
}
private void rollbackAssetBalances(Long sessionId) {
Instant now = Instant.now();
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.equals("sessionId", sessionId),
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.A__B).build()),
pb.not(pb.equals("balance", BigDecimal.ZERO))
);
Collection<Registry> a__bs = rgsImdg.getCollectionObjectsByPredicate(prdct);
a__bs.forEach(rgs -> {
rgs.setBalance(BigDecimal.ZERO);
rgs.setUpdated(now);
rgsImdg.update(rgs);
assets.processByAm_b(rgs, BigDecimal.ZERO);
});
log.debug("set ZERO balance for {} A**B by predicate: {}", a__bs.size(), prdct);
}
private void deleteLiabilitiesAndClaims(Long sessionId) {
ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.equals("sessionId", sessionId),
pb.or(
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.C__T).build()),
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.L__T).build()),
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.O__T).build()),
pb.sql(RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.T__T).build())
)
);
Collection<Registry> liabilitiesAndClaims = rgsImdg.getCollectionObjectsByPredicate(prdct);
liabilitiesAndClaims.forEach(rgsImdg::delete);
log.debug("deleted {} liabilities and claims by predicate: {}", liabilitiesAndClaims.size(), prdct);
}
private static <T extends SpcexObjectBase, U extends T> Imdg<T> upcastImdg(Imdg<U> imdg) {
@SuppressWarnings("unchecked")
Imdg<T> result = (Imdg<T>) imdg;
return result;
}
}

View file

@ -28,17 +28,22 @@ import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; 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 java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.*; import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import static ru.spcex.clearing.error.ClearingErrorInternal.SessionGeneralError; import static ru.spcex.clearing.error.ClearingErrorInternal.SessionGeneralError;
import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey;
@Service @Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@ -55,6 +60,7 @@ public class FinishingSession implements ISessionStage {
private final IMessageResolver msgResolver; private final IMessageResolver msgResolver;
private final Sdf05Sender sdf05Sender; private final Sdf05Sender sdf05Sender;
private final Sdf14Sender sdf14Sender; private final Sdf14Sender sdf14Sender;
private SessionType sessionType;
private Section section; private Section section;
@Autowired @Autowired
@ -74,6 +80,9 @@ public class FinishingSession implements ISessionStage {
public void setSection(Section section) { public void setSection(Section section) {
this.section = section; this.section = section;
} }
public void setSessionType(SessionType sessionType) {
this.sessionType = sessionType;
}
@Override @Override
public StageResult<?> submit(Task<?> task) { public StageResult<?> submit(Task<?> task) {
@ -106,48 +115,79 @@ public class FinishingSession implements ISessionStage {
log.error("Session id={} not found. Can not update Execution's.", sessionId); log.error("Session id={} not found. Can not update Execution's.", sessionId);
} else { } else {
Collection<Registry> oRegs = findORegistryBySessionId(sessionId); Collection<Registry> oRegs = findORegistryBySessionId(sessionId);
Set<Long> exchangeExecutionIdAllowed = oRegs.stream() Map<Long, RegistryStatus> obligationStatusByGroupId;
.filter(rgs -> RegistryStatus.CLRD.equalsByKey(rgs.getRegistryStatus())) obligationStatusByGroupId = oRegs.stream()
.map(Registry::getGroupId) // Registry::getGroupId == Execution.ExchangeExecutionId, см. RegistryFondBuilder/RegistryDepoBuilder .map(rgs -> new Pair<>(rgs.getGroupId(), getEnumByKey(RegistryStatus.class, rgs.getRegistryStatus())))
.collect(Collectors.toSet()); .filter(pair -> pair.getSecond() != null)
.collect(Collectors.toMap(Pair::getFirst, Pair::getSecond, (o1, o2) -> o1));
Function<Long, CoverageStatus> statusByExchangeId = id-> {
RegistryStatus obligationStatus = obligationStatusByGroupId.get(id);
if (obligationStatus == null) return null;
return switch (obligationStatus) {
case CLRD -> CoverageStatus.ALWD;
case FAIL, UNCV, NACK, NACC -> CoverageStatus.DEND;
default -> null;
};
};
Set<Long> exchangeExecutionIdsPreviousDay = oRegs.stream() Set<Long> exchangeExecutionIdsPreviousDay = oRegs.stream()
.filter(rgs -> Objects.nonNull(rgs.getSettlementDate())) .filter(rgs -> Objects.nonNull(rgs.getSettlementDate()))
.filter(rgs -> Objects.nonNull(rgs.getTradingDate())) .filter(rgs -> Objects.nonNull(rgs.getTradingDate()))
.filter(rgs -> rgs.getSettlementDate().compareTo(rgs.getTradingDate()) > 0) .filter(rgs -> rgs.getSettlementDate().compareTo(rgs.getTradingDate()) > 0)
.map(Registry::getGroupId) .map(Registry::getGroupId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
log.trace("obligations number with second leg in the past: {}", exchangeExecutionIdsPreviousDay.size());
int allowed = 0;
int notAllowed = 0;
if (IEnumKey.contains(session.getSessionType(), SessionType.FINL, SessionType.MEDM)) { if (IEnumKey.contains(session.getSessionType(), SessionType.FINL, SessionType.MEDM)) {
Collection<ExecutionDeposit> executions = findExecutionDepositBySessionId(sessionId); Collection<ExecutionDeposit> executions = findExecutionDepositBySessionId(sessionId);
int notAllowed = 0; log.trace("loaded {} ExecutionDeposits for sessionId {}", executions.size(), sessionId);
for (ExecutionDeposit execution : executions) { for (ExecutionDeposit execution : executions) {
CoverageStatus toStatus = exchangeExecutionIdAllowed.contains(execution.getExchangeExecutionId()) ? CoverageStatus toStatus = statusByExchangeId.apply(execution.getExchangeExecutionId());
CoverageStatus.ALWD : CoverageStatus.DEND; if (toStatus == null) {
if (toStatus == CoverageStatus.DEND) log.trace("CoverageStatus not defined for execution.id={}", execution.getId());
continue;
}
if (toStatus == CoverageStatus.DEND) {
notAllowed++; notAllowed++;
}
if (toStatus == CoverageStatus.ALWD) {
allowed++;
}
execution.setCoverageStatus(toStatus.getKey()); execution.setCoverageStatus(toStatus.getKey());
execution.setUpdated(Instant.now()); execution.setUpdated(Instant.now());
executionDepositImdg.update(execution); executionDepositImdg.update(execution);
} }
log.trace("By sessionId={} update {} ExecutionDeposit: {} allowed, {} denied", sessionId, log.trace("By sessionId={} processed {} ExecutionDeposit: {} allowed, {} denied, skipped {}",
executions.size(), exchangeExecutionIdAllowed.size(), notAllowed); sessionId,
executions.size(),
allowed,
notAllowed,
executions.size() - (allowed + notAllowed));
} else if (IEnumKey.contains(session.getSessionType(), SessionType.TRDT, SessionType.IPOB, SessionType.IPO0, SessionType.IPOT)) { } else if (IEnumKey.contains(session.getSessionType(), SessionType.TRDT, SessionType.IPOB, SessionType.IPO0, SessionType.IPOT)) {
List<ExecutionFond> executions = Stream.concat( Collection<ExecutionFond> executions = findExecutionFondBySessionId(sessionId);
findExecutionFondBySessionId(sessionId).stream(), log.trace("loaded {} ExecutionFonds for sessionId {}", executions.size(), sessionId);
findExecutionFondBySessionId(exchangeExecutionIdsPreviousDay).stream())
.toList();
int notAllowed = 0;
for (ExecutionFond execution : executions) { for (ExecutionFond execution : executions) {
CoverageStatus toStatus = exchangeExecutionIdAllowed.contains(execution.getExchangeExecutionId()) ? CoverageStatus toStatus = statusByExchangeId.apply(execution.getExchangeExecutionId());
CoverageStatus.ALWD : CoverageStatus.DEND; if (toStatus == null) {
if (toStatus == CoverageStatus.DEND) log.trace("CoverageStatus not defined for execution.id={}", execution.getId());
continue;
}
if (toStatus == CoverageStatus.DEND) {
notAllowed++; notAllowed++;
}
if (toStatus == CoverageStatus.ALWD) {
allowed++;
}
execution.setCoverageStatus(toStatus.getKey()); execution.setCoverageStatus(toStatus.getKey());
execution.setUpdated(Instant.now()); execution.setUpdated(Instant.now());
executionFondImdg.update(execution); executionFondImdg.update(execution);
} }
log.trace("By sessionId={} update {} ExecutionFond: {} allowed, {} denied", sessionId, log.trace("By sessionId={} processed {} ExecutionFond: allowed {}, denied {}, skipped {}",
executions.size(), exchangeExecutionIdAllowed.size(), notAllowed); sessionId,
executions.size(),
allowed,
notAllowed,
executions.size() - (allowed + notAllowed));
} else { } else {
log.warn("Unsupported session[{}].SessionType={} for update Executions", sessionId, session.getSessionType()); log.warn("Unsupported session[{}].SessionType={} for update Executions", sessionId, session.getSessionType());
} }
@ -163,7 +203,7 @@ public class FinishingSession implements ISessionStage {
return sResult; return sResult;
} }
for (Registry registryA : forRegistries) { for (Registry registryA : forRegistries) {
if (!RegistryDesignation.A.equalsByKey(registryA.getRegistryUnit())) { if (!RegistryDesignation.A.equalsByKey(registryA.getRegistryUnit())) { //fixme Unit -> Designation
log.warn("For registry {}.RegistryDesignation is not A.", registryA.getId()); log.warn("For registry {}.RegistryDesignation is not A.", registryA.getId());
continue; continue;
} }
@ -247,37 +287,43 @@ public class FinishingSession implements ISessionStage {
// registryStatus - любой статус // registryStatus - любой статус
pb.equals("registryDesignation", RegistryDesignation.O.getKey())); pb.equals("registryDesignation", RegistryDesignation.O.getKey()));
Collection<Registry> result = registryImdg.getCollectionObjectsByPredicate(prdct); Collection<Registry> result = registryImdg.getCollectionObjectsByPredicate(prdct);
log.trace("found {} liabilities by query {} ", result.size(), prdct); int size = result.size();
result = result.stream() result = result.stream()
.filter(registry -> Objects.equals(registry.getSettlementDate(), LocalDate.now())) .filter(registry -> Objects.equals(registry.getSettlementDate(), LocalDate.now()))
.filter(registry -> Objects.equals(registry.getValueDate(), registry.getSettlementDate())) .filter(registry -> Objects.equals(registry.getValueDate(), registry.getSettlementDate()))
.collect(Collectors.toList()); .collect(Collectors.toList());
log.debug("found {} liabilities 'O' by query {} and ValueDate==SettlementDate", result.size(), prdct); log.debug("found {} liabilities by query {} and {} liabilities after filtering ValueDate==SettlementDate",
size, result.size(), prdct);
return result; return result;
} }
protected Collection<ExecutionFond> findExecutionFondBySessionId(Long sessionId) { protected Collection<ExecutionFond> findExecutionFondBySessionId(Long sessionId) {
ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder(); ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder();
ImdgPredicate prdct = pb.and( ImdgPredicate prdct = pb.or(
pb.equals("sessionId", sessionId), pb.equals("sessionId", sessionId),
pb.equals("settlementDate", LocalDate.now()) pb.equals("settlementDate", LocalDate.now())
); );
Collection<ExecutionFond> result = executionFondImdg.getCollectionObjectsByPredicate(prdct); Collection<ExecutionFond> result = executionFondImdg.getCollectionObjectsByPredicate(prdct)
.stream()
.filter(eFond -> Objects.nonNull(eFond.getSessionId()))
.filter(eFond -> {
if (sessionId.equals(eFond.getSessionId())) return true;
Session session = sessionImdg.getSingleObjectByID(eFond.getSessionId());
return sessionType.equalsByKey(session.getSessionType());
})
.toList();
log.trace("found {} ExecutionFond by sessionId={}", result.size(), sessionId); log.trace("found {} ExecutionFond by sessionId={}", result.size(), sessionId);
return result; return result;
} }
protected Collection<ExecutionFond> findExecutionFondBySessionId(Set<Long> exchangeIds) {
ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder();
ImdgPredicate prdct = pb.in("exchangeExecutionId", exchangeIds.toArray(new Long[0]));
Collection<ExecutionFond> result = executionFondImdg.getCollectionObjectsByPredicate(prdct);
log.trace("found {} ExecutionFond from first day", result.size());
return result;
}
protected Collection<ExecutionDeposit> findExecutionDepositBySessionId(Long sessionId) { protected Collection<ExecutionDeposit> findExecutionDepositBySessionId(Long sessionId) {
Collection<ExecutionDeposit> result = executionDepositImdg.getCollectionObjectsByFieldValues(Map.of("sessionId", sessionId)); ImdgPredicateBuilder pb = executionDepositImdg.predicateBuilder();
log.trace("found {} ExecutionDeposit by sessionId={}", result.size(), sessionId); ImdgPredicate prdct = pb.or(
pb.equals("sessionId", sessionId),
pb.equals("firstLegSettlementDate", LocalDate.now())
);
Collection<ExecutionDeposit> result = executionDepositImdg.getCollectionObjectsByPredicate(prdct);
log.trace("found {} ExecutionDeposit by {}", result.size(), prdct);
return result; return result;
} }

View file

@ -215,6 +215,8 @@ public class FormingPaymentInstructionAssets implements ISessionStage {
.creditLegAccount(creditLegAccount) .creditLegAccount(creditLegAccount)
.amount(amount) .amount(amount)
.sessionId(sessionId) .sessionId(sessionId)
.checkBLKD((SessionType.FINL.equals(sessionType) || SessionType.MEDM.equals(sessionType))
&& !isPositiveBalance ? registry : null)
.purpose(String.format("Перевод по итогу клиринга по ТКР %s", registry.getTradingClearingRegistry())); .purpose(String.format("Перевод по итогу клиринга по ТКР %s", registry.getTradingClearingRegistry()));
PaymentInstruction paymentInstruction = paymentInstructionBuilder.build(); PaymentInstruction paymentInstruction = paymentInstructionBuilder.build();
log.debug("Created paymentInstruction by registry.id: {}", registry.getId()); log.debug("Created paymentInstruction by registry.id: {}", registry.getId());

View file

@ -154,7 +154,7 @@ public class FormingPaymentInstructionSecurities implements ISessionStage {
.stream() .stream()
.collect(Collectors.groupingBy(Registry::getGroupId)); .collect(Collectors.groupingBy(Registry::getGroupId));
log.debug("groups.size = {}", groups.size()); log.debug("groups.size = {}", groups.size());
Map<Long, PaymentGroup> lstGroups = RegistryLiabilitiesGroup.group(registries); Map<Long, PaymentGroup> lstGroups = RegistryLiabilitiesGroup.group(groups);
for (Map.Entry<Long, List<Registry>> group : groups.entrySet()) { for (Map.Entry<Long, List<Registry>> group : groups.entrySet()) {
Long groupId = group.getKey(); Long groupId = group.getKey();
Function<RegistryTradingParams, Registry> findByCode = rgsCode -> group.getValue() Function<RegistryTradingParams, Registry> findByCode = rgsCode -> group.getValue()

View file

@ -4,44 +4,56 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.service.registry.RegistryManager; import ru.spcex.clearing.service.registry.RegistryManager;
import ru.spcex.platform.enumeration.RegistryTradingParams;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.text.TextUtil;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static ru.spcex.platform.enumeration.RegistryTradingParams.CS_T;
import static ru.spcex.platform.enumeration.RegistryTradingParams.LS_T; import static ru.spcex.platform.enumeration.RegistryTradingParams.LS_T;
public class RegistryLiabilitiesGroup { public class RegistryLiabilitiesGroup {
private Logger log = LoggerFactory.getLogger(getClass()); private static final Logger log = LoggerFactory.getLogger(RegistryLiabilitiesGroup.class);
public static RegistryLiabilitiesGroup builder() { public static Map<Long, PaymentGroup> group(Map<Long, List<Registry>> registriesCollection) {
return new RegistryLiabilitiesGroup();
}
private RegistryLiabilitiesGroup() {
}
public static Map<Long, PaymentGroup> group(Collection<Registry> registriesCollection) {
Map<Long, PaymentGroup> result = new HashMap<>(); Map<Long, PaymentGroup> result = new HashMap<>();
List<Registry> registries = registriesCollection List<Pair<Registry, Registry>> lstCstGroup = registriesCollection.entrySet()
.stream() .stream()
.filter(rgs -> RegistryManager.equalsByCode(LS_T, rgs)) .map(entry -> {
Long groupId = entry.getKey();
List<Registry> value = entry.getValue();
Registry ls_t = obtain(value, LS_T);
Registry cs_t = obtain(value, CS_T);
if (ls_t == null || cs_t == null) {
log.error("groupId {} registries {} failed to find LS_T/CS_T", groupId, value.stream()
.map(Registry::getId)
.map(Object::toString)
.collect(TextUtil.join));
return null;
}
return new Pair<>(ls_t, cs_t);
})
.collect(Collectors.toList()); .collect(Collectors.toList());
for (int i = 0; i < registries.size(); i++) { for (int i = 0; i < lstCstGroup.size(); i++) {
Registry ls_t = registries.get(i); var pair = lstCstGroup.get(i);
if (ls_t == null) { if (pair == null) {
continue; continue;
} }
Registry ls_t = pair.getFirst();
LinkedList<Registry> relatedLiabilities = new LinkedList<>(); LinkedList<Registry> relatedLiabilities = new LinkedList<>();
relatedLiabilities.add(ls_t); relatedLiabilities.add(ls_t);
for (int j = i + 1; j < registries.size(); j++) { for (int j = i + 1; j < lstCstGroup.size(); j++) {
Registry related = registries.get(j); var anotherGroup = lstCstGroup.get(j);
if (related == null) { if (anotherGroup == null) {
continue; continue;
} }
if (rgsOfTheSameAgents(ls_t, related)) { Registry related = anotherGroup.getFirst();
if (rgsOfTheSameAgents(pair.getFirst(), pair.getSecond(), anotherGroup.getFirst(), anotherGroup.getSecond())) {
relatedLiabilities.add(related); relatedLiabilities.add(related);
registries.set(j, null); lstCstGroup.set(j, null);
} }
} }
PaymentGroup paymentGroup = new PaymentGroup(); PaymentGroup paymentGroup = new PaymentGroup();
@ -57,10 +69,25 @@ public class RegistryLiabilitiesGroup {
return result; return result;
} }
private static boolean rgsOfTheSameAgents(Registry ls_t1, Registry ls_t2) { private static boolean rgsOfTheSameAgents(Registry ls_t1, Registry cs_t1, Registry ls_t2, Registry cs_t2) {
return Objects.equals(ls_t1.getSecurityId(), ls_t2.getSecurityId()) return Objects.equals(ls_t1.getSecurityId(), ls_t2.getSecurityId())
&& Objects.equals(ls_t1.getTradingClearingRegistryId(), ls_t2.getTradingClearingRegistryId()) && Objects.equals(ls_t1.getTradingClearingRegistryId(), ls_t2.getTradingClearingRegistryId())
&& Objects.equals(cs_t1.getTradingClearingRegistryId(), cs_t2.getTradingClearingRegistryId())
&& Objects.equals(ls_t1.getCompanyId(), ls_t2.getCompanyId()) && Objects.equals(ls_t1.getCompanyId(), ls_t2.getCompanyId())
&& Objects.equals(ls_t1.getCounterPartyId(), ls_t2.getCounterPartyId()); && Objects.equals(ls_t1.getCounterPartyId(), ls_t2.getCounterPartyId());
} }
private static Registry obtain(Collection<Registry> group, RegistryTradingParams cde) {
List<Registry> allRegistries = group
.stream()
.filter(rgs -> RegistryManager.equalsByCode(cde, rgs))
.toList();
if (allRegistries.size() > 1) {
throw new IllegalStateException("more than one " + cde + " entry in group " + group.iterator().next().getGroupId());
}
if (allRegistries.size() == 1) {
return allRegistries.iterator().next();
}
return null;
}
} }

View file

@ -3,7 +3,7 @@
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
<charset>UTF-8</charset> <charset>UTF-8</charset>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> <pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>
@ -11,7 +11,7 @@
<file>./logs/clearing-service.log</file> <file>./logs/clearing-service.log</file>
<encoder> <encoder>
<charset>UTF-8</charset> <charset>UTF-8</charset>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> <pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern> <fileNamePattern>
@ -40,7 +40,7 @@
<appender-ref ref="CONSOLE"/> <appender-ref ref="CONSOLE"/>
</logger> </logger>
<logger name="ru.spcex.clearing.service.execution" level="warn" additivity="false"> <logger name="ru.spcex.clearing.service.execution" level="info" additivity="false">
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
<appender-ref ref="CONSOLE"/> <appender-ref ref="CONSOLE"/>
</logger> </logger>

View file

@ -1,91 +0,0 @@
package ru.spcex.clearing.config;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.MockConsumer;
import org.apache.kafka.clients.consumer.OffsetResetStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.kafka.core.KafkaTemplate;
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.spcex.clearing.config.element.ClearingServiceSettings;
import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.clearing.service.builder.PaymentInstructionCreator;
import ru.spcex.clearing.test.config.KafkaTestConfig;
import ru.spcex.clearing.util.services.IMDGMessageResolver;
import ru.spcex.clearing.util.services.RequestHelper;
import ru.spcex.platform.enumeration.ClearingCategory;
import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
@Configuration
@ComponentScan(basePackages = {"ru.spcex.clearing.service", "ru.spcex.clearing.session.stage",
"ru.spcex.clearing.notification", "ru.spcex.clearing.statement"})
@Import(KafkaTestConfig.class)
public class ConfigTest {
@Bean
public RequestHelper reqHelper(IMessageResolver msgRslv) {
return new RequestHelper(msgRslv, ClearingError.GeneralError);
}
@Bean
public IMessageResolver messageResolver(ImdgProvider imdgProvider) {
return new IMDGMessageResolver(imdgProvider);
}
@Bean
public ClearingServiceSettings clearingServiceSettings() {
return new ClearingServiceSettings();
}
@Bean(name = "paymentInstructionCreatorTest")
public PaymentInstructionCreatorTest createPaymentInstructionCreator(@Qualifier("hazelcastServiceTest") ImdgProvider hazelcastServiceTest) {
return new PaymentInstructionCreatorTest(hazelcastServiceTest);
}
public static class PaymentInstructionCreatorTest extends PaymentInstructionCreator {
public PaymentInstructionCreatorTest(ImdgProvider imdgProvider) {
super(imdgProvider);
}
public PaymentInstruction createPaymentInstruction(ExecutionDeposit executionDeposit, LiabilitiesClaimsAssets liabilitiesClaimsAssets,
Collection<ClearingCategory> clearingCategory) {
List<PaymentInstruction> list = super.createPaymentInstructions(executionDeposit, liabilitiesClaimsAssets, clearingCategory);
return list.stream().findFirst().orElseGet(PaymentInstruction::new);
}
}
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean("kafkaConsumer")
public MockConsumer<String, Object> createMockConsumer() {
return new MockConsumer<>(OffsetResetStrategy.EARLIEST);
}
@Bean("kafkaConsumerGateway")
public Supplier<Consumer<String, Object>> getwaySessionConsumer() {
return () -> new MockConsumer<>(OffsetResetStrategy.EARLIEST);
}
@Autowired
@Bean("kafkaSenderWithoutRequestInfo")
public KafkaSender kafkaSenderWithoutRequestInfo(KafkaTemplate<String, Object> kafkaTemplate, ImdgProvider imdgProvider) {
ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator();
return KafkaSender
.setup()
.setKafkaTemplate(kafkaTemplate)
.idGenerator(imdgIdGenerator::nextId)
.saveRequestInfo(false)
.build();
}
}

View file

@ -0,0 +1,71 @@
package ru.spcex.clearing.config;
import com.hazelcast.config.*;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
@Configuration
public class HazelcastServiceTestConfiguration {
public static final AtomicLong currentID = new AtomicLong(0L);
private HazelcastInstance hazelcastInstance;
private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
if (maxPoolSz > 2) {
pool.setKeepAliveSeconds(60);
pool.setAllowCoreThreadTimeOut(true);
}
pool.setCorePoolSize(maxPoolSz);
pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion);
return pool;
}
@Bean(name = "hazelcastServiceTest")
public HazelcastService hazelcastService(@Qualifier("taskExecutorHazelcastClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer, @Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, HazelcastClientParams params) {
Config cfg = new Config();
cfg.setInstanceName("localhost");
NetworkConfig networkConfig = new NetworkConfig();
JoinConfig joinConfig = new JoinConfig();
joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false));
joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(true).setMembers(List.of("127.0.0.1")));
networkConfig.setJoin(joinConfig);
cfg.setNetworkConfig(networkConfig);
hazelcastInstance = Hazelcast.getOrCreateHazelcastInstance(cfg);
HazelcastHelper.imdgSystem_setStorageState(true, hazelcastInstance);
return new HazelcastService(taskExecutorHazelcastClientInitializer, taskExecutorIdGeneratorAwaiter, params);
}
@Bean(name = "taskExecutorHazelcastClientInitializer")
public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() {
return createThreadPoolTaskExecutor(1, true);
}
@Bean(name = "taskExecutorIdGeneratorAwaiter")
public ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter() {
return createThreadPoolTaskExecutor(1, false);
}
@Bean(name = "hazelcastClientParams")
public HazelcastClientParams getHazelcastClientParams() {
HazelcastClientParams params = new HazelcastClientParams();
params.setLogin("dev");
params.setPassword("dev-pass");
params.setClusterMembers("127.0.0.1");
params.setInstanceName("hzTestClient" + new Random().nextInt());
params.setNearCacheConfig(new NearCacheConfig());
return params;
}
}

View file

@ -0,0 +1,44 @@
package ru.spcex.clearing.config;
import org.apache.kafka.clients.consumer.MockConsumer;
import org.apache.kafka.clients.consumer.OffsetResetStrategy;
import org.apache.kafka.clients.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.service.RequestInfo;
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
import ru.spcex.platform.imdg.api.ImdgProvider;
@Configuration
public class KafkaConfigTest {
@Autowired
@Bean(name = "kafkaSenderTest")
public KafkaSender kafkaSender(Producer<String, Object> kafkaProducer, @Qualifier("hazelcastServiceTest") ImdgProvider imdgProvider) {
ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator();
return KafkaSender
.setup()
.producer(kafkaProducer)
.idGenerator(imdgIdGenerator::nextId)
.imdgProvider(s -> {
Imdg<RequestInfo> imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class);
return imdg::insert;
})
.build();
}
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(name = "mockConsumerTest")
public MockConsumer<String, Object> createConsumer() {
return new MockConsumer<>(OffsetResetStrategy.EARLIEST);
}
}

View file

@ -0,0 +1,15 @@
package ru.spcex.clearing.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import ru.spcex.clearing.utils.TestUtils;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
public class PaymentInstructionCreatorConfigTest {
@Bean(name = "paymentInstructionCreatorTest")
public TestUtils.PaymentInstructionCreatorTest createPaymentInstructionCreator(@Qualifier("hazelcastServiceTest") HazelcastService hazelcastServiceTest) {
return new TestUtils.PaymentInstructionCreatorTest(hazelcastServiceTest);
}
}

View file

@ -1,38 +1,54 @@
package ru.spcex.clearing.service; package ru.spcex.clearing.service;
import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
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.annotation.Qualifier;
import org.springframework.kafka.core.KafkaTemplate; import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import ru.spcex.clearing.config.*; import ru.spcex.clearing.config.*;
import ru.spcex.clearing.test.config.ImdgTestConfig; import ru.spcex.clearing.service.builder.LiabilitiesClaimsAssetsCreator;
import ru.spcex.clearing.test.config.KafkaTestConfig; import ru.spcex.clearing.service.builder.LiabilitiesClaimsMoneyCreator;
import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.clearing.service.execution.ExecutionDepositComponent;
import ru.spcex.clearing.service.order.ExecutionDepositSorter;
import ru.spcex.clearing.service.order.PaymentInstructionSorter;
import ru.spcex.clearing.utils.TestUtils;
import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = { @ContextConfiguration(classes = {
SdfCreatorBySTLDPayment.class,
PaymentUpdateBySdf04.class,
VerificationResultComponent.class,
ExecutionDepositComponent.class,
ExecutionDepositSorter.class,
LiabilitiesClaimsAssetsCreator.class,
LiabilitiesClaimsMoneyCreator.class,
EventsReceiver.class,
ClearingService.class,
Clearing.class,
SortingConfig.class, SortingConfig.class,
PaymentInstructionSorter.class,
MessageResolverConfig.class, MessageResolverConfig.class,
ConfigTest.class, PaymentInstructionCreatorConfigTest.class,
MarketCodesBySessionConfig.class,
ValidationConfig.class, ValidationConfig.class,
KafkaTestConfig.class, KafkaConfigTest.class,
ImdgTestConfig.class}) HazelcastServiceTestConfiguration.class})
public abstract class AbstractClearingTest { public abstract class AbstractClearingTest {
@Autowired @Autowired
@Qualifier("hazelcastServiceTest") @Qualifier("hazelcastServiceTest")
protected ImdgProvider hazelcastServiceTest; protected HazelcastService hazelcastServiceTest;
@Captor
@Autowired protected ArgumentCaptor<ProducerRecord> producerRecord;
@Qualifier("mockProducer") @SpyBean
protected Producer<String, Object> mockProducer; protected MockProducer<String, Object> mockProducer;
@Autowired
@Qualifier("kafkaTestTemplate")
protected KafkaTemplate<String, Object> kafkaTemplate;
@Autowired @Autowired
protected PaymentUpdateBySdf04 paymentUpdateBySdf04; protected PaymentUpdateBySdf04 paymentUpdateBySdf04;
@ -42,6 +58,8 @@ public abstract class AbstractClearingTest {
protected void init() { protected void init() {
hazelcastServiceTest.waitAvailable(); hazelcastServiceTest.waitAvailable();
TestUtils.FutureRecordMetadata future = spy(TestUtils.FutureRecordMetadata.class);
doReturn(future).when(mockProducer).send(producerRecord.capture());
} }
} }

View file

@ -1,390 +1,425 @@
package ru.spcex.clearing.service; package ru.spcex.clearing.service;
//todo ClearingService не используется тест пока не нужен.. import org.apache.kafka.clients.consumer.MockConsumer;
class ClearingServiceTest{ import org.junit.jupiter.api.Test;
// extends AbstractClearingTest { import org.springframework.beans.factory.annotation.Autowired;
// public static final MatcherFactory.Matcher<LiabilitiesClaimsAssets> LIABILITIES_CLAIMS_ASSETS_MATCHER = usingIgnoringFieldsComparator("created", "updated"); import org.springframework.beans.factory.annotation.Qualifier;
// public static final MatcherFactory.Matcher<LiabilitiesClaimsMoney> LIABILITIES_CLAIMS_MONEY_MATCHER = usingIgnoringFieldsComparator("created", "updated"); import ru.clearing.classes.statics.data.account.Account;
// public static final MatcherFactory.Matcher<PaymentInstruction> PAYMENT_INSTRUCTION_MATCHER = usingIgnoringFieldsComparator("created", "updated"); import ru.clearing.classes.statics.data.account.AccountBalance;
// public static final MatcherFactory.Matcher<ExecutionDeposit> EXECUTION_DEPOSIT_MATCHER = usingIgnoringFieldsComparator("created", "updated"); import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
// private static final int PARTITION = 0; import ru.clearing.classes.statics.data.company.Company;
// private static final String TOPIC_START_CLEARING = Task.startOfClearing.topic(); import ru.clearing.classes.statics.data.company.relation.Relation;
// private static final String TOPIC_CONTINUE_CLEARING = Consts.CONTINUE_CLEARING; import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
// private static final Long FIRST_ID = currentID.getAndIncrement(); import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets;
// private static final Long SECOND_ID = currentID.getAndIncrement(); import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney;
// private static final AtomicInteger currentInteger = new AtomicInteger(1); import ru.clearing.classes.statics.data.payment.PaymentInstruction;
// import ru.spcex.clearing.imdg.IMDGDistributedNames;
// @Autowired import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
// EventsReceiver eventsReceiver; import ru.spcex.clearing.platform.messaging.domain.Consts;
// import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest;
// @Autowired import ru.spcex.clearing.platform.messaging.domain.cud.registry.DealRegisterNewRequest;
// LiabilitiesClaimsAssetsCreator lbltsClmsAssetsCreator; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest;
// import ru.spcex.clearing.service.builder.LiabilitiesClaimsAssetsCreator;
// @Autowired import ru.spcex.clearing.service.builder.LiabilitiesClaimsMoneyCreator;
// @Qualifier("paymentInstructionCreatorTest") import ru.spcex.clearing.utils.MatcherFactory;
// ConfigTest.PaymentInstructionCreatorTest paymentInstructionCreator; import ru.spcex.clearing.utils.TestUtils;
// import ru.spcex.platform.enumeration.*;
// @Autowired import ru.spcex.platform.imdg.api.Imdg;
// LiabilitiesClaimsMoneyCreator lbltsClmsMoneyCreator; import ru.spcex.platform.utils.enumeration.IEnumKey;
// private Imdg<ExecutionDeposit> executionDepositImdg;
// private Imdg<LiabilitiesClaimsAssets> liabilitiesClaimsAssetsImdg; import javax.annotation.PostConstruct;
// private Imdg<LiabilitiesClaimsMoney> liabilitiesClaimsMoneyImdg; import java.math.BigDecimal;
// private Imdg<ClearingMemberCategory> clearingCategoryImdg; import java.time.Instant;
// private Imdg<Relation> relationImdg; import java.time.LocalDate;
// private Imdg<Company> companyImdg; import java.util.Collections;
// private Imdg<Account> accountImdg; import java.util.Map;
// private Imdg<AccountBalance> accountBalanceImdg; import java.util.concurrent.atomic.AtomicInteger;
// private ClearingCategory category;
// private ExecutionDeposit executionDeposit; import static org.junit.jupiter.api.Assertions.assertEquals;
// private Relation relation; import static org.mockito.Mockito.timeout;
// private Account account; import static org.mockito.Mockito.verify;
// private Company company; import static ru.spcex.clearing.config.HazelcastServiceTestConfiguration.currentID;
// private AccountBalance accountBalance; import static ru.spcex.clearing.utils.MatcherFactory.usingIgnoringFieldsComparator;
// import static ru.spcex.clearing.utils.TestUtils.addRecordToKafka;
// @PostConstruct import static ru.spcex.clearing.utils.TestUtils.getJsonStringForNew;
// protected void init() {
// super.init(); class ClearingServiceTest extends AbstractClearingTest {
// this.executionDepositImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); public static final MatcherFactory.Matcher<LiabilitiesClaimsAssets> LIABILITIES_CLAIMS_ASSETS_MATCHER = usingIgnoringFieldsComparator("created", "updated");
// this.clearingCategoryImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); public static final MatcherFactory.Matcher<LiabilitiesClaimsMoney> LIABILITIES_CLAIMS_MONEY_MATCHER = usingIgnoringFieldsComparator("created", "updated");
// this.liabilitiesClaimsAssetsImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class); public static final MatcherFactory.Matcher<PaymentInstruction> PAYMENT_INSTRUCTION_MATCHER = usingIgnoringFieldsComparator("created", "updated");
// this.liabilitiesClaimsMoneyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsMoney, LiabilitiesClaimsMoney.class); public static final MatcherFactory.Matcher<ExecutionDeposit> EXECUTION_DEPOSIT_MATCHER = usingIgnoringFieldsComparator("created", "updated");
// private static final int PARTITION = 0;
// this.relationImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); private static final String TOPIC_START_CLEARING = Task.startOfClearing.topic();
// this.companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class); private static final String TOPIC_CONTINUE_CLEARING = Consts.CONTINUE_CLEARING;
// this.accountImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Account, Account.class); private static final Long FIRST_ID = currentID.getAndIncrement();
// this.accountBalanceImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); private static final Long SECOND_ID = currentID.getAndIncrement();
// } private static final AtomicInteger currentInteger = new AtomicInteger(1);
//
// /** @Autowired
// * {@link ClearingService#executeClearing()} <br> EventsReceiver eventsReceiver;
// * Тест проверяет создание сущностей
// * {@link LauncherCommandRequest} @Autowired
// * {@link LiabilitiesClaimsMoney} LiabilitiesClaimsAssetsCreator lbltsClmsAssetsCreator;
// * {@link PaymentInstruction}
// * {@link ExecutionDeposit} @Autowired
// * в Hazelcast при передаче из Apache Kafka.<br> @Qualifier("paymentInstructionCreatorTest")
// */ TestUtils.PaymentInstructionCreatorTest paymentInstructionCreator;
//// @Test
// void startClearingNew() { @Autowired
// //ARRANGE LiabilitiesClaimsMoneyCreator lbltsClmsMoneyCreator;
// int times = currentInteger.getAndIncrement(); private Imdg<ExecutionDeposit> executionDepositImdg;
// Long companyIdI1 = 11L; private Imdg<LiabilitiesClaimsAssets> liabilitiesClaimsAssetsImdg;
// Long relationIdI1 = 111L; private Imdg<LiabilitiesClaimsMoney> liabilitiesClaimsMoneyImdg;
// Long accountIdI1 = 1111L; private Imdg<ClearingMemberCategory> clearingCategoryImdg;
// Long securityIdI1 = 11111L; private Imdg<Relation> relationImdg;
// LocalDate firstSettlementDateI1 = LocalDate.now(); private Imdg<Company> companyImdg;
// LocalDate secondSettlementDateI2 = LocalDate.ofYearDay(2022, 31); private Imdg<Account> accountImdg;
// private Imdg<AccountBalance> accountBalanceImdg;
// preparOptimisticCase(companyIdI1, relationIdI1, accountIdI1, private ClearingCategory category;
// securityIdI1, firstSettlementDateI1, secondSettlementDateI2, "I"); private ExecutionDeposit executionDeposit;
// private Relation relation;
// //ACT private Account account;
// LauncherCommandRequest accountRequest = new LauncherCommandRequest(); private Company company;
// accountRequest.setSessionType(TRDT.getKey()); private AccountBalance accountBalance;
// accountRequest.setSection(MKR.getKey());
// String jsonString = getJsonStringForNew(accountRequest, FIRST_ID); @PostConstruct
// addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_START_CLEARING, PARTITION, times, jsonString); protected void init() {
// super.init();
// //waiting for kafka producer send message this.executionDepositImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
// ArgumentCaptor<ProducerRecord> producerRecord = getCaptor(kafkaTemplate); this.clearingCategoryImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
// verify(kafkaTemplate, timeout(30_000L).times(1)) this.liabilitiesClaimsAssetsImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class);
// .send(producerRecord.capture()); this.liabilitiesClaimsMoneyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsMoney, LiabilitiesClaimsMoney.class);
// assertEquals(Consts.BALANCE_ACCOUNT_UPDATE, producerRecord.getValue().topic());
// BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value(); this.relationImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
// this.companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class);
// //stage continueClearing this.accountImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Account, Account.class);
// CommonIdRequest requestPayload = new CommonIdRequest(); this.accountBalanceImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
// requestPayload.setId(baseRequestResult.getId()); }
// addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_CONTINUE_CLEARING, PARTITION, times, getJsonStringForNew(requestPayload, FIRST_ID));
// /**
// //waiting for kafka producer send message (finale event) * {@link ClearingService#executeClearing()} <br>
// verify(kafkaTemplate, timeout(30_000L).times(2)) * Тест проверяет создание сущностей
// .send(producerRecord.capture()); * {@link LauncherCommandRequest}
// * {@link LiabilitiesClaimsMoney}
// //ASSERT * {@link PaymentInstruction}
// assertEquals(Task.createOrder.topic(), producerRecord.getValue().topic()); * {@link ExecutionDeposit}
// * в Hazelcast при передаче из Apache Kafka.<br>
// //First LiabilitiesClaimsAssets && LiabilitiesClaimsMoney */
// LiabilitiesClaimsAssets resultFirstClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues( @Test
// Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1)); void startClearingNew() {
// LiabilitiesClaimsMoney resultFirstClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues( //ARRANGE
// Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1)); int times = currentInteger.getAndIncrement();
// LiabilitiesClaimsAssets predictableFirstClaimsAssets = lbltsClmsAssetsCreator.createFirstLegLCA(category, executionDeposit); Long companyIdI1 = 11L;
// predictableFirstClaimsAssets.setId(resultFirstClaimsAssets.getId()); Long relationIdI1 = 111L;
// predictableFirstClaimsAssets.setPaymentId(resultFirstClaimsAssets.getPaymentId()); Long accountIdI1 = 1111L;
// predictableFirstClaimsAssets.setLiabilitiesClaimsMoneyId(resultFirstClaimsMoney.getId()); Long securityIdI1 = 11111L;
// LiabilitiesClaimsMoney predictableFirstClaimsMoney = lbltsClmsMoneyCreator.createFirstLegLcm(predictableFirstClaimsAssets, category); LocalDate firstSettlementDateI1 = LocalDate.now();
// predictableFirstClaimsMoney.setId(resultFirstClaimsMoney.getId()); LocalDate secondSettlementDateI2 = LocalDate.ofYearDay(2022, 31);
// LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultFirstClaimsAssets, predictableFirstClaimsAssets);
// LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultFirstClaimsMoney, predictableFirstClaimsMoney); preparOptimisticCase(companyIdI1, relationIdI1, accountIdI1,
// //Second LiabilitiesClaimsAssets && LiabilitiesClaimsMoney securityIdI1, firstSettlementDateI1, secondSettlementDateI2, "I");
// LiabilitiesClaimsAssets resultSecondClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues(
// Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2)); //ACT
// LiabilitiesClaimsMoney resultSecondClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues( //stage executeClearing(startClearing)
// Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2)); addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_START_CLEARING, PARTITION, times, getJsonStringForNew(new DealRegisterNewRequest(), FIRST_ID));
// LiabilitiesClaimsAssets predictableSecondClaimsAssets = lbltsClmsAssetsCreator.createSecondLegLCA(category, executionDeposit);
// predictableSecondClaimsAssets.setId(resultSecondClaimsAssets.getId()); //waiting for kafka producer send message
// predictableSecondClaimsAssets.setLiabilitiesClaimsMoneyId(resultSecondClaimsMoney.getId()); verify(mockProducer, timeout(30_000L).times(1))
// LiabilitiesClaimsMoney predictableSecondClaimsMoney = lbltsClmsMoneyCreator.createSecondLegLcm(predictableSecondClaimsAssets, category); .send(producerRecord.capture());
// predictableSecondClaimsMoney.setId(resultSecondClaimsMoney.getId()); assertEquals(Consts.BALANCE_ACCOUNT_UPDATE, producerRecord.getValue().topic());
// LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultSecondClaimsAssets, predictableSecondClaimsAssets); BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value();
// LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultSecondClaimsMoney, predictableSecondClaimsMoney);
// //PaymentInstruction //stage continueClearing
// PaymentInstruction resultPaymentInstruction = paymentInstructionCreator.searchExistPaymentInstructionsFirstI(predictableFirstClaimsAssets); CommonIdRequest requestPayload = new CommonIdRequest();
// PaymentInstruction predictablePaymentInstruction = paymentInstructionCreator.createPaymentInstruction(executionDeposit, predictableFirstClaimsAssets, Collections.singleton(category)); requestPayload.setId(baseRequestResult.getId());
// predictablePaymentInstruction.setId(resultPaymentInstruction.getId()); addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_CONTINUE_CLEARING, PARTITION, times, getJsonStringForNew(requestPayload, FIRST_ID));
// predictablePaymentInstruction.setDocumentNumber(resultPaymentInstruction.getDocumentNumber());
// PAYMENT_INSTRUCTION_MATCHER.assertMatch(resultPaymentInstruction, predictablePaymentInstruction); //waiting for kafka producer send message (finale event)
// //ExecutionDeposit verify(mockProducer, timeout(30_000L).times(2))
// ExecutionDeposit resultExecutionDeposit = executionDepositImdg.getFirstObjectByFieldValues( .send(producerRecord.capture());
// Map.of("accountId", accountIdI1, "securityId", securityIdI1));
// executionDeposit.setSessionId(resultExecutionDeposit.getSessionId()); //ASSERT
// EXECUTION_DEPOSIT_MATCHER.assertMatch(resultExecutionDeposit, executionDeposit); assertEquals(Task.createOrder.topic(), producerRecord.getValue().topic());
// }
// //First LiabilitiesClaimsAssets && LiabilitiesClaimsMoney
// /** LiabilitiesClaimsAssets resultFirstClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues(
// * {@link ClearingService#executeClearing()} <br> Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1));
// * Тест проверяет обновление сущностей LiabilitiesClaimsMoney resultFirstClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues(
// * {@link LauncherCommandRequest} Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1));
// * {@link LiabilitiesClaimsMoney} LiabilitiesClaimsAssets predictableFirstClaimsAssets = lbltsClmsAssetsCreator.createFirstLegLCA(category, executionDeposit);
// * {@link PaymentInstruction} predictableFirstClaimsAssets.setId(resultFirstClaimsAssets.getId());
// * {@link ExecutionDeposit} predictableFirstClaimsAssets.setPaymentId(resultFirstClaimsAssets.getPaymentId());
// * в Hazelcast при передаче из Apache Kafka.<br> predictableFirstClaimsAssets.setLiabilitiesClaimsMoneyId(resultFirstClaimsMoney.getId());
// */ LiabilitiesClaimsMoney predictableFirstClaimsMoney = lbltsClmsMoneyCreator.createFirstLegLcm(predictableFirstClaimsAssets, category);
//// @Test predictableFirstClaimsMoney.setId(resultFirstClaimsMoney.getId());
// void startClearingUpdate() { LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultFirstClaimsAssets, predictableFirstClaimsAssets);
// //ARRANGE LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultFirstClaimsMoney, predictableFirstClaimsMoney);
// int times = currentInteger.getAndIncrement(); //Second LiabilitiesClaimsAssets && LiabilitiesClaimsMoney
// Long companyIdI1 = 21L; LiabilitiesClaimsAssets resultSecondClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues(
// Long relationIdI1 = 211L; Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2));
// Long accountIdI1 = 2111L; LiabilitiesClaimsMoney resultSecondClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues(
// Long securityIdI1 = 21111L; Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2));
// LocalDate firstSettlementDateI1 = LocalDate.now(); LiabilitiesClaimsAssets predictableSecondClaimsAssets = lbltsClmsAssetsCreator.createSecondLegLCA(category, executionDeposit);
// LocalDate secondSettlementDateI2 = LocalDate.ofYearDay(2022, 31); predictableSecondClaimsAssets.setId(resultSecondClaimsAssets.getId());
// predictableSecondClaimsAssets.setLiabilitiesClaimsMoneyId(resultSecondClaimsMoney.getId());
// preparOptimisticCase(companyIdI1, relationIdI1, accountIdI1, LiabilitiesClaimsMoney predictableSecondClaimsMoney = lbltsClmsMoneyCreator.createSecondLegLcm(predictableSecondClaimsAssets, category);
// securityIdI1, firstSettlementDateI1, secondSettlementDateI2, "I"); predictableSecondClaimsMoney.setId(resultSecondClaimsMoney.getId());
// LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultSecondClaimsAssets, predictableSecondClaimsAssets);
// LiabilitiesClaimsAssets predictableFirstClaimsAssets = lbltsClmsAssetsCreator.createFirstLegLCA(category, executionDeposit); LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultSecondClaimsMoney, predictableSecondClaimsMoney);
// predictableFirstClaimsAssets.setId(FIRST_ID); //PaymentInstruction
// liabilitiesClaimsAssetsImdg.insert(predictableFirstClaimsAssets); PaymentInstruction resultPaymentInstruction = paymentInstructionCreator.searchExistPaymentInstructionsFirstI(predictableFirstClaimsAssets);
// LiabilitiesClaimsMoney predictableFirstClaimsMoney = lbltsClmsMoneyCreator.createFirstLegLcm(predictableFirstClaimsAssets, category); PaymentInstruction predictablePaymentInstruction = paymentInstructionCreator.createPaymentInstruction(executionDeposit, predictableFirstClaimsAssets, Collections.singleton(category));
// predictableFirstClaimsMoney.setId(FIRST_ID); predictablePaymentInstruction.setId(resultPaymentInstruction.getId());
// liabilitiesClaimsMoneyImdg.insert(predictableFirstClaimsMoney); predictablePaymentInstruction.setDocumentNumber(resultPaymentInstruction.getDocumentNumber());
// LiabilitiesClaimsAssets predictableSecondClaimsAssets = lbltsClmsAssetsCreator.createSecondLegLCA(category, executionDeposit); PAYMENT_INSTRUCTION_MATCHER.assertMatch(resultPaymentInstruction, predictablePaymentInstruction);
// predictableSecondClaimsAssets.setId(SECOND_ID); //ExecutionDeposit
// liabilitiesClaimsAssetsImdg.insert(predictableSecondClaimsAssets); ExecutionDeposit resultExecutionDeposit = executionDepositImdg.getFirstObjectByFieldValues(
// LiabilitiesClaimsMoney predictableSecondClaimsMoney = lbltsClmsMoneyCreator.createSecondLegLcm(predictableSecondClaimsAssets, category); Map.of("accountId", accountIdI1, "securityId", securityIdI1));
// predictableSecondClaimsMoney.setId(SECOND_ID); executionDeposit.setSessionId(resultExecutionDeposit.getSessionId());
// liabilitiesClaimsMoneyImdg.insert(predictableSecondClaimsMoney); EXECUTION_DEPOSIT_MATCHER.assertMatch(resultExecutionDeposit, executionDeposit);
// //ACT }
// //stage executeClearing(startClearing)
// addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_START_CLEARING, PARTITION, times, getJsonStringForNew(new DealRegisterNewRequest(), FIRST_ID)); /**
// * {@link ClearingService#executeClearing()} <br>
// //waiting for kafka producer send message * Тест проверяет обновление сущностей
// ArgumentCaptor<ProducerRecord> producerRecord = getCaptor(kafkaTemplate); * {@link LauncherCommandRequest}
// verify(kafkaTemplate, timeout(30_000L).times(1)) * {@link LiabilitiesClaimsMoney}
// .send(producerRecord.capture()); * {@link PaymentInstruction}
// assertEquals(Consts.BALANCE_ACCOUNT_UPDATE, producerRecord.getValue().topic()); * {@link ExecutionDeposit}
// BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value(); * в Hazelcast при передаче из Apache Kafka.<br>
// */
// //stage continueClearing @Test
// CommonIdRequest requestPayload = new CommonIdRequest(); void startClearingUpdate() {
// requestPayload.setId(baseRequestResult.getId()); //ARRANGE
// addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_CONTINUE_CLEARING, PARTITION, times, getJsonStringForNew(requestPayload, FIRST_ID)); int times = currentInteger.getAndIncrement();
// Long companyIdI1 = 21L;
// //waiting for kafka producer send message (finale event) Long relationIdI1 = 211L;
// verify(kafkaTemplate, timeout(30_000L).times(2)) Long accountIdI1 = 2111L;
// .send(producerRecord.capture()); Long securityIdI1 = 21111L;
// LocalDate firstSettlementDateI1 = LocalDate.now();
// //ASSERT LocalDate secondSettlementDateI2 = LocalDate.ofYearDay(2022, 31);
// assertEquals(Task.createOrder.topic(), producerRecord.getValue().topic());
// preparOptimisticCase(companyIdI1, relationIdI1, accountIdI1,
// //First LiabilitiesClaimsAssets && LiabilitiesClaimsMoney securityIdI1, firstSettlementDateI1, secondSettlementDateI2, "I");
// LiabilitiesClaimsAssets resultFirstClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues(
// Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1)); LiabilitiesClaimsAssets predictableFirstClaimsAssets = lbltsClmsAssetsCreator.createFirstLegLCA(category, executionDeposit);
// LiabilitiesClaimsMoney resultFirstClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues( predictableFirstClaimsAssets.setId(FIRST_ID);
// Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1)); liabilitiesClaimsAssetsImdg.insert(predictableFirstClaimsAssets);
// predictableFirstClaimsAssets.setPaymentId(resultFirstClaimsAssets.getPaymentId()); LiabilitiesClaimsMoney predictableFirstClaimsMoney = lbltsClmsMoneyCreator.createFirstLegLcm(predictableFirstClaimsAssets, category);
// predictableFirstClaimsAssets.setLiabilitiesClaimsMoneyId(resultFirstClaimsMoney.getId()); predictableFirstClaimsMoney.setId(FIRST_ID);
// lbltsClmsAssetsCreator.updateFirstLegLca(predictableFirstClaimsAssets, executionDeposit, category); liabilitiesClaimsMoneyImdg.insert(predictableFirstClaimsMoney);
// lbltsClmsMoneyCreator.updateFirstLegLcm(predictableFirstClaimsMoney, predictableFirstClaimsAssets, executionDeposit, category); LiabilitiesClaimsAssets predictableSecondClaimsAssets = lbltsClmsAssetsCreator.createSecondLegLCA(category, executionDeposit);
// LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultFirstClaimsAssets, predictableFirstClaimsAssets); predictableSecondClaimsAssets.setId(SECOND_ID);
// LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultFirstClaimsMoney, predictableFirstClaimsMoney); liabilitiesClaimsAssetsImdg.insert(predictableSecondClaimsAssets);
// //Second LiabilitiesClaimsAssets && LiabilitiesClaimsMoney LiabilitiesClaimsMoney predictableSecondClaimsMoney = lbltsClmsMoneyCreator.createSecondLegLcm(predictableSecondClaimsAssets, category);
// LiabilitiesClaimsAssets resultSecondClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues( predictableSecondClaimsMoney.setId(SECOND_ID);
// Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2)); liabilitiesClaimsMoneyImdg.insert(predictableSecondClaimsMoney);
// LiabilitiesClaimsMoney resultSecondClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues( //ACT
// Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2)); //stage executeClearing(startClearing)
// addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_START_CLEARING, PARTITION, times, getJsonStringForNew(new DealRegisterNewRequest(), FIRST_ID));
// predictableSecondClaimsAssets.setLiabilitiesClaimsMoneyId(resultSecondClaimsMoney.getId());
// lbltsClmsAssetsCreator.updateSecondLegLca(predictableSecondClaimsAssets, executionDeposit, category); //waiting for kafka producer send message
// lbltsClmsMoneyCreator.updateSecondLegLcm(predictableSecondClaimsMoney, predictableSecondClaimsAssets, executionDeposit, category); verify(mockProducer, timeout(30_000L).times(1))
// LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultSecondClaimsAssets, predictableSecondClaimsAssets); .send(producerRecord.capture());
// LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultSecondClaimsMoney, predictableSecondClaimsMoney); assertEquals(Consts.BALANCE_ACCOUNT_UPDATE, producerRecord.getValue().topic());
// //PaymentInstruction BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value();
// PaymentInstruction resultPaymentInstruction = paymentInstructionCreator.searchExistPaymentInstructionsFirstI(predictableFirstClaimsAssets);
// PaymentInstruction predictablePaymentInstruction = paymentInstructionCreator.createPaymentInstruction(executionDeposit, predictableFirstClaimsAssets, Collections.singleton(category)); //stage continueClearing
// predictablePaymentInstruction.setId(resultPaymentInstruction.getId()); CommonIdRequest requestPayload = new CommonIdRequest();
// predictablePaymentInstruction.setDocumentNumber(resultPaymentInstruction.getDocumentNumber()); requestPayload.setId(baseRequestResult.getId());
// PAYMENT_INSTRUCTION_MATCHER.assertMatch(resultPaymentInstruction, predictablePaymentInstruction); addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_CONTINUE_CLEARING, PARTITION, times, getJsonStringForNew(requestPayload, FIRST_ID));
// //ExecutionDeposit
// ExecutionDeposit resultExecutionDeposit = executionDepositImdg.getFirstObjectByFieldValues( //waiting for kafka producer send message (finale event)
// Map.of("accountId", accountIdI1, "securityId", securityIdI1)); verify(mockProducer, timeout(30_000L).times(2))
// executionDeposit.setSessionId(resultExecutionDeposit.getSessionId()); .send(producerRecord.capture());
// EXECUTION_DEPOSIT_MATCHER.assertMatch(resultExecutionDeposit, executionDeposit);
// } //ASSERT
// assertEquals(Task.createOrder.topic(), producerRecord.getValue().topic());
// /**
// * {@link ClearingService#executeClearing()} <br> //First LiabilitiesClaimsAssets && LiabilitiesClaimsMoney
// * Тест проверяет обновление сущностей LiabilitiesClaimsAssets resultFirstClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues(
// * {@link LauncherCommandRequest} Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1));
// * {@link LiabilitiesClaimsMoney} LiabilitiesClaimsMoney resultFirstClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues(
// * {@link PaymentInstruction} Map.of("accountId", accountIdI1, "settlementDate", firstSettlementDateI1));
// * {@link ExecutionDeposit} predictableFirstClaimsAssets.setPaymentId(resultFirstClaimsAssets.getPaymentId());
// * в Hazelcast при передаче из Apache Kafka.<br> predictableFirstClaimsAssets.setLiabilitiesClaimsMoneyId(resultFirstClaimsMoney.getId());
// */ lbltsClmsAssetsCreator.updateFirstLegLca(predictableFirstClaimsAssets, executionDeposit, category);
//// @Test lbltsClmsMoneyCreator.updateFirstLegLcm(predictableFirstClaimsMoney, predictableFirstClaimsAssets, executionDeposit, category);
// void startClearingValidatError() { LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultFirstClaimsAssets, predictableFirstClaimsAssets);
// //ARRANGE LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultFirstClaimsMoney, predictableFirstClaimsMoney);
// Long companyId = 31L; //Second LiabilitiesClaimsAssets && LiabilitiesClaimsMoney
// Long relationId = 311L; LiabilitiesClaimsAssets resultSecondClaimsAssets = liabilitiesClaimsAssetsImdg.getFirstObjectByFieldValues(
// Long accountId = 3111L; Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2));
// Long securityId = 31111L; LiabilitiesClaimsMoney resultSecondClaimsMoney = liabilitiesClaimsMoneyImdg.getFirstObjectByFieldValues(
// LocalDate firstSettlementDate = LocalDate.now(); Map.of("accountId", accountIdI1, "settlementDate", secondSettlementDateI2));
// LocalDate secondSettlementDate = LocalDate.ofYearDay(2022, 31);
// predictableSecondClaimsAssets.setLiabilitiesClaimsMoneyId(resultSecondClaimsMoney.getId());
// preparOptimisticCase(companyId, relationId, accountId, lbltsClmsAssetsCreator.updateSecondLegLca(predictableSecondClaimsAssets, executionDeposit, category);
// securityId, firstSettlementDate, secondSettlementDate, "V"); lbltsClmsMoneyCreator.updateSecondLegLcm(predictableSecondClaimsMoney, predictableSecondClaimsAssets, executionDeposit, category);
// LIABILITIES_CLAIMS_ASSETS_MATCHER.assertMatch(resultSecondClaimsAssets, predictableSecondClaimsAssets);
// LIABILITIES_CLAIMS_MONEY_MATCHER.assertMatch(resultSecondClaimsMoney, predictableSecondClaimsMoney);
// //ClearingIsAllowed //PaymentInstruction
// relation.setServiceStatus(ServiceStatus.Blocked.getKey()); PaymentInstruction resultPaymentInstruction = paymentInstructionCreator.searchExistPaymentInstructionsFirstI(predictableFirstClaimsAssets);
// relationImdg.insert(relation); PaymentInstruction predictablePaymentInstruction = paymentInstructionCreator.createPaymentInstruction(executionDeposit, predictableFirstClaimsAssets, Collections.singleton(category));
// checkHaveSomeError(currentInteger.getAndIncrement()); predictablePaymentInstruction.setId(resultPaymentInstruction.getId());
// predictablePaymentInstruction.setDocumentNumber(resultPaymentInstruction.getDocumentNumber());
// //AccountIsNotBlocked PAYMENT_INSTRUCTION_MATCHER.assertMatch(resultPaymentInstruction, predictablePaymentInstruction);
// relation.setServiceStatus(ServiceStatus.Active.getKey()); //ExecutionDeposit
// relationImdg.insert(relation); ExecutionDeposit resultExecutionDeposit = executionDepositImdg.getFirstObjectByFieldValues(
// executionDeposit = getExecutionDeposit(companyId, null, securityId, firstSettlementDate, secondSettlementDate); Map.of("accountId", accountIdI1, "securityId", securityIdI1));
// executionDepositImdg.insert(executionDeposit); executionDeposit.setSessionId(resultExecutionDeposit.getSessionId());
// checkHaveSomeError(currentInteger.getAndIncrement()); EXECUTION_DEPOSIT_MATCHER.assertMatch(resultExecutionDeposit, executionDeposit);
// }
// executionDeposit = getExecutionDeposit(companyId, accountId, securityId, firstSettlementDate, secondSettlementDate);
// executionDepositImdg.insert(executionDeposit); /**
// account.setStatus(AccountStatus.BLOCKED.getKey()); * {@link ClearingService#executeClearing()} <br>
// accountImdg.insert(account); * Тест проверяет обновление сущностей
// checkHaveSomeError(currentInteger.getAndIncrement()); * {@link LauncherCommandRequest}
// * {@link LiabilitiesClaimsMoney}
// //CompanyIsNotBlocked * {@link PaymentInstruction}
// account.setStatus(AccountStatus.ACTIVE.getKey()); * {@link ExecutionDeposit}
// accountImdg.insert(account); * в Hazelcast при передаче из Apache Kafka.<br>
// company.setWorkflowStatus(WorkflowStatus.Blocked.getKey()); */
// companyImdg.insert(company); @Test
// checkHaveSomeError(currentInteger.getAndIncrement()); void startClearingValidatError() {
// //ARRANGE
// company.setWorkflowStatus(null); Long companyId = 31L;
// companyImdg.insert(company); Long relationId = 311L;
// checkHaveSomeError(currentInteger.getAndIncrement()); Long accountId = 3111L;
// Long securityId = 31111L;
// //FinancialObligationSecurity LocalDate firstSettlementDate = LocalDate.now();
// company.setWorkflowStatus(WorkflowStatus.Active.getKey()); LocalDate secondSettlementDate = LocalDate.ofYearDay(2022, 31);
// companyImdg.insert(company);
// accountBalance.setAccountId(0L); preparOptimisticCase(companyId, relationId, accountId,
// accountBalanceImdg.insert(accountBalance); securityId, firstSettlementDate, secondSettlementDate, "V");
// checkHaveSomeError(currentInteger.getAndIncrement());
//
// accountBalance.setAccountId(accountId); //ClearingIsAllowed
// accountBalance.setFreeBalanceAmount(new BigDecimal(19)); relation.setServiceStatus(ServiceStatus.Blocked.getKey());
// accountBalanceImdg.insert(accountBalance); relationImdg.insert(relation);
// executionDeposit.setFirstLegAmount(new BigDecimal(200)); checkHaveSomeError(currentInteger.getAndIncrement());
// executionDepositImdg.insert(executionDeposit);
// checkHaveSomeError(currentInteger.getAndIncrement()); //AccountIsNotBlocked
// } relation.setServiceStatus(ServiceStatus.Active.getKey());
// relationImdg.insert(relation);
// void preparOptimisticCase(Long companyId, Long relationId, Long accountId, executionDeposit = getExecutionDeposit(companyId, null, securityId, firstSettlementDate, secondSettlementDate);
// Long securityId, LocalDate dtF, LocalDate dtS, String memberCategory) { executionDepositImdg.insert(executionDeposit);
// category = IEnumKey.getEnumByKey(ClearingCategory.class, memberCategory); checkHaveSomeError(currentInteger.getAndIncrement());
//
// executionDeposit = getExecutionDeposit(companyId, accountId, securityId, dtF, dtS); executionDeposit = getExecutionDeposit(companyId, accountId, securityId, firstSettlementDate, secondSettlementDate);
// executionDepositImdg.insert(executionDeposit); executionDepositImdg.insert(executionDeposit);
// account.setStatus(AccountStatus.BLOCKED.getKey());
// ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory(); accountImdg.insert(account);
// clearingMemberCategory.setCompanyId(companyId); checkHaveSomeError(currentInteger.getAndIncrement());
// clearingMemberCategory.setClearingMemberCategory(memberCategory);
// clearingCategoryImdg.insert(clearingMemberCategory); //CompanyIsNotBlocked
// account.setStatus(AccountStatus.ACTIVE.getKey());
// relation = new Relation(); accountImdg.insert(account);
// relation.setId(relationId); company.setWorkflowStatus(WorkflowStatus.Blocked.getKey());
// relation.setConsumerId(companyId); companyImdg.insert(company);
// relation.setServiceStatus(ServiceStatus.Active.getKey()); checkHaveSomeError(currentInteger.getAndIncrement());
// relationImdg.insert(relation);
// company.setWorkflowStatus(null);
// account = new Account(); companyImdg.insert(company);
// account.setId(accountId); checkHaveSomeError(currentInteger.getAndIncrement());
// account.setRelationId(relationId);
// account.setStatus(AccountStatus.ACTIVE.getKey()); //FinancialObligationSecurity
// accountImdg.insert(account); company.setWorkflowStatus(WorkflowStatus.Active.getKey());
// companyImdg.insert(company);
// company = new Company(); accountBalance.setAccountId(0L);
// company.setId(companyId); accountBalanceImdg.insert(accountBalance);
// company.setWorkflowStatus(WorkflowStatus.Active.getKey()); checkHaveSomeError(currentInteger.getAndIncrement());
// companyImdg.insert(company);
// accountBalance.setAccountId(accountId);
// accountBalance = new AccountBalance(); accountBalance.setFreeBalanceAmount(new BigDecimal(19));
// accountBalance.setAccountId(accountId); accountBalanceImdg.insert(accountBalance);
// accountBalance.setCompanyId(companyId); executionDeposit.setFirstLegAmount(new BigDecimal(200));
// accountBalanceImdg.insert(accountBalance); executionDepositImdg.insert(executionDeposit);
// } checkHaveSomeError(currentInteger.getAndIncrement());
// }
// ExecutionDeposit getExecutionDeposit(Long companyId, Long accountId, Long securityId, LocalDate dtF, LocalDate dtS) {
// ExecutionDeposit executionDeposit = new ExecutionDeposit(); void preparOptimisticCase(Long companyId, Long relationId, Long accountId,
// executionDeposit.setExchangeExecutionId(5L); Long securityId, LocalDate dtF, LocalDate dtS, String memberCategory) {
// executionDeposit.setExchangeExecutionTime(Instant.now()); category = IEnumKey.getEnumByKey(ClearingCategory.class, memberCategory);
// executionDeposit.setTradingDate(LocalDate.now());
// executionDeposit.setTradingClearingRegistryId(accountId); //todo CLS-275 executionDeposit.setAccountId(accountId); executionDeposit = getExecutionDeposit(companyId, accountId, securityId, dtF, dtS);
// executionDeposit.setMarket("market"); executionDepositImdg.insert(executionDeposit);
// executionDeposit.setPrice(new BigDecimal(9));
// executionDeposit.setLots(new BigDecimal(0)); ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory();
// executionDeposit.setQuantity(new BigDecimal(8)); clearingMemberCategory.setCompanyId(companyId);
// executionDeposit.setFirstLegAmount(new BigDecimal(7)); clearingMemberCategory.setClearingMemberCategory(memberCategory);
// executionDeposit.setSecondLegAmount(new BigDecimal(6)); clearingCategoryImdg.insert(clearingMemberCategory);
// executionDeposit.setInterestAmount(new BigDecimal(5));
// executionDeposit.setSide("side"); relation = new Relation();
// executionDeposit.setSettlementCurrency("settlementCurrency"); relation.setId(relationId);
// executionDeposit.setCompanyId(companyId); relation.setConsumerId(companyId);
// executionDeposit.setDuration(1L); relation.setServiceStatus(ServiceStatus.Active.getKey());
// executionDeposit.setFirstLegSettlementDate(dtF); relationImdg.insert(relation);
// executionDeposit.setSecondLegSettlementDate(dtS);
// executionDeposit.setFirstLegSettlementCode("leg1c"); account = new Account();
// executionDeposit.setSecondLegSettlementCode("legcc"); account.setId(accountId);
// executionDeposit.setContract("contract"); account.setRelationId(relationId);
// executionDeposit.setSecurityFullName("full"); account.setStatus(AccountStatus.ACTIVE.getKey());
// executionDeposit.setSecuritySymbol("symbol"); accountImdg.insert(account);
// executionDeposit.setSecurityId(securityId);
// executionDeposit.setCounterPartyId(0L); company = new Company();
// executionDeposit.setCoverageStatus(Allowed.ALLOWED.getKey()); company.setId(companyId);
// executionDeposit.setSessionId(null); company.setWorkflowStatus(WorkflowStatus.Active.getKey());
// executionDeposit.setClearingDate(LocalDate.now()); companyImdg.insert(company);
// executionDeposit.setId(FIRST_ID);
// return executionDeposit; accountBalance = new AccountBalance();
// } accountBalance.setAccountId(accountId);
// accountBalance.setCompanyId(companyId);
// void checkHaveSomeError(long times) { accountBalanceImdg.insert(accountBalance);
// //ACT }
// //stage executeClearing(startClearing)
// addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_START_CLEARING, PARTITION, times, getJsonStringForNew(new DealRegisterNewRequest(), FIRST_ID)); ExecutionDeposit getExecutionDeposit(Long companyId, Long accountId, Long securityId, LocalDate dtF, LocalDate dtS) {
// ExecutionDeposit executionDeposit = new ExecutionDeposit();
// //waiting for kafka producer send message executionDeposit.setExchangeExecutionId(5L);
// ArgumentCaptor<ProducerRecord> producerRecord = getCaptor(kafkaTemplate); executionDeposit.setExchangeExecutionTime(Instant.now());
// verify(kafkaTemplate, timeout(30_000L).times(1)) executionDeposit.setTradingDate(LocalDate.now());
// .send(producerRecord.capture()); executionDeposit.setTradingClearingRegistryId(accountId); //todo CLS-275 executionDeposit.setAccountId(accountId);
// executionDeposit.setMarket("market");
// //ASSERT executionDeposit.setPrice(new BigDecimal(9));
// assertEquals(Task.createOrder.topic(), producerRecord.getValue().topic()); executionDeposit.setLots(new BigDecimal(0));
// ExecutionDeposit resultExecutionDeposit = executionDepositImdg.getFirstObjectBySQL("settlementCurrency = 'settlementCurrency'"); executionDeposit.setQuantity(new BigDecimal(8));
// executionDeposit.setUpdated(resultExecutionDeposit.getUpdated()); executionDeposit.setFirstLegAmount(new BigDecimal(7));
// executionDeposit.setCoverageStatus(Allowed.DENIED.getKey()); executionDeposit.setSecondLegAmount(new BigDecimal(6));
// EXECUTION_DEPOSIT_MATCHER.assertMatch(resultExecutionDeposit, executionDeposit); executionDeposit.setInterestAmount(new BigDecimal(5));
// } executionDeposit.setSide("side");
executionDeposit.setSettlementCurrency("settlementCurrency");
executionDeposit.setCompanyId(companyId);
executionDeposit.setDuration(1L);
executionDeposit.setFirstLegSettlementDate(dtF);
executionDeposit.setSecondLegSettlementDate(dtS);
executionDeposit.setFirstLegSettlementCode("leg1c");
executionDeposit.setSecondLegSettlementCode("legcc");
executionDeposit.setContract("contract");
executionDeposit.setSecurityFullName("full");
executionDeposit.setSecuritySymbol("symbol");
executionDeposit.setSecurityId(securityId);
executionDeposit.setCounterPartyId(0L);
executionDeposit.setCoverageStatus(Allowed.ALLOWED.getKey());
executionDeposit.setSessionId(null);
executionDeposit.setClearingDate(LocalDate.now());
executionDeposit.setId(FIRST_ID);
return executionDeposit;
}
void checkHaveSomeError(long times) {
//ACT
//stage executeClearing(startClearing)
addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_START_CLEARING, PARTITION, times, getJsonStringForNew(new DealRegisterNewRequest(), FIRST_ID));
//waiting for kafka producer send message
verify(mockProducer, timeout(30_000L).times((int) times))
.send(producerRecord.capture());
//ASSERT
assertEquals(Task.createOrder.topic(), producerRecord.getValue().topic());
ExecutionDeposit resultExecutionDeposit = executionDepositImdg.getFirstObjectBySQL("settlementCurrency = 'settlementCurrency'");
executionDeposit.setUpdated(resultExecutionDeposit.getUpdated());
executionDeposit.setCoverageStatus(Allowed.DENIED.getKey());
EXECUTION_DEPOSIT_MATCHER.assertMatch(resultExecutionDeposit, executionDeposit);
}
} }

View file

@ -18,7 +18,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static ru.spcex.clearing.test.TestUtils.*; import static ru.spcex.clearing.utils.TestUtils.*;
class PaymentUpdateBySdf04Test extends AbstractClearingTest { class PaymentUpdateBySdf04Test extends AbstractClearingTest {
private static final int PARTITION = 0; private static final int PARTITION = 0;
@ -80,7 +80,7 @@ class PaymentUpdateBySdf04Test extends AbstractClearingTest {
//ACT //ACT
addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_SDF04_PROCESS, addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_SDF04_PROCESS,
PARTITION, times, getJsonStringForUpdate(requestPayload, sdf04GroupId)); PARTITION, times, getJsonStringForUPDATE(requestPayload, sdf04GroupId));
//waiting for paymentImdgs update //waiting for paymentImdgs update
verify(paymentImdgsMock, timeout(30_000L).times(times)) verify(paymentImdgsMock, timeout(30_000L).times(times))

View file

@ -24,15 +24,15 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static ru.spcex.clearing.test.TestUtils.*; import static ru.spcex.clearing.utils.TestUtils.*;
class VerificationResultComponentTest extends AbstractClearingTest { class VerificationResultComponentTest extends AbstractClearingTest {
private static final int PARTITION = 0; private static final int PARTITION = 0;
private static final AtomicInteger currentInteger = new AtomicInteger(1); private static final AtomicInteger currentInteger = new AtomicInteger(1);
private static final String TOPIC_VERIFICATION = Task.createOrderConfirm.topic(); private static final String TOPIC_VERIFICATION = Task.getVerification.topic();
@Autowired @Autowired
LauncherCommandReceiver receiver; EventsReceiver eventsReceiver;
private Imdg<SDf01> sdf01Imdg; private Imdg<SDf01> sdf01Imdg;
private Imdg<AccountBalance> accountBalanceImdg; private Imdg<AccountBalance> accountBalanceImdg;
private Imdg<Account> accountImdg; private Imdg<Account> accountImdg;
@ -112,8 +112,8 @@ class VerificationResultComponentTest extends AbstractClearingTest {
private void checkVerificationResults(String resultStatuses) { private void checkVerificationResults(String resultStatuses) {
int times = currentInteger.getAndIncrement(); int times = currentInteger.getAndIncrement();
//ACT //ACT
addRecordToKafka((MockConsumer) receiver.getConsumer(), TOPIC_VERIFICATION, addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC_VERIFICATION,
PARTITION, times, getJsonStringForUpdate(new LauncherCommandRequest(), 1L)); PARTITION, times, getJsonStringForUPDATE(new LauncherCommandRequest(), 1L));
ArgumentCaptor<VerificationResult> settingResult = ArgumentCaptor.forClass(VerificationResult.class); ArgumentCaptor<VerificationResult> settingResult = ArgumentCaptor.forClass(VerificationResult.class);
verify(verificationResultImdgMock, timeout(30_000L).times(4 * times)) verify(verificationResultImdgMock, timeout(30_000L).times(4 * times))

View file

@ -21,8 +21,8 @@ import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static ru.spcex.clearing.test.TestUtils.addRecordToKafka; import static ru.spcex.clearing.utils.TestUtils.addRecordToKafka;
import static ru.spcex.clearing.test.TestUtils.getJsonStringForUpdate; import static ru.spcex.clearing.utils.TestUtils.getJsonStringForUPDATE;
class ExecutionDepositComponentTest extends AbstractClearingTest { class ExecutionDepositComponentTest extends AbstractClearingTest {
private static final int PARTITION = 0; private static final int PARTITION = 0;
@ -85,7 +85,7 @@ class ExecutionDepositComponentTest extends AbstractClearingTest {
int times = currentInteger.getAndIncrement(); int times = currentInteger.getAndIncrement();
addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC, addRecordToKafka((MockConsumer) eventsReceiver.getConsumer(), TOPIC,
PARTITION, times, getJsonStringForUpdate(new LauncherCommandRequest(), 1L)); PARTITION, times, getJsonStringForUPDATE(new LauncherCommandRequest(), 1L));
//waiting for kafka producer send message (finale event) //waiting for kafka producer send message (finale event)
// verify(mockProducer, timeout(30_000L).times(times)) // verify(mockProducer, timeout(30_000L).times(times))

View file

@ -0,0 +1,38 @@
package ru.spcex.clearing.utils;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Factory for creating test matchers.
* <p>
* Comparing actual and expected objects via AssertJ
*/
public class MatcherFactory {
public static <T> Matcher<T> usingIgnoringFieldsComparator(String... fieldsToIgnore) {
return new Matcher<>(fieldsToIgnore);
}
public static class Matcher<T> {
private final String[] fieldsToIgnore;
private Matcher(String... fieldsToIgnore) {
this.fieldsToIgnore = fieldsToIgnore;
}
public void assertMatch(T actual, T expected) {
assertThat(actual).usingRecursiveComparison().ignoringFields(fieldsToIgnore).isEqualTo(expected);
}
@SafeVarargs
public final void assertMatch(Iterable<T> actual, T... expected) {
assertMatch(actual, Arrays.asList(expected));
}
public void assertMatch(Iterable<T> actual, Iterable<T> expected) {
assertThat(actual).usingRecursiveFieldByFieldElementComparatorIgnoringFields(fieldsToIgnore).isEqualTo(expected);
}
}
}

View file

@ -0,0 +1,158 @@
package ru.spcex.clearing.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.MockConsumer;
import org.apache.kafka.clients.producer.MockProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.TopicPartition;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets;
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.service.builder.PaymentInstructionCreator;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.ClearingCategory;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
import static ru.spcex.clearing.platform.messaging.service.Status.Success;
import static ru.spcex.clearing.utils.MatcherFactory.usingIgnoringFieldsComparator;
public class TestUtils {
public static final MatcherFactory.Matcher<BaseRequest<Object>> BASE_REQUEST_MATCHER = usingIgnoringFieldsComparator();
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void waitingWhenAddedRecordAndCheckIt(Long id, MockProducer mockProducer, ArgumentCaptor<ProducerRecord> producerRecord) {
BaseRequest<Object> predictableBaseRequest = new BaseRequest<>();
predictableBaseRequest.setId(id);
predictableBaseRequest.setActionType(ActionType.SYSTEM);
RequestInfoUpdate requestInfoUpdate = new RequestInfoUpdate();
requestInfoUpdate.setId(id);
requestInfoUpdate.setStatus(Success);
predictableBaseRequest.setRequestPayload(requestInfoUpdate);
//waiting for kafka producer send message (finale event)
verify(mockProducer, timeout(30_000L).times(1))
.send(producerRecord.capture());
BaseRequest<Object> baseRequestResult = (BaseRequest<Object>) producerRecord.getValue().value();
assertEquals(Consts.REQUEST_INFO_UPDATE, producerRecord.getValue().topic());
BASE_REQUEST_MATCHER.assertMatch(baseRequestResult, predictableBaseRequest);
}
public static void addRecordToKafka(MockConsumer mockConsumer, String topic, int partition, long offset, String jsonValue) {
TopicPartition tp = new TopicPartition(topic, partition);
HashMap<TopicPartition, Long> startOffsets = new HashMap<>();
startOffsets.put(tp, 0L);
mockConsumer.updateBeginningOffsets(startOffsets);
mockConsumer.schedulePollTask(() -> {
mockConsumer.rebalance(Collections.singletonList(tp));
mockConsumer.addRecord(new ConsumerRecord<>(topic, partition, offset, "key", jsonValue));
});
}
public static <T> String getJsonStringForNew(T accountRequest, long id) {
return getJsonBaseRequest(accountRequest, id, ActionType.NEW);
}
public static <T> String getJsonStringForUPDATE(T accountRequest, long id) {
return getJsonBaseRequest(accountRequest, id, ActionType.UPDATE);
}
public static <T> String getJsonStringForDELETE(T accountRequest, long id) {
return getJsonBaseRequest(accountRequest, id, ActionType.DELETE);
}
private static <T> String getJsonBaseRequest(T accountRequest, long id, ActionType actionType) {
BaseRequest<T> baseRequest = new BaseRequest<>();
baseRequest.setRequestPayload(accountRequest);
baseRequest.setId(id);
baseRequest.setActionType(actionType);
String jsonBaseRequest;
try {
jsonBaseRequest = objectMapper.writeValueAsString(baseRequest);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return jsonBaseRequest;
}
public static <T, V> T getMockForFildObj(T from, V obj, String fildName) {
T mock = Mockito.mock((Class<T>) from.getClass(), withSettings()
.serializable()
.spiedInstance(from)
.defaultAnswer(CALLS_REAL_METHODS));
try {
Field dbServiceField = obj.getClass().getDeclaredField(fildName);
dbServiceField.setAccessible(true);
dbServiceField.set(obj, mock);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
return mock;
}
public static <T extends SpcexObjectBase> void clearAllInImdg(Imdg<T> imdg) {
Collection<T> values = imdg.getAllValues();
values.forEach(imdg::delete);
}
public static class FutureRecordMetadata implements Future<RecordMetadata> {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return false;
}
@Override
public RecordMetadata get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public RecordMetadata get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
}
public static class PaymentInstructionCreatorTest extends PaymentInstructionCreator {
public PaymentInstructionCreatorTest(ImdgProvider imdgProvider) {
super(imdgProvider);
}
public PaymentInstruction createPaymentInstruction(ExecutionDeposit executionDeposit, LiabilitiesClaimsAssets liabilitiesClaimsAssets,
Collection<ClearingCategory> clearingCategory) {
List<PaymentInstruction> list = super.createPaymentInstructions(executionDeposit, liabilitiesClaimsAssets, clearingCategory);
return list.stream().findFirst().orElseGet(PaymentInstruction::new);
}
}
}

View file

@ -23,7 +23,7 @@ public class ISchedulerChecker {
/** /**
* @param isWeekend тек.день=СБ-ВС<br> * @param isWeekend тек.день=СБ-ВС<br>
*/ */
public static boolean isValidWorkday(ClearingCalendar clearingCalendar, boolean isWeekend) { public static boolean isWorkDayByTradingCalendar(ClearingCalendar clearingCalendar, boolean isWeekend) {
if (clearingCalendar.getDayStatus() != null && clearingCalendar.getDayStatus().equalsIgnoreCase(DayStatus.Workday.getKey())) { if (clearingCalendar.getDayStatus() != null && clearingCalendar.getDayStatus().equalsIgnoreCase(DayStatus.Workday.getKey())) {
if (isWeekend) { if (isWeekend) {
return clearingCalendar.getCompanyId() != null && clearingCalendar.getCompanyId() != 0; return clearingCalendar.getCompanyId() != null && clearingCalendar.getCompanyId() != 0;
@ -31,4 +31,9 @@ public class ISchedulerChecker {
} }
return false; return false;
} }
public static boolean isWorkDayByTradingCalendar(ClearingCalendar clearingCalendar) {
return clearingCalendar.getDayStatus() != null &&
clearingCalendar.getDayStatus().equalsIgnoreCase(DayStatus.Workday.getKey());
}
} }

Some files were not shown because too many files have changed in this diff Show more