diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/SDFProcessService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/SDFProcessService.java index ed5d3d1af..e22cfa248 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/SDFProcessService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/SDFProcessService.java @@ -1,33 +1,29 @@ package ru.spcex.clearing.account.service; +import java.time.Instant; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; import org.apache.commons.lang3.tuple.Triple; import org.apache.kafka.clients.producer.Producer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.account.Account; -import ru.clearing.classes.statics.data.misc.Notification; import ru.clearing.classes.statics.data.sdf.SDf52; import ru.clearing.classes.statics.data.sdf.SDf53; 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.balance.ExportToFileRequest; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.utilities.NotificationFeedbackRequest; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.platform.enumeration.AccountStatus; -import ru.spcex.platform.enumeration.NotificationStatus; -import ru.spcex.platform.enumeration.ObjectType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgTransaction; -import ru.spcex.platform.utils.collection.Pair; - -import java.time.Instant; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; @Service public class SDFProcessService { @@ -116,6 +112,7 @@ public class SDFProcessService { newSdf.setDeal(sdf52.getDeal()); newSdf.setDate(sdf52.getDate()); newSdf.setStatus(sdf52.getStatus()); + newSdf.setAccType(sdf52.getAcc_type()); newSdf.setResult(result); newSdf.setGenerationTime(now); newSdf.setGenerationId(sdf52.getGenerationId()); diff --git a/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/sdf/SDf53.java b/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/sdf/SDf53.java index ed1038eaa..dce6ce2b8 100644 --- a/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/sdf/SDf53.java +++ b/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/sdf/SDf53.java @@ -1,12 +1,9 @@ package ru.clearing.classes.statics.data.sdf; +import java.time.Instant; import ru.clearing.classes.ConstSerializable; import ru.spcex.platform.classes.base.SpcexObjectBase; -import java.math.BigDecimal; -import java.time.Instant; -import java.time.LocalDate; - /** * ДФ-53 Квитанция о получении информации о состоянии счета (блокировка/разблокировка/закрытие/открытие) *

@@ -25,6 +22,7 @@ public class SDf53 extends SpcexObjectBase { private String fileName; private Long inSDfId; private String accName; + private String accType; public String getAccount() { return account; @@ -105,4 +103,12 @@ public class SDf53 extends SpcexObjectBase { public void setAccName(String accName) { this.accName = accName; } + + public String getAccType() { + return accType; + } + + public void setAccType(String accType) { + this.accType = accType; + } } \ No newline at end of file diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/MarketCodesBySessionConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/MarketCodesBySessionConfig.java index 59864c9ef..2934b9f6f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/MarketCodesBySessionConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/MarketCodesBySessionConfig.java @@ -1,5 +1,10 @@ package ru.spcex.clearing.config; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import ru.clearing.classes.statics.data.misc.Market; @@ -9,12 +14,6 @@ import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; -import java.util.stream.Collectors; - @Configuration public class MarketCodesBySessionConfig { @@ -28,6 +27,11 @@ public class MarketCodesBySessionConfig { return new MarketCodesProvider(imdgProvider, Section.FOND, MarketType.SCND); } + @Bean(name = "marketCodesForCurr") + public Supplier> marketCodesForCurr(ImdgProvider imdgProvider) { + return new MarketCodesProvider(imdgProvider, Section.CURR, MarketType.SCND); + } + @Bean(name = "marketCodesForT0Primary") public Supplier> marketCodesForT0Primary(ImdgProvider imdgProvider) { return new MarketCodesProvider(imdgProvider, Section.FOND, MarketType.PRMR); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java index e8fbcecbb..9c695355d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java @@ -34,6 +34,7 @@ import ru.spcex.clearing.platform.messaging.service.Status; import ru.spcex.clearing.service.executors.Sdf06Executor; import ru.spcex.clearing.service.executors.Sdf10Executor; import ru.spcex.clearing.service.payment.PaymentInstructionOutboundService; +import ru.spcex.clearing.session.stage.CurrencySession; import ru.spcex.clearing.session.stage.FinalMkrSession; import ru.spcex.clearing.session.stage.IntermediateMkrSession; import ru.spcex.clearing.session.stage.PrimaryAuctionB0Session; @@ -60,6 +61,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { private final PrimaryAuctionBnSession primaryAuctionBnSession; private final PrimaryAuctionT0Session primaryAuctionT0Session; private final SecondaryAuctionT0Session secondaryAuctionT0Session; + private final CurrencySession currencySession; private final PrimaryAuctionB0Session primaryAuctionB0Session; private final IntermediateMkrSession intermediateMkrSession; private final FinalMkrSession finalMkrSession; @@ -80,6 +82,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { RegistryService registryService, PrimaryAuctionBnSession primaryAuctionBnSession, SecondaryAuctionT0Session secondaryAuctionT0Session, + CurrencySession currencySession, PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager, Sdf06Executor sdf06Executor, Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender, StatementServiceV2 statementService, SessionTerminator sessionTerminator, PaymentInstructionOutboundService pmtOutboundService) { @@ -90,6 +93,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { this.registryService = registryService; this.primaryAuctionBnSession = primaryAuctionBnSession; this.secondaryAuctionT0Session = secondaryAuctionT0Session; + this.currencySession = currencySession; this.primaryAuctionB0Session = primaryAuctionB0Session; this.primaryAuctionT0Session = primaryAuctionT0Session; this.intermediateMkrSession = intermediateMkrSession; @@ -145,6 +149,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { primaryAuctionBnSession.continueSession(req); primaryAuctionT0Session.continueSession(req); secondaryAuctionT0Session.continueSession(req); + currencySession.continueSession(req); primaryAuctionB0Session.continueSession(req); intermediateMkrSession.continueSession(req); finalMkrSession.continueSession(req); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java index 93d0d2f9a..4ea98f2f6 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java @@ -1,5 +1,7 @@ package ru.spcex.clearing.service; +import java.time.Instant; +import java.time.format.DateTimeFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -18,9 +20,6 @@ import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.number.BigDecimalUtil; import ru.spcex.platform.utils.time.TimeUtil; -import java.time.Instant; -import java.time.format.DateTimeFormatter; - @Component public class Sdf03Creator { private Logger log = LoggerFactory.getLogger(getClass()); @@ -63,6 +62,7 @@ public class Sdf03Creator { sDf03.setId(idGenerator.nextId()); sDf03.setSeg_type("S"); sDf03.setDoc_type("002"); + sDf03.setPay_val(paymentInstruction.getCreditLeg_currencyCode()); String strId = paymentInstruction.getId().toString(); String strIdCut = strId.length() > 16 ? strId.substring(strId.length() - 16) : strId; sDf03.setDocnm_ref(strIdCut); @@ -104,7 +104,6 @@ public class Sdf03Creator { sDf03::setRbanknam5); sDf03.setPay_date(payDateFormatter.format(TimeUtil.toLocalDate(paymentInstruction.getPaymentDate()))); - sDf03.setPay_val("RUR"); String sumDeb = paymentInstruction.getDebitLeg_amount() != null ? paymentInstruction.getDebitLeg_amount().toString() : ""; sDf03.setSum_deb(BigDecimalUtil.limitDecimalPlaces(sumDeb, 2)); sDf03.setSpecif_1(paymentInstruction.getPaymentPurpose()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/TcrSearcher.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/TcrSearcher.java index cf128a442..9c23fdebd 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/TcrSearcher.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/TcrSearcher.java @@ -1,5 +1,6 @@ package ru.spcex.clearing.service; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -12,6 +13,7 @@ import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.CurrencyCode; import ru.spcex.platform.enumeration.ServiceStatus; +import ru.spcex.platform.enumeration.Status; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -48,7 +50,44 @@ public class TcrSearcher { this.accountImdg = accountImdg; } - public AnltSearcher.AnltSearch loadByCurrencyAccountId(Long accountId, String currency) { + + public Optional searchByTcr(Long tcrId, String currency) { + TradingClearingRegistry tcr = tcrImdg.getSingleObjectByID(tcrId); + if (tcr == null || (CurrencyCode.RUB.equalsByKey(currency) && tcr.getMoneyAccountId() == null)) { + log.warn("couldn't find account by tcr#id={}; currency {}. TCR {}", + tcrId, currency, tcr != null ? "found" : "not found"); + return Optional.empty(); + } + if (CurrencyCode.RUB.equalsByKey(currency)) { + Optional acc = Optional.ofNullable(accountImdg.getSingleObjectByID(tcr.getMoneyAccountId())); + if (acc.isEmpty()) { + log.warn("couldn't find account by tcr#id={}; currency {}. tcr#moneyAccountId {}.", + tcrId, currency, tcr.getMoneyAccountId()); + } + return acc; + } + ImdgPredicateBuilder pb = tcrListImdg.predicateBuilder(); + TradingClearingRegistryList tcrList = tcrListImdg.getFirstObjectByPredicate( + pb.and( + pb.equals("tradingClearingRegistryId", tcr.getId()), + pb.equals("currency", currency), + pb.equals("status", Status.Active.getKey()) + ) + ); + if (tcrList == null || tcrList.getAccountId() == null) { + log.warn("couldn't find account by tcr#id={}; currency {}. tcrList {}.", + tcrId, currency, tcrList != null ? (tcrList.getId() + " present though.") : "not found"); + return Optional.empty(); + } + Account acc = accountImdg.getSingleObjectByID(tcrList.getAccountId()); + if (acc == null) { + log.warn("couldn't find account by tcr#id={}; currency {}. tcrList.id={}.", + tcrId, currency, tcrList.getId()); + } + return Optional.of(acc); + } + + public AnltSearcher.AnltSearch searchByAccountId(Long accountId, String currency) { AnltSearcher.AnltSearch srchRes = new AnltSearcher.AnltSearch(); ImdgPredicateBuilder pb = tcrImdg.predicateBuilder(); ImdgPredicate sttsPrdct = pb.or( diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java index 636bdbb23..74ff213b7 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderV2.java @@ -1,5 +1,12 @@ package ru.spcex.clearing.service.builder; +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,7 +18,16 @@ import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.enumeration.CompanyRole; +import ru.spcex.platform.enumeration.CompanySymbol; +import ru.spcex.platform.enumeration.CurrencyCode; +import ru.spcex.platform.enumeration.InOutDirection; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.enumeration.Sender; +import ru.spcex.platform.enumeration.SpecifFlag; +import ru.spcex.platform.enumeration.TransactionStatus; +import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -20,14 +36,6 @@ import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.time.TimeUtil; -import java.math.BigDecimal; -import java.time.Instant; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; - public class PaymentInstructionBuilderV2 { private final static Logger log = LoggerFactory.getLogger(PaymentInstructionBuilderV2.class); private Registry registry; @@ -47,6 +55,7 @@ public class PaymentInstructionBuilderV2 { private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy"); private Long senderId; private Long addresseeId; + private String currency; private boolean useCS_BLKD = false; private Registry am_b; @@ -113,6 +122,11 @@ public class PaymentInstructionBuilderV2 { return this; } + public PaymentInstructionBuilderV2 currency(String currency) { + this.currency = currency; + return this; + } + public PaymentInstruction build() { Instant now = Instant.now(); PaymentInstruction payment = new PaymentInstruction(); @@ -175,8 +189,13 @@ public class PaymentInstructionBuilderV2 { } payment.setDebit_csAccount(null); - payment.setCreditLeg_currencyCode(CurrencyCode.RUB.getKey()); - payment.setDebitLeg_currencyCode(CurrencyCode.RUB.getKey()); + if (currency != null) { + payment.setCreditLeg_currencyCode(currency); + payment.setDebitLeg_currencyCode(currency); + } else { + payment.setCreditLeg_currencyCode(CurrencyCode.RUB.getKey()); + payment.setDebitLeg_currencyCode(CurrencyCode.RUB.getKey()); + } payment.setTransactionStatus(TransactionStatus.stld.getKey()); payment.setDocumentNumber(nextDocumentNumber(registry, payment)); payment.setCreditLeg_direction(InOutDirection.out.getKey()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/RegistryBuilder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/RegistryBuilder.java index 73af2f4e6..7bc429dfb 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/RegistryBuilder.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/RegistryBuilder.java @@ -117,7 +117,7 @@ public class RegistryBuilder { rgs.setRegistryCode(RegistryUtil.clearingCode(rgs)); if (currency != null) { - AnltSearcher.AnltSearch anltSearch = tcrSrcher.loadByCurrencyAccountId(account.getId(), currency); + AnltSearcher.AnltSearch anltSearch = tcrSrcher.searchByAccountId(account.getId(), currency); if (anltSearch.isFound()) { TradingClearingRegistry tcr = anltSearch.getTcr(); rgs.setTradingClearingRegistryId(tcr.getId()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/execution/ExecutionCurrencyComponent.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/execution/ExecutionCurrencyComponent.java index 24c468396..10c68106d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/execution/ExecutionCurrencyComponent.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/execution/ExecutionCurrencyComponent.java @@ -1,17 +1,23 @@ package ru.spcex.clearing.service.execution; +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; 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.Qualifier; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.execution.ExecutionCurrency; import ru.clearing.classes.statics.data.misc.Listing; -import ru.clearing.classes.statics.data.misc.Market; import ru.clearing.classes.statics.data.misc.STrades; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.security.Security; @@ -36,15 +42,6 @@ import ru.spcex.platform.utils.log.ExceptionUtils; import ru.spcex.platform.utils.time.TimeUtil; import ru.spcex.platform.utils.validation.IValidator; -import java.math.BigDecimal; -import java.time.Instant; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; - /** * ExecutionCurrency - Сделки на Валютной секции */ @@ -186,7 +183,7 @@ public class ExecutionCurrencyComponent { eCurrency.setExchangeExecutionTime(sTrades.getTradeDateTime()); eCurrency.setExchangeExecutionMicroseconds(sTrades.getTradeDateTime()); // todo проверить это дата+время или нет eCurrency.setPartyTradingClearingRegistryId(rgstr.getId()); // setTradingClearingRegistryId - eCurrency.setPartyTradingClearingRegistry(sTrades.getAccount()); // todo уточнить rgstr.code/strades.account? + eCurrency.setPartyTradingClearingRegistry(rgstr.getCode()); // todo уточнить rgstr.code/strades.account? eCurrency.setMarket(sTrades.getClassCode()); // { todo нет поля Description и не понятно как искать Market // Market market = market=market.code ; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf04Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf04Executor.java index 3459ff88d..8ab3418be 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf04Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf04Executor.java @@ -1,5 +1,11 @@ package ru.spcex.clearing.service.executors; +import java.math.BigDecimal; +import java.time.Instant; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,7 +21,11 @@ import ru.spcex.clearing.service.AnltSearcher; import ru.spcex.clearing.service.model.Result; import ru.spcex.clearing.service.registry.AssetTBFProcessing; import ru.spcex.clearing.service.registry.RegistryManager; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.enumeration.Status; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -23,13 +33,6 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.log.ExceptionUtils; -import java.math.BigDecimal; -import java.time.Instant; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Optional; - @Service public class Sdf04Executor extends AbstractExecutor { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -84,8 +87,10 @@ public class Sdf04Executor extends AbstractExecutor { //обычно мы ищем по группу sdf04, здесь как будто всегда только одна запись, todo нужно прочекать этот момент log.debug("Process sdf04 record; sdf04.id: {}", sdf04.getId()); Collection registries; - Account anltAcc = accountImdg.getFirstObjectBySQL("account = '%s' and accountType = '%s'" - .formatted(sdf04.getC_acc_deb(), AccountType.Anlt.getKey())); + Account anltAcc = accountImdg.getFirstObjectBySQL("account = '%s' and accountType = '%s' and currency = '%s'" + .formatted(sdf04.getC_acc_deb(), + AccountType.Anlt.getKey(), + sdf04.getPay_val())); // Account tranAcc = accountImdg.getFirstObjectBySQL("account = '%s' and accountType = '%s'" // .formatted(sdf04.getC_acc_cred(), AccountType.Tran.getKey())); // //если сдф04 не по аналитическому счету ни по tran счету, выбираем по тому c_acc_deb/c_acc_cred что пришло @@ -100,7 +105,7 @@ public class Sdf04Executor extends AbstractExecutor { // registries = selectRegistryForSDF04(acc); } else { //в сдф04 указан ANLT или TRAN счет, ищем по контракту - AnltSearcher.AnltSearch anltSearch = anltSearcher.loadByAnlt(sdf04.getSpecif_1()); + AnltSearcher.AnltSearch anltSearch = anltSearcher.loadByAnlt(sdf04.getSpecif_1(), sdf04.getPay_val()); if (!anltSearch.isFound()) { log.error("sdf04.id={} search by specif1 failed {}", sdf04.getId(), msgRslv.resolve(anltSearch.getError())); registries = Collections.emptyList(); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java index 6b988bf17..e0927b70f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java @@ -348,6 +348,8 @@ public class Sdf06Executor { sDf07.setNumber(sdf06.getNumber()); sDf07.setSpec(sdf06.getSpec()); sDf07.setResult(result); + sDf07.setDoc_Date(sdf06.getDoc_Date()); + sDf07.setDoc_Num(sdf06.getDoc_Num()); sDf07.setPay_val(sdf06.getPay_val()); return sDf07; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf06NewValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf06NewValidationRule.java index 30cd00265..49fe1010b 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf06NewValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf06NewValidationRule.java @@ -207,7 +207,7 @@ public enum Sdf06NewValidationRule implements IValidationRule executionFondImdg; + private final Imdg executionCurrencyImdg; + private final Supplier> marketCodes; + private SessionMonitor firstReviseMonitor; + private SessionMonitor afterPaymentsSdf4And13Monitor; + private SessionMonitor afterPaymentsReviseMonitor; + private SessionMonitor afterReviseErrorMonitor; + + + public CurrencySession( + ImdgProvider imdgProvider, + BalanceRevise balanceRevise, + DealsPrepare dealsPrepare, + RequirementsAndObligationCreation requirementsAndObligationCreation, + ObligationAdmission obligationsAdmission, + InclusionObligations inclusionObligations, + FormingRegistersOnOS formingRegistersOnOS, + FormingPaymentInstructionAssets formingPaymentInstructionAssets, + UnlockResources unlockResources, + FinishingSession finishingSession, + EndStageNotification endStageNotification, + IMessageResolver messageResolver, + InspectionObligations inspectionObligations, + @Qualifier("marketCodesForCurr") Supplier> marketCodes) { + super(imdgProvider, messageResolver); + this.balanceRevise = balanceRevise; + this.dealsPrepare = dealsPrepare; + this.requirementsAndObligationCreation = requirementsAndObligationCreation; + this.obligationsAdmission = obligationsAdmission; + this.inclusionObligations = inclusionObligations; + this.formingRegistersOnOS = formingRegistersOnOS; + this.formingPaymentInstructionAssets = formingPaymentInstructionAssets; + this.unlockResources = unlockResources; + this.finishingSession = finishingSession; + this.endStageNotification = endStageNotification; + this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + this.executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class); + this.inspectionObligations = inspectionObligations; + this.marketCodes = marketCodes; + } + + @Override + public void afterPropertiesSet() throws Exception { + dealsPrepare.searchForExecutions(ExecutionType.ExecutionCurrency); + ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder(); + dealsPrepare.addExecutionCurrencyCondition(execFondPb.regex("settlementCode", "^T0.*$")); + dealsPrepare.addExecutionCurrencyCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0]))); + formingPaymentInstructionAssets.setSessionType(sessionType()); + inclusionObligations.setSessionType(sessionType()); + inspectionObligations.setSection(section()); + finishingSession.setSection(section()); + finishingSession.setSessionType(sessionType()); + imdgProvider.waitAvailable(); + initSessionIfPresent(); + } + + @Override + public void runSession(BaseRequest req) { + if (!startSession()) { + return; + } + StageResult submit = balanceRevise.submit(new Task<>(TaskType.StartRevise, null)); + if (!submit.success) { + log.error("stage {} error={}", balanceRevise.getClass().getSimpleName(), messageResolver.resolve(submit.error)); + endSession(); + } else { + log.info("stage BalanceRevise success, waiting for a response from kafka"); + this.firstReviseMonitor = SessionMonitorFactory.waitRevise(); + } + } + + public void continueSession(BaseRequest req) { + try { + if (!isRunning()) { + return; + } + log.info("session is running, stage {}, monitors: {}", + currStage.get(), + logMonitors(firstReviseMonitor, afterPaymentsSdf4And13Monitor, afterPaymentsReviseMonitor)); + if (firstReviseMonitor != null && isMonitorPassed(firstReviseMonitor, req.getRequestPayload())) { + firstReviseMonitor = null; + firstPart(); + return; + } + if (afterPaymentsSdf4And13Monitor != null && isMonitorPassed(afterPaymentsSdf4And13Monitor, req.getRequestPayload())) { + afterPaymentsSdf4And13Monitor = null; + checkStageAndThrow(TaskType.FormingPaymentInstruction); + finishPart(); + return; + } + if (afterReviseErrorMonitor != null && isMonitorPassed(afterReviseErrorMonitor, req.getRequestPayload())) { + afterReviseErrorMonitor = null; + finishPart(); + return; + } + //if (afterPaymentsReviseMonitor != null && isMonitorPassed(afterPaymentsReviseMonitor, req.getRequestPayload())) { + // afterPaymentsReviseMonitor = null; + // finishPart(); + //} + } catch (StageException e) { + //already logged + } + } + + private void firstPart() { + try { + if (!checkStage(TaskType.StartRevise)) { + log.error("cannot continue session, current stage is {}", currStage.get()); + throw new StageException(); + } + runStage(TaskType.StartRevisePart1, currSession.getId(), balanceRevise); + //stage 1 + StageResult> dealsPreparationResult; + { + DealsPreparePayload payload = new DealsPreparePayload(); + payload.setSessionId(currSession.getId()); + dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); + } + //stage 2 + runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + //stage 3 + runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); + //stage 4 + { + InclusionToPoolPayload inclusionToPoolPayload = new InclusionToPoolPayload(); + inclusionToPoolPayload.setSessionType(currSession.getSessionType()); + inclusionToPoolPayload.setSessionId(currSession.getId()); + runStage(TaskType.InclusionToPool, inclusionToPoolPayload, inclusionObligations); + } + //stage 5 + { + InspectionPoolPayload companyIdPayload = new InspectionPoolPayload(); + companyIdPayload.setSessionId(currSession.getId()); + companyIdPayload.setProcessedCompanyId(currSession.getCompanyId()); + runStage(TaskType.InspectionObligations, companyIdPayload, inspectionObligations); + } + //stage 6 + { + FormingRegistersOnOSPayload payload = new FormingRegistersOnOSPayload(); + payload.setSessionId(currSession.getId()); + runStage(TaskType.FormingRegistersOnOS, payload, formingRegistersOnOS); //returns Collection + } + //stage 7 + StageResult paymentResult = null; + { + FormingPaymentInstructionPayload payload = new FormingPaymentInstructionPayload(); + payload.setSessionId(currSession.getId()); + paymentResult = runStage(TaskType.FormingPaymentInstruction, payload, formingPaymentInstructionAssets); + } + + if (paymentResult.getStageResult().getPaymentInstructions().isEmpty()) { + log.info("no payment instructions were created"); + finishPart(); + } else { + this.afterPaymentsSdf4And13Monitor = SessionMonitorFactory.waitStep7(section()); + log.info("created {} PaymentInstructions, waiting for {}", + paymentResult.getStageResult().getPaymentInstructions().size(), + this.afterPaymentsSdf4And13Monitor.allConditions()); + } + } catch (StageException e) { + //already logged + } + } + + public void finishPart() { + try { + //stage 9 continue revision + { + StageResult reviseRes = runStage(TaskType.AgainRevise, currSession.getId(), balanceRevise, false); + if (!reviseRes.isSuccess()) { + this.afterReviseErrorMonitor = SessionMonitorFactory.waitReviseError(section()); + log.warn("{} stage error, created monitor for {}", + TaskType.AgainRevise, + afterReviseErrorMonitor.allConditions()); + return; + } + } + //stage 10 + { + FinishingSessionPayload payload = new FinishingSessionPayload(); + payload.setSessionId(currSession.getId()); + payload.setPr("1"); + runStage(TaskType.FinishingSession, payload, finishingSession); + } + //stage 11 + { + EndStageNotificationPayload payload = new EndStageNotificationPayload(); + payload.setSection(currSession.getSection()); + payload.setSessionId(currSession.getId()); + runStage(TaskType.EndStageNotification, payload, endStageNotification); + endSession(); + } + } catch (StageException e) { + //already logged + } + } + + private boolean startSession() { + synchronized (this.currStage) { + if (this.currStage.get() != null) { + log.info("already running session.id={}", this.currSession.getId()); + return false; + } else { + TaskType startStatus = TaskType.StartRevise; + Session newSession = new Session(); + newSession.setSection(Section.MKR.getKey()); + newSession.setSessionType(sessionType().getKey()); + newSession.setSessionStatus(startStatus.getKey()); + newSession.setWorkflowStatus(SessionStatus.ACTV.getKey()); + newSession.setClearingDate(LocalDate.now()); + newSession.setCreated(Instant.now()); + + //todo companyId/securityId/userId передается из сообщения очереди + sessionImdg.insert(newSession); + currSession = newSession; + log.info("started new session.id={}", this.currSession.getId()); + currStage.set(TaskType.StartRevise); + return true; + } + } + } + + @Override + protected Section section() { + return Section.MKR; + } + + @Override + protected SessionType sessionType() { + return SessionType.CURR; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java index 5294808d8..c342ddee4 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java @@ -1,5 +1,6 @@ package ru.spcex.clearing.session.stage; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -10,7 +11,11 @@ import ru.spcex.clearing.notification.NotificationSender; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; import ru.spcex.clearing.service.schedule.TradingTimeService; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.ObjectType; +import ru.spcex.platform.enumeration.Priority; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.SessionStatus; +import ru.spcex.platform.enumeration.SessionType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -18,8 +23,6 @@ import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.error.ValidationException; -import java.util.Map; - @Service public class SessionManager { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -31,6 +34,7 @@ public class SessionManager { private final PrimaryAuctionBnSession primaryAuctionBnSession; private final PrimaryAuctionB0Session primaryAuctionB0Session; private final SecondaryAuctionT0Session secondaryAuctionT0Session; + private final CurrencySession currencySession; private final IntermediateMkrSession intermediateMkrSession; private final FinalMkrSession finalMkrSession; private final ReturnDepositSession returnDepositSession; @@ -40,7 +44,7 @@ public class SessionManager { NotificationSender notification, IMessageResolver msgs, PrimaryAuctionT0Session primaryAuctionT0Session, PrimaryAuctionBnSession primaryAuctionBnSession, PrimaryAuctionB0Session primaryAuctionB0Session, - SecondaryAuctionT0Session secondaryAuctionT0Session, + SecondaryAuctionT0Session secondaryAuctionT0Session, CurrencySession currencySession, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, TradingTimeService time) { this.notification = notification; this.msgs = msgs; @@ -48,6 +52,7 @@ public class SessionManager { this.primaryAuctionBnSession = primaryAuctionBnSession; this.primaryAuctionB0Session = primaryAuctionB0Session; this.secondaryAuctionT0Session = secondaryAuctionT0Session; + this.currencySession = currencySession; this.intermediateMkrSession = intermediateMkrSession; this.finalMkrSession = finalMkrSession; this.returnDepositSession = returnDepositSession; @@ -109,6 +114,7 @@ public class SessionManager { case IPOT -> session = primaryAuctionT0Session; case IPO0 -> session = primaryAuctionB0Session; case TRDT -> session = secondaryAuctionT0Session; + case CURR -> session = currencySession; case MEDM -> session = intermediateMkrSession; case FINL -> session = finalMkrSession; case XDEP -> session = returnDepositSession; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java index e66c6139f..9f688b677 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java @@ -1,5 +1,11 @@ package ru.spcex.clearing.session.stage.impl; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -7,6 +13,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionCurrency; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.execution.ExecutionFond; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -20,27 +27,23 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; - @Service @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class DealsPrepare implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg executionDepositImdg; private final Imdg executionFondImdg; + private final Imdg executionCurrencyImdg; private final List execDepositPredicates = new ArrayList<>(); private final List execFondPredicates = new ArrayList<>(); + private final List execCurrencyPredicates = new ArrayList<>(); private ExecutionType executionType = ExecutionType.ExecutionFond; @Autowired public DealsPrepare(ImdgProvider imdgProvider) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + this.executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class); } public void searchForExecutions(ExecutionType executionType) { @@ -102,6 +105,14 @@ public class DealsPrepare implements ISessionStage { .map(execToInterface()) .collect(Collectors.toList()); } + case ExecutionCurrency -> { + ImdgPredicate excCurrPrct = prdComposer.apply(execCurrencyPredicates, executionCurrencyImdg); + log.info("using predicate to load deals: {}", excCurrPrct.toString()); + excs = executionCurrencyImdg.getCollectionObjectsByPredicate(excCurrPrct) + .stream() + .map(execToInterface()) + .collect(Collectors.toList()); + } default -> throw new IllegalStateException("Unknown execution type: " + executionType); } for (ExecutionCommon exc : excs) { @@ -110,6 +121,8 @@ public class DealsPrepare implements ISessionStage { executionDepositImdg.update((ExecutionDeposit) exc); } else if (exc instanceof ExecutionFond) { executionFondImdg.update((ExecutionFond) exc); + } else if (exc instanceof ExecutionCurrency ) { + executionCurrencyImdg.update((ExecutionCurrency) exc); } } StageResult> res = new StageResult<>(null, true); @@ -128,6 +141,11 @@ public class DealsPrepare implements ISessionStage { return this; } + public DealsPrepare addExecutionCurrencyCondition(ImdgPredicate imdgPredicate) { + this.execCurrencyPredicates.add(imdgPredicate); + return this; + } + private static Function execToInterface() { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java index 31304592f..e8b43522e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionAssets.java @@ -1,5 +1,14 @@ package ru.spcex.clearing.session.stage.impl; +import java.math.BigDecimal; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +36,17 @@ import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.AccountStatus; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.Allowed; +import ru.spcex.platform.enumeration.InstrumentType; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryStatus; +import static ru.spcex.platform.enumeration.RegistryTradingParams.*; +import ru.spcex.platform.enumeration.SdfTable; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.Sender; +import ru.spcex.platform.enumeration.SessionType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -40,13 +59,6 @@ import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; import ru.spcex.platform.utils.number.BigDecimalUtil; - -import java.math.BigDecimal; -import java.time.Instant; -import java.util.*; -import java.util.stream.Stream; - -import static ru.spcex.platform.enumeration.RegistryTradingParams.*; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; @Service @@ -136,13 +148,6 @@ public class FormingPaymentInstructionAssets implements ISessionStage { Collection AMBregistries = selectAMBRegistries(sessionId); log.debug("found AMB registries.size() = {}", AMBregistries.size()); Instant now = Instant.now(); - Account tranAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" - .formatted(AccountType.Tran.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); - if (tranAcc == null) { - return new StageResult<>( - new EnumMessage(ClearingError.AccountNotPresent, "accountType = " + AccountType.Tran.getKey()), - false); - } Account dtrnAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" .formatted(AccountType.Dtrn.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); @@ -154,6 +159,19 @@ public class FormingPaymentInstructionAssets implements ISessionStage { List paymentInstructions = new ArrayList<>(); for (Registry registry : AMBregistries) { + Account tranAcc = accountImdg.getFirstObjectBySQL(("accountType = '%s' " + + "and status = '%s' " + + "and currency = '%s' " + + "and processingSign = '%s'") + .formatted(AccountType.Tran.getKey(), + AccountStatus.ACTIVE.getKey(), + registry.getSecuritySymbol(), + Allowed.ALLOWED.getKey())); + if (tranAcc == null) { + return new StageResult<>( + new EnumMessage(ClearingError.AccountNotPresent, "accountType = " + AccountType.Tran.getKey()), + false); + } //по каждому AMB регистру создаем PaymentInstruction //проверяем balance посчитанный на шаге 5 Account counterAcc = null; @@ -162,6 +180,7 @@ public class FormingPaymentInstructionAssets implements ISessionStage { } else if (AccountType.Info.equalsByKey(registry.getAccountType())) { counterAcc = accountImdg.getFirstObjectByFieldValues( Map.of("companyId", 1L, + "currency", registry.getSecuritySymbol(), "accountType", AccountType.Anlt.getKey()) ); } @@ -214,6 +233,7 @@ public class FormingPaymentInstructionAssets implements ISessionStage { .debitLegAccount(debitLegAccount) .creditLegAccount(creditLegAccount) .amount(amount) + .currency(SessionType.CURR.equals(sessionType) ? registry.getSecuritySymbol() : null) .sessionId(sessionId) .checkBLKD((SessionType.FINL.equals(sessionType) || SessionType.MEDM.equals(sessionType)) && !isPositiveBalance ? registry : null) @@ -286,6 +306,7 @@ public class FormingPaymentInstructionAssets implements ISessionStage { .creditLegAccount(creditLegAccount) .amount(amount) .sessionId(sessionId) + .currency(SessionType.CURR.equals(sessionType) ? registry.getSecuritySymbol() : null) .purpose(String.format("Перевод по итогу клиринга по ТКР %s", registry.getTradingClearingRegistry())); PaymentInstruction paymentInstruction = paymentInstructionBuilder.build(); log.debug("Created paymentInstruction by registry.id: {}", registry.getId()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java index fdc9be3a4..1d6eba81d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java @@ -1,5 +1,13 @@ package ru.spcex.clearing.session.stage.impl; +import java.time.Instant; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -7,6 +15,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionCurrency; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.execution.ExecutionFond; import ru.clearing.classes.statics.data.misc.Session; @@ -17,7 +26,11 @@ import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.enumeration.SessionType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -25,11 +38,6 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IEnumKey; -import java.time.Instant; -import java.time.LocalDate; -import java.util.*; -import java.util.stream.Collectors; - @Service @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @@ -42,6 +50,7 @@ public class InclusionObligations implements ISessionStage { private Imdg sessionImdg; private final Imdg executionDepositImdg; private final Imdg executionFondImdg; + private final Imdg executionCurrImdg; private KafkaSender kafkaSender; private final List registryConditions = new ArrayList<>(); private SessionType sessionType; @@ -55,6 +64,7 @@ public class InclusionObligations implements ISessionStage { this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + this.executionCurrImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class); this.rgsPb = registryImdg.predicateBuilder(); } @@ -141,6 +151,7 @@ public class InclusionObligations implements ISessionStage { switch (ssnTpe) { case MEDM, FINL, XDEP -> execImdg = (Imdg) executionDepositImdg; case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg) executionFondImdg; + case CURR -> execImdg = (Imdg) executionCurrImdg; default -> execImdg = null; } if (execImdg == null) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java index 40822eb5d..f919c7773 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java @@ -1,5 +1,16 @@ package ru.spcex.clearing.session.stage.impl; +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -19,7 +30,14 @@ import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; import ru.spcex.clearing.session.stage.util.RegistryUtil; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import static ru.spcex.platform.enumeration.RegistryTradingParams.*; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.SessionType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; @@ -29,15 +47,6 @@ import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; - -import java.math.BigDecimal; -import java.time.Instant; -import java.time.LocalDate; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static ru.spcex.platform.enumeration.RegistryTradingParams.*; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; @@ -259,12 +268,18 @@ public class InspectionObligations implements ISessionStage { private void defineStatusAndUpdateRegistry(List checkResults, List registries) { boolean isOneUncovered = checkResults.stream().anyMatch(checkResult -> checkResult.isUncovered); log.debug("groupId {}, uncovered: {}", registries.stream().findFirst().map(Registry::getGroupId).orElse(null), isOneUncovered); + String commentErr = msgResolver.resolve(ClearingError.InsecurityObligation, checkResults.stream() + .filter(chk -> chk.isUncovered) + .map(chk -> chk.registry.getCompanyId()) + .findFirst().orElse(null)); + if (isOneUncovered) { for (CheckResult checkResult : checkResults) { Optional tRegistryWithSameCompany = registries.stream().filter(registry -> registry.getCompanyId().equals(checkResult.registry.getCompanyId()) && !registry.getRegistryDesignation().equals(checkResult.registry.getRegistryDesignation()) ).findFirst(); + checkResult.registry.setComment(commentErr); if (checkResult.isUncovered) { updateRegistryStatus(checkResult.registry, uncvStatus()); tRegistryWithSameCompany.ifPresent(registry -> updateRegistryStatus(registry, failStatus())); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryCurrBuilder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryCurrBuilder.java new file mode 100644 index 000000000..2e76d0750 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryCurrBuilder.java @@ -0,0 +1,244 @@ +package ru.spcex.clearing.session.stage.impl; + +import java.time.Instant; +import java.time.LocalDate; +import java.util.Map; +import java.util.Optional; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.ClearingAccount; +import ru.clearing.classes.statics.data.account.DepoAccount; +import ru.clearing.classes.statics.data.account.InformationAccount; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionCurrency; +import ru.clearing.classes.statics.data.misc.Currency; +import ru.clearing.classes.statics.data.misc.Market; +import ru.clearing.classes.statics.data.misc.Session; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.clearing.classes.statics.data.security.CurrencyPairSecurity; +import ru.clearing.classes.statics.data.security.Security; +import ru.clearing.platform.dictionary.CurrencyPairDictionary; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.TcrSearcher; +import ru.spcex.clearing.session.stage.util.RegistryUtil; +import ru.spcex.platform.classes.base.interfaces.ExecutionType; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.BalanceDimension; +import ru.spcex.platform.enumeration.CurrencyCode; +import ru.spcex.platform.enumeration.ISide; +import ru.spcex.platform.enumeration.MoneyFlowSide; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.enumeration.Side; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; + +public class RegistryCurrBuilder implements IRegistryBuilder { + private Imdg companyImdg; + private Imdg tradingClearingRegistryImdg; + private Imdg accountImdg; + private Imdg marketImdg; + private Imdg sessionImdg; + private Imdg clearingAccountImdg; + private Imdg informationAccountImdg; + private Imdg depoAccountImdg; + private Imdg currencyImdg; + private Imdg currPairSecImdg; + private Imdg currPairDictImdg; + private SecuritySelector scrSlctr; + private TcrSearcher tcrSearcher; + private ExecutionCommon exec; + private RegistryDesignation regDsgn; + + + private RegistryCurrBuilder() { + } + + public static RegistryCurrBuilder builder() { + return new RegistryCurrBuilder(); + } + + @Override + public RegistryCurrBuilder imdg(ImdgProvider imdgProvider) { + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, Market.class); + this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); + this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class); + this.depoAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); + this.informationAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_InformationAccount, InformationAccount.class); + this.currPairSecImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class); + this.currPairDictImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairDictionary, CurrencyPairDictionary.class); + this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class); + this.scrSlctr = new SecuritySelector<>(imdgProvider, Security.class); + this.tcrSearcher = new TcrSearcher(imdgProvider); + return this; + } + + @Override + public RegistryCurrBuilder exec(ExecutionCommon exec) { + this.exec = exec; + return this; + } + + @Override + public RegistryCurrBuilder registryDesignation(RegistryDesignation registryDesignation) { + this.regDsgn = registryDesignation; + return this; + } + + @Override + public IRegistryBuilder returnDeposit(boolean returnDep) { + if (returnDep) { + throw new IllegalStateException("cannot create second leg registry for ExecutionFond"); + } + return this; + } + + @Override + public Registry build() { + ISide side = getSide(exec); + Registry reg = new Registry(); + reg.setCompanyId(exec.getCompanyId()); + reg.setCreated(Instant.now()); + Company company = searchCompany(); + reg.setTradingCode(company.getTradingCode()); + reg.setClearingCode(company.getClearingCode()); + reg.setShortName(company.getShortName()); + reg.setFullName(company.getFullName()); + TradingClearingRegistry tcr = searchTradingClearingRegistry(); + String capacityByAccount = null; + + //In: execution_currency (SECURITY_SYMBOL: CNYRUB_TOM_C, securityId-->registry.contract) + // C securityId идем в currency_pair_security, чтобы найти currency_pair_id + // C currency_pair_id идем currency_pair_dictionary для базовой base_currency_id [CNY], и обменная в чем торги quote_currency_id [RUB] + //3.1 Для side=Buy + //OM_T = RUB [quote_currency_id] balance=settlement_ammount + //TM_T = CNY [base_currency_id] balance=quantity + //3.2 для side=Sell + //OM_T = CNY [base_currency_id] balance=quantity + //TM_T = RUB [quote_currency_id] balance=settlement_ammount + reg.setContract(String.valueOf(exec.getSecurityId())); + CurrencyPairSecurity curPairSec = currPairSecImdg.getFirstObjectBySQL( + "code = '%s'".formatted(exec.getSecuritySymbol()) //fixme or securityId = "" + ); + CurrencyPairDictionary curPairDict = null; + if (curPairSec != null) { + curPairDict = currPairDictImdg.getFirstObjectBySQL("id = %d".formatted(curPairSec.getCurrencyPairId())); + } + assert curPairSec != null && curPairDict != null; + ExecutionCurrency execCurr = (ExecutionCurrency) this.exec; + //что покупают + String baseCurrency = curPairDict.getBaseCurrency(); + //за что покупают + String quoteCurrency = curPairDict.getQuoteCurrency(); + reg.setRegistryInstrumentType(RegistryInstrumentType.M.getKey()); + reg.setBalanceDimension(BalanceDimension.MONY.getKey()); + String curr; + + Currency currency; + if ((regDsgn.equals(RegistryDesignation.O) && side.isBuy()) || (regDsgn.equals(RegistryDesignation.T) && side.isSell())) { + curr = quoteCurrency; + reg.setBalance(execCurr.getSettlementAmount()); + } else if ((regDsgn.equals(RegistryDesignation.T) && side.isBuy()) || (regDsgn.equals(RegistryDesignation.O) && side.isSell())) { + curr = baseCurrency; + reg.setBalance(execCurr.getQuantity()); + } else curr = CurrencyCode.RUB.getKey(); + currency = currencyImdg.getFirstObjectByFieldValues( + Map.of("currencyCode", curr) + ); + reg.setSecurityId(currency.getId()); + reg.setSecuritySymbol(currency.getCurrencyCode()); + Optional acc = tcrSearcher.searchByTcr(exec.getTradingClearingRegistryId(), curr); + if (acc.isPresent()) { + reg.setAccountId(acc.get().getId()); + reg.setAccount(acc.get().getAccount()); + reg.setAccountType(acc.get().getAccountType()); + capacityByAccount = defineCapacityByAccountType(acc.get().getAccountType(), acc.get().getId()); + } + + reg.setRegistryDesignation(regDsgn.getKey()); + if (capacityByAccount != null) { + reg.setRegistryCapacity(capacityByAccount); + } + reg.setRegistryUnit(RegistryUnit.T.getKey()); + reg.setRegistryCode(RegistryUtil.clearingCode(reg)); + reg.setTradingClearingRegistryId(exec.getTradingClearingRegistryId()); + reg.setTradingClearingRegistry(tcr.getCode()); + reg.setRegistryStatus(RegistryStatus.PROC.getKey()); +// if (isMoney) { +// Security security = scrSlctr.selectSecurityById(execFond.getSecurityId()); +// if (InstrumentType.BOND.equalsByKey(security.getInstrumentType())) { +// BigDecimal stlAmt = safeBD(execFond.getSettlementAmount()); +// BigDecimal intAmt = safeBD(execFond.getInterestAmount()); +// reg.setBalance(stlAmt.add(intAmt.setScale(2, RoundingMode.HALF_UP))); +// } else { +// reg.setBalance(execFond.getSettlementAmount()); +// } +// } else { +// reg.setBalance(execFond.getQuantity()); +// } + + reg.setSettlementDate(execCurr.getSettlementDate()); + reg.setValueDate(execCurr.getSettlementDate()); + reg.setSettlementCode(execCurr.getSettlementCode()); + reg.setTradingDate(exec.getTradingDate()); + reg.setClearingDate(LocalDate.now()); + reg.setPrice(exec.getPrice()); + reg.setCounterPartyId(exec.getCounterPartyId()); + reg.setGroupId(groupId()); + reg.setSessionId(exec.getSessionId()); + reg.setSessionType(sessionType()); + return reg; + } + + private Long groupId() { +// Market market = marketImdg.getFirstObjectBySQL("code = '" + exec.getMarket() + "'"); + return exec.getExchangeExecutionId(); + } + + //можно передать из стейджа + private String sessionType() { + Session session = sessionImdg.getSingleObjectByID(exec.getSessionId()); + return session.getSessionType(); + } + + private Company searchCompany() { + return companyImdg.getFirstObjectBySQL("id = " + exec.getCompanyId()); + } + + private TradingClearingRegistry searchTradingClearingRegistry() { + return tradingClearingRegistryImdg.getSingleObjectByID(exec.getTradingClearingRegistryId()); + } + + private static ISide getSide(ExecutionCommon exec) { + if (exec.type().equals(ExecutionType.ExecutionDeposit)) { + return ISide.parse(MoneyFlowSide.class, exec.getSide()); + } else if (exec.type().equals(ExecutionType.ExecutionFond)) { + return ISide.parse(Side.class, exec.getSide()); + } else if (exec.type().equals(ExecutionType.ExecutionCurrency)) { + return ISide.parse(Side.class, exec.getSide()); + } else { + throw new RuntimeException("Unknown Execution type: " + exec.type()); + } + } + + private String defineCapacityByAccountType(String accountType, Long moneyAccountId) { + String capacityByAccount = null; + if (AccountType.Clrn.equalsByKey(accountType)) { + ClearingAccount clearingAccount = clearingAccountImdg.getFirstObjectByFieldValues(Map.of("accountId", moneyAccountId)); + if (clearingAccount != null) { + capacityByAccount = clearingAccount.getClearingAccountType(); + } + } else if (AccountType.Info.equalsByKey(accountType)) { + capacityByAccount = RegistryCapacity.A.getKey(); + } + return capacityByAccount; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java index 5fe5c2e90..e53ed10eb 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java @@ -1,5 +1,12 @@ package ru.spcex.clearing.session.stage.impl; +import java.time.LocalDate; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiFunction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -7,6 +14,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionCurrency; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.execution.ExecutionFond; import ru.clearing.classes.statics.data.registry.Registry; @@ -16,7 +24,14 @@ import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.TaskType; import ru.spcex.platform.classes.base.interfaces.ExecutionType; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.ISide; +import ru.spcex.platform.enumeration.MoneyFlowSide; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.enumeration.Side; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -24,14 +39,6 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.utils.collection.Pair; -import java.time.LocalDate; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiFunction; - /** * LiabilitiesAndClaims */ @@ -197,6 +204,8 @@ public class RequirementsAndObligationCreation implements ISessionStage { return ((ExecutionDeposit) exec).getFirstLegSettlementDate(); } else if (exec.type().equals(ExecutionType.ExecutionFond)) { return ((ExecutionFond) exec).getSettlementDate(); + } else if (exec.type().equals(ExecutionType.ExecutionCurrency)) { + return ((ExecutionCurrency) exec).getSettlementDate(); } else { throw new RuntimeException("Unknown Execution type: " + exec.type()); } @@ -240,7 +249,7 @@ public class RequirementsAndObligationCreation implements ISessionStage { private static ISide getSide(ExecutionCommon exec) { if (exec.type().equals(ExecutionType.ExecutionDeposit)) { return ISide.parse(MoneyFlowSide.class, exec.getSide()); - } else if (exec.type().equals(ExecutionType.ExecutionFond)) { + } else if (exec.type().equals(ExecutionType.ExecutionFond) || exec.type().equals(ExecutionType.ExecutionCurrency)) { return ISide.parse(Side.class, exec.getSide()); } else { throw new RuntimeException("Unknown Execution type: " + exec.type()); @@ -251,7 +260,7 @@ public class RequirementsAndObligationCreation implements ISessionStage { return switch (executionType) { case ExecutionFond -> RegistryFondBuilder.builder(); case ExecutionDeposit -> RegistryDepoBuilder.builder(); - case ExecutionCurrency -> throw new IllegalStateException("ExecutionCurrency not supported"); // todo ExecutionCurrency по CLS-613 + case ExecutionCurrency -> RegistryCurrBuilder.builder(); }; } diff --git a/clearing-parent/db-scripts/src/main/resources/db/DDL.sql b/clearing-parent/db-scripts/src/main/resources/db/DDL.sql index 8b3528701..3adac2e71 100644 --- a/clearing-parent/db-scripts/src/main/resources/db/DDL.sql +++ b/clearing-parent/db-scripts/src/main/resources/db/DDL.sql @@ -4495,7 +4495,7 @@ GRANT ALL PRIVILEGES ON TABLE S_DF52 TO clearing; -- sDf53 - ДФ-53 Квитанция о получении информации о состоянии счета (блокировка/разблокировка/закрытие/открытие) DROP TABLE IF EXISTS S_DF53; -CREATE TABLE S_DF53(ID bigint PRIMARY KEY, ACC_NAME varchar(30), ACCOUNT varchar(25), DEAL varchar(4), DATE varchar(8), STATUS bigint, RESULT varchar(255), FILE_NAME varchar(255), GENERATION_TIME timestamp, GENERATION_ID bigint, IN_S_DF_ID bigint); +CREATE TABLE S_DF53(ID bigint PRIMARY KEY, ACC_NAME varchar(30), ACCOUNT varchar(25), DEAL varchar(4), DATE varchar(8), STATUS bigint, RESULT varchar(255), FILE_NAME varchar(255), GENERATION_TIME timestamp, GENERATION_ID bigint, IN_S_DF_ID bigint, ACC_TYPE varchar(3)); COMMENT ON TABLE S_DF53 IS 'ДФ-53 Квитанция о получении информации о состоянии счета (блокировка/разблокировка/закрытие/открытие)'; COMMENT ON COLUMN S_DF53.ID IS 'Идентификатор записи'; @@ -4520,6 +4520,8 @@ COMMENT ON COLUMN S_DF53.GENERATION_ID IS 'Идентификатор взаим COMMENT ON COLUMN S_DF53.IN_S_DF_ID IS 'Идентификатор соответствующей записи из таблицы-источника'; +COMMENT ON COLUMN S_DF53.ACC_TYPE IS 'Признак счета'; + GRANT ALL PRIVILEGES ON TABLE S_DF53 TO clearing; -- sDf54 - ДФ-54 Вывод свободных средств для инициаторов категории В с клирингового счета 30414 diff --git a/clearing-parent/db-scripts/src/main/resources/db/updateDDL_3.11.sql b/clearing-parent/db-scripts/src/main/resources/db/updateDDL_3.11.sql index c4ee35c3e..3b31eb64a 100644 --- a/clearing-parent/db-scripts/src/main/resources/db/updateDDL_3.11.sql +++ b/clearing-parent/db-scripts/src/main/resources/db/updateDDL_3.11.sql @@ -348,3 +348,6 @@ COMMENT ON COLUMN NOTIFICATION_HISTORY.SENDER_ID IS 'Идентификатор INSERT INTO DB_VERSION(ID, VERSION) values (1, '3.11') ON CONFLICT (ID) DO UPDATE SET VERSION = EXCLUDED.VERSION + +ALTER TABLE S_DF53 ADD COLUMN IF NOT EXISTS ACC_TYPE varchar(3); +COMMENT ON COLUMN S_DF53.ACC_TYPE IS 'Признак счета'; \ No newline at end of file diff --git a/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/services/converters/S_DF53_Converter.java b/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/services/converters/S_DF53_Converter.java index cdcf0d072..9fc78e207 100644 --- a/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/services/converters/S_DF53_Converter.java +++ b/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/services/converters/S_DF53_Converter.java @@ -1,13 +1,12 @@ package ru.spcex.clearing.dbf.exporter.services.converters; +import java.util.LinkedList; +import java.util.List; import com.linuxense.javadbf.DBFDataType; import com.linuxense.javadbf.DBFField; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.sdf.SDf53; -import java.util.LinkedList; -import java.util.List; - @Service public class S_DF53_Converter extends DFConverter { public S_DF53_Converter() { @@ -23,6 +22,7 @@ public class S_DF53_Converter extends DFConverter { values.add(typeMatch(entity.getDate())); values.add(typeMatch(entity.getStatus())); values.add(typeMatch(entity.getResult())); + values.add(typeMatch(entity.getAccType())); return values.toArray(Object[]::new); } @@ -35,6 +35,7 @@ public class S_DF53_Converter extends DFConverter { dbfFields.add(new DBFField("DATE", DBFDataType.CHARACTER, 8)); dbfFields.add(new DBFField("STATUS", DBFDataType.NUMERIC, 1,0)); dbfFields.add(new DBFField("RESULT", DBFDataType.CHARACTER, 10)); + dbfFields.add(new DBFField("ACC_TYPE", DBFDataType.CHARACTER, 3)); return dbfFields.toArray(DBFField[]::new); } diff --git a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/SDf53MapStore.java b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/SDf53MapStore.java index 6a5617434..22daa4091 100644 --- a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/SDf53MapStore.java +++ b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/SDf53MapStore.java @@ -1,5 +1,9 @@ package ru.spcex.clearing.imdg.object; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import ru.clearing.classes.statics.data.sdf.SDf53; @@ -8,11 +12,6 @@ import ru.spcex.clearing.imdg.base.TemplateMapStore; import ru.spcex.platform.utils.log.ExceptionUtils; import ru.spcex.platform.utils.time.TimeUtil; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.LocalDate; -import java.util.List; - @Component public class SDf53MapStore extends TemplateMapStore { @@ -33,7 +32,7 @@ public class SDf53MapStore extends TemplateMapStore { @Override public String[] getFields() { return new String[]{ - "ID", "ACC_NAME", "ACCOUNT", "DEAL", "DATE", "STATUS", "RESULT", "FILE_NAME", "GENERATION_TIME", "GENERATION_ID", "IN_S_DF_ID" + "ID", "ACC_NAME", "ACCOUNT", "DEAL", "DATE", "STATUS", "RESULT", "FILE_NAME", "GENERATION_TIME", "GENERATION_ID", "IN_S_DF_ID", "ACC_TYPE" }; } @@ -66,6 +65,7 @@ public class SDf53MapStore extends TemplateMapStore { object.setGenerationTime(getInstantFromTimestamp(resultSet, "GENERATION_TIME")); object.setGenerationId(resultSet.getObject("GENERATION_ID", Long.class)); object.setInSDfId(resultSet.getObject("IN_S_DF_ID", Long.class)); + object.setAccType(resultSet.getObject("ACC_TYPE", String.class)); return object; } @@ -82,7 +82,8 @@ public class SDf53MapStore extends TemplateMapStore { object.getFileName(), TimeUtil.toDateFromInstant(object.getGenerationTime()), object.getGenerationId(), - object.getInSDfId() + object.getInSDfId(), + object.getAccType() }; return args; } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java index 5d5d01c0c..da0050393 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java @@ -5,6 +5,7 @@ import ru.spcex.platform.utils.enumeration.IEnumKey; public enum SessionType implements IEnumKey { IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"), TRDT("TRDT"), MEDM("MEDM"), FINL("FINL"), XDEP("XDEP"), LIQU("LIQU"), + CURR("CURR") ; SessionType(String key) {