Merge branch 'dev' into spring-state-machine-template

# Conflicts:
#	clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java
This commit is contained in:
ialbert 2024-11-19 17:08:01 +03:00
commit 7b32872920
236 changed files with 19466 additions and 23834 deletions

View file

@ -26,6 +26,7 @@ preflight:
only:
- dev
- /^dev_.*$/
- new
resource_group: clearing-test
build:
@ -41,6 +42,7 @@ build:
only:
- dev
- /^dev_.*$/
- new
resource_group: clearing-test
test:
@ -52,7 +54,7 @@ test:
script:
- echo "Installing maven and python" && apk update && apk add maven python3
- echo "Copying jar files to clearing-all/bin" && cp -r /builds/mfd/clearing/z-distr/target/clearing/bin ./clr_test/clearing-all/bin
- echo "Copying DDL.sql to db directory" && cp /builds/mfd/clearing/z-distr/target/clearing/db/DDL.sql ./db
- echo "Copying DDL.sql to db directory" && cp /builds/mfd/clearing/z-distr/target/clearing/db/DDL.sql ./clr_test/db/
- python3 clr_test/run_test_docker_containers.py
artifacts:
expire_in: 1 day
@ -62,4 +64,5 @@ test:
only:
- dev
- /^dev_.*$/
- new
resource_group: clearing-test

View file

@ -5,7 +5,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -3,6 +3,7 @@ package ru.spcex.clearing.account.config.settings;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import ru.spcex.clearing.account.config.settings.elem.AppSettings;
import ru.spcex.clearing.platform.messaging.config.element.KafkaConsumerSettings;
import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings;
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
@ -14,6 +15,7 @@ public class AccountServiceSettings {
private HazelcastClientParams hazelcast;
private KafkaConsumerSettings kafkaConsumer;
private KafkaProducerSettings kafkaProducer;
private AppSettings app;
public HazelcastClientParams getHazelcast() {
return hazelcast;
@ -38,4 +40,12 @@ public class AccountServiceSettings {
public void setKafkaProducer(KafkaProducerSettings kafkaProducer) {
this.kafkaProducer = kafkaProducer;
}
public AppSettings getApp() {
return app;
}
public void setApp(AppSettings app) {
this.app = app;
}
}

View file

@ -0,0 +1,13 @@
package ru.spcex.clearing.account.config.settings.elem;
public class AppSettings {
private String registryUnit = "T";
public String getRegistryUnit() {
return registryUnit;
}
public void setRegistryUnit(String registryUnit) {
this.registryUnit = registryUnit;
}
}

View file

@ -4,6 +4,7 @@ import java.time.Instant;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer;
import org.slf4j.Logger;
@ -42,6 +43,8 @@ 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.ImdgTransaction;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.validation.Stored;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
@ -145,9 +148,29 @@ public class AccountService extends QueueConsumer implements InitializingBean {
account.setCompanyId(req.getCompanyId());
account.setAccount(req.getAccount());
if (AccountType.Info.equalsByKey(req.getAccountType())) {
Long infoSequenceId = informationAccountService.accountNextId(currencyCode, currencyCodeId);
Account anltAccount;
{
ImdgPredicateBuilder pb = accountMap.predicateBuilder();
ImdgPredicate andPredicate = pb.and(
pb.equals("accountType", AccountType.Anlt.getKey()),
pb.equals("currency", currency.getCurrencyCode())
);
Collection<Account> accountsAnlt = accountMap.getCollectionObjectsByPredicate(andPredicate);
if (accountsAnlt.isEmpty()) {
log.warn("Account with {} not exist.", andPredicate);
} else if (accountsAnlt.size() > 1) {
log.warn("Account for companyId 1 and accountType=ANLT contains multiply elements, use first");
}
anltAccount = accountsAnlt.iterator().next();
}
String accountValue = informationAccountService.generateInfoAccount(currencyCodeId, infoSequenceId);
String specialAnltAccId = "7000";
if (anltAccount != null && StringUtils.isNotEmpty(anltAccount.getAccount()) && anltAccount.getAccount().length() >= 4) {
specialAnltAccId = anltAccount.getAccount().substring(anltAccount.getAccount().length() - 4);
}
Long infoSequenceId = informationAccountService.accountNextId(currencyCode, currencyCodeId);
String accountValue = informationAccountService.generateInfoAccount(currencyCodeId, infoSequenceId, specialAnltAccId);
log.trace("New info-account SequenceId={} account={}", infoSequenceId, accountValue);
account.setAccount(accountValue);
}

View file

@ -793,7 +793,7 @@ public class ClearingAccountService extends QueueConsumer implements Initializin
}
if (returnTrigger) {
log.debug("Remove from waiting list accountId={} (list groupId={})", accountId, inWaitingLst.getGroupId());
waitingList.remove(inWaitingLst);
waitingList.remove(accountId);
}
if (returnTrigger)
return inWaitingLst;

View file

@ -119,9 +119,6 @@ public class InformationAccountService extends QueueConsumer implements Initiali
String currency = req.getCurrency() == null ? CurrencyCode.RUB.getKey() : req.getCurrency(); //userRequest.getRequestPayload().getCurrency();
Long newId = informationAccountImdg.nextIDSequenceFor();
Long infoSequenceId = accountNextId(currency, 810L);
String accountValue = generateInfoAccount(810L, infoSequenceId);
log.trace("New info-account id={}, sequenceId={}, account={}", newId, infoSequenceId, accountValue);
ImdgPredicateBuilder accountPredicateBuilder = accountImdg.predicateBuilder();
ImdgPredicate companyIdPredicate = accountPredicateBuilder.equals("companyId", 1L);
@ -215,15 +212,11 @@ public class InformationAccountService extends QueueConsumer implements Initiali
String currency = userRequest.getRequestPayload().getCurrency();
if (currency == null)
currency = CurrencyCode.RUB.getKey();
Long newId = informationAccountImdg.nextIDSequenceFor();
Long infoSequenceId = accountNextId(currency, 810L); // требуется последовательность n+1
String accountValue = generateInfoAccount(810L, infoSequenceId);
log.trace("New info-account id={}, sequenceId={}, account={}", newId, infoSequenceId, accountValue);
Long anltAccountId = null;
Account anltAccount;
{
ImdgPredicate andPredicate = pb.and(
pb.equals("companyId", 1L),
pb.equals("accountType", AccountType.Anlt.getKey()),
pb.equals("currency", currency)
);
@ -234,10 +227,20 @@ public class InformationAccountService extends QueueConsumer implements Initiali
} else if (accountsAnlt.size() > 1) {
log.warn("Account for companyId 1 and accountType=ANLT contains multiply elements, use first");
}
Account anltAccount = accountsAnlt.iterator().next();
anltAccount = accountsAnlt.iterator().next();
anltAccountId = anltAccount.getId();
}
String specialAnltAccId = "7000";
if (anltAccount != null && StringUtils.isNotEmpty(anltAccount.getAccount()) && anltAccount.getAccount().length() >= 4) {
specialAnltAccId = anltAccount.getAccount().substring(anltAccount.getAccount().length() - 4);
}
Long newId = informationAccountImdg.nextIDSequenceFor();
Long infoSequenceId = accountNextId(currency, 810L); // требуется последовательность n+1
String accountValue = generateInfoAccount(810L, infoSequenceId, specialAnltAccId);
log.trace("New info-account id={}, sequenceId={}, account={}", newId, infoSequenceId, accountValue);
Instant now = Instant.now();
Account account = new Account();
account.setAccount(accountValue);
@ -301,8 +304,8 @@ public class InformationAccountService extends QueueConsumer implements Initiali
kafkaSender.sendRequestToQueue(Consts.CREATE_NOTIFICATION_NCMP, request);
}
public String generateInfoAccount(Long currencyCodeId, Long id) {
return "%d%03d%08d%d".formatted(39911, currencyCodeId, id, 7000);
public String generateInfoAccount(Long currencyCodeId, Long id, String specialAnltAccId) {
return "%d%03d%08d%s".formatted(39911, currencyCodeId, id, specialAnltAccId);
}
public synchronized Long accountNextId(String currency) {
@ -339,7 +342,7 @@ public class InformationAccountService extends QueueConsumer implements Initiali
infoCounter = new AtomicLong(1);
log.debug("No account information on map. n={}", infoCounter.get());
} else {
Pattern accPattern = Pattern.compile("39911%s([0-9]{8})7000".formatted(idWithTrailingZero));
Pattern accPattern = Pattern.compile("39911%s([0-9]{8})\\d{4}".formatted(idWithTrailingZero));
int maxN = 1;
int parsedCount = 0;
String lastAccount = null; // for debug

View file

@ -27,6 +27,7 @@ import ru.clearing.classes.statics.data.company.CompanySymbols;
import ru.clearing.classes.statics.data.company.relation.Relation;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistryList;
import ru.spcex.clearing.account.config.settings.AccountServiceSettings;
import ru.spcex.clearing.account.errors.AccountError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
@ -93,6 +94,7 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini
private final IMessageResolver messageResolver;
private final Producer<String, Object> kafkaProducer;
private final KafkaSender kafkaSender;
private final AccountServiceSettings accountServiceSettings;
public TradingClearingRegistryService(Consumer<String, Object> kafkaQueue,
Producer<String, Object> kafkaProducer,
@ -107,7 +109,7 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini
@Qualifier("tradingClearingRegistryUpdateRequest")
Function<TradingClearingRegistryUpdateRequest, IValidator> tradingClearingRegistryUpdateRequestValidator,
@Qualifier("tradingClearingRegistryBlockRequest")
Function<CommonIdRequest, IValidator> tradingClearingRegistryBlockRequestValidator) {
Function<CommonIdRequest, IValidator> tradingClearingRegistryBlockRequestValidator, AccountServiceSettings accountServiceSettings) {
super(kafkaQueue, kafkaProducer);
this.kafkaProducer = kafkaProducer;
this.kafkaSender = kafkaSender;
@ -131,6 +133,7 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini
this.tradingClearingRegistryUpdateRequestValidator = tradingClearingRegistryUpdateRequestValidator;
this.tradingClearingRegistryBlockRequestValidator = tradingClearingRegistryBlockRequestValidator;
this.messageResolver = messageResolver;
this.accountServiceSettings = accountServiceSettings;
}
@Override
@ -444,7 +447,8 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini
code = "%4s".formatted(code).replace(' ', '0');
// code += registryPurpose.getKey(); // C / M / ...
code += "C";//пока ставим всегда С, возможно придется откатить
String trType = tradingRegistryType + "T"; // 2 символа
String registryUnit = accountServiceSettings.getApp() != null ? accountServiceSettings.getApp().getRegistryUnit() : "T";
String trType = tradingRegistryType + registryUnit; // 2 символа
code += trType;
String sId = "%5s".formatted(id).replace(' ', '0');
if (sId.length() > 5)

View file

@ -132,7 +132,7 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
clientCodeNewRequest.setCompanyId(company.getId());
clientCodeNewRequest.setCode(tkrAccount.getClientCode());
clientCodeNewRequest.setDepoAccountId(depoAccountId);
Account moneyAccount = accountByCurrency.get(CurrencyCode.RUB);
Account moneyAccount = accountByCurrency.get(CurrencyCode.RUB.getKey());
clientCodeNewRequest.setMoneyAccountId(moneyAccount.getId());
List<Long> foreignCurrencyList = accountByCurrency.entrySet()

View file

@ -16,4 +16,6 @@ account-service.kafka-producer.acks=all
account-service.kafka-producer.retries=0
account-service.kafka-producer.batch-size=16384
account-service.kafka-producer.linger-ms=1
account-service.kafka-producer.buffer-memory=33554432
account-service.kafka-producer.buffer-memory=33554432
account-service.app.registry-unit=L

View file

@ -11,7 +11,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>

View file

@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.nio.file.Files;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
@ -12,9 +14,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import ru.spcex.clearing.backendapi.meta.MetaServer;
import java.io.IOException;
import java.nio.file.Files;
@Configuration
public class MetaConfiguration {
@Value("file:${spring.config.location}/meta.json")

View file

@ -3,6 +3,7 @@ package ru.spcex.clearing.backendapi.config.element;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import ru.spcex.clearing.backendapi.security.element.JsConfigSettings;
import ru.spcex.clearing.backendapi.security.element.SecuritySettings;
import ru.spcex.clearing.platform.messaging.config.element.KafkaConsumerSettings;
import ru.spcex.clearing.platform.messaging.config.element.KafkaProducerSettings;
@ -17,6 +18,7 @@ public class BackendApiSettings {
private KafkaProducerSettings kafkaProducer;
private KafkaConsumerSettings kafkaConsumer;
private SecuritySettings security;
private JsConfigSettings jsConfig;
private String exampleSetting;
public HazelcastClientParams getHazelcast() {
@ -59,6 +61,14 @@ public class BackendApiSettings {
this.security = security;
}
public JsConfigSettings getJsConfig() {
return jsConfig;
}
public void setJsConfig(JsConfigSettings jsConfig) {
this.jsConfig = jsConfig;
}
public HazelcastClientParams getHazelcastSearch() {
return hazelcastSearch;
}

View file

@ -0,0 +1,39 @@
package ru.spcex.clearing.backendapi.controller.queue.misc;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import ru.spcex.clearing.backendapi.config.element.BackendApiSettings;
import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse;
import ru.spcex.clearing.backendapi.security.element.JsConfigSettings;
@Controller
@RequestMapping("/")
public class JsConfigController {
private final BackendApiSettings backendApiSettings;
public JsConfigController(BackendApiSettings backendApiSettings) {
this.backendApiSettings = backendApiSettings;
}
@ApiOperation(value = "get js config.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CommonGetAllResponse.class)})
@RequestMapping(path = "/spcexConfig.js", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> getJsConfig() {
Map<String, Object> result = new HashMap<>();
String title = new String(backendApiSettings.getJsConfig().getServerTitle().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
result.put(JsConfigSettings.SERVER_TITLE_PARAM_NAME, title);
result.put(JsConfigSettings.IS_CENTRAL_COUNTER_PARTY_PARAM_NAME, backendApiSettings.getJsConfig().getCentralCounterPartyEnable());
return result;
}
}

View file

@ -0,0 +1,74 @@
package ru.spcex.clearing.backendapi.controller.queue.securities;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import ru.clearing.classes.statics.data.security.Rates;
import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController;
import ru.spcex.clearing.backendapi.controller.request.cud.securities.RatesNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.securities.RatesUpdateAction;
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;
@Controller
@RequestMapping("/rates")
public class RatesController extends AbstractQueueController {
private final IStateLoader stateLoader;
@Autowired
public RatesController(IOperator operator, IStateLoader stateLoader) {
super(operator);
this.stateLoader = stateLoader;
}
@ApiOperation(value = "get all rates.")
@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_Rates, Rates.class);
CommonGetAllResponse response = new CommonGetAllResponse();
response.fromEntity(all);
return response;
}
@ApiOperation(value = "create rates.")
@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)
@ResponseBody
public CudResponse create(
@ApiParam(value = "Значения полей нового объекта.", required = true)
@RequestBody RatesNewAction ratesNewAction) throws ExecutionException, InterruptedException {
return processRequest(Consts.DESTINATION_RATES_NEW, ratesNewAction);
}
@ApiOperation(value = "update risk_parameter.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CudResponse update(
@ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234")
@PathVariable("id") Long id,
@ApiParam(value = "Новые значения полей объекта.", required = true)
@RequestBody RatesUpdateAction ratesUpdateAction) throws ExecutionException, InterruptedException {
ratesUpdateAction.setId(id);
return processRequest(Consts.DESTINATION_RATES_UPDATE, ratesUpdateAction);
}
}

View file

@ -0,0 +1,74 @@
package ru.spcex.clearing.backendapi.controller.queue.securities;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import ru.clearing.classes.statics.data.security.RiskParameter;
import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController;
import ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterNewAction;
import ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterUpdateAction;
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;
@Controller
@RequestMapping("/risk-parameter")
public class RiskParameterController extends AbstractQueueController {
private final IStateLoader stateLoader;
@Autowired
public RiskParameterController(IOperator operator, IStateLoader stateLoader) {
super(operator);
this.stateLoader = stateLoader;
}
@ApiOperation(value = "get all risk_parameter.")
@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_RiskParameter, RiskParameter.class);
CommonGetAllResponse response = new CommonGetAllResponse();
response.fromEntity(all);
return response;
}
@ApiOperation(value = "create risk_parameter.")
@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)
@ResponseBody
public CudResponse create(
@ApiParam(value = "Значения полей нового объекта.", required = true)
@RequestBody RiskParameterNewAction riskParameterNewAction) throws ExecutionException, InterruptedException {
return processRequest(Consts.DESTINATION_RISK_PARAMETER_NEW, riskParameterNewAction);
}
@ApiOperation(value = "update risk_parameter.")
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
@RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public CudResponse update(
@ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234")
@PathVariable("id") Long id,
@ApiParam(value = "Новые значения полей объекта.", required = true)
@RequestBody RiskParameterUpdateAction riskParameterUpdateAction) throws ExecutionException, InterruptedException {
riskParameterUpdateAction.setId(id);
return processRequest(Consts.DESTINATION_RISK_PARAMETER_UPDATE, riskParameterUpdateAction);
}
}

View file

@ -53,6 +53,51 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
@ApiModelProperty(value = "Код SWIFT посредника", example = "ABCDE")
@JsonProperty
private String intermediarySwiftCode;
@ApiModelProperty(value = "Наименование владельца счета", example = "ABCDE")
@JsonProperty
private String name;
@ApiModelProperty(value = "Адрес владельца счета", example = "ABCDE")
@JsonProperty
private String address;
@ApiModelProperty(value = "Место нахождения банка получателя средств", example = "ABCDE")
@JsonProperty
private String bankAddress;
@ApiModelProperty(value = "SWIFT банка получателя средств", example = "ABCDE")
@JsonProperty
private String bankSwiftCode;
@ApiModelProperty(value = "Номер счета банка получателя средств", example = "ABCDE")
@JsonProperty
private String bankAccount;
@ApiModelProperty(value = "Наименование банка-посредника 1", example = "ABCDE")
@JsonProperty
private String bankName1;
@ApiModelProperty(value = "Место нахождения банка-посредника 1", example = "ABCDE")
@JsonProperty
private String bankAddress1;
@ApiModelProperty(value = "Номер счета банка-посредника 1", example = "ABCDE")
@JsonProperty
private String bankAccount1;
@ApiModelProperty(value = "Наименование банка-посредника 2", example = "ABCDE")
@JsonProperty
private String bankName2;
@ApiModelProperty(value = "Место нахождения банка-посредника 2", example = "ABCDE")
@JsonProperty
private String bankAddress2;
@ApiModelProperty(value = "SWIFT банка-посредника 2", example = "ABCDE")
@JsonProperty
private String intermediarySwiftCode2;
@ApiModelProperty(value = "Номер счета банка-посредника 2", example = "ABCDE")
@JsonProperty
private String bankAccount2;
@ApiModelProperty(value = "Лицевой счет получателя", example = "ABCDE")
@JsonProperty
private String personalAccount;
@ApiModelProperty(value = "КБК", example = "ABCDE")
@JsonProperty
private String budgetClassificationCode;
@ApiModelProperty(value = "ОКТМО получателя средств", example = "ABCDE")
@JsonProperty
private String oktmo;
@Override
public BankAccountNewRequest toRequest() {
@ -69,6 +114,21 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
req.setCompanyId(this.companyId);
req.setSwiftCode(swiftCode);
req.setIntermediarySwiftCode(intermediarySwiftCode);
req.setName(name);
req.setAddress(address);
req.setBankAddress(bankAddress);
req.setBankSwiftCode(bankSwiftCode);
req.setBankAccount(bankAccount);
req.setBankName1(bankName1);
req.setBankAddress1(bankAddress1);
req.setBankAccount1(bankAccount1);
req.setBankName2(bankName2);
req.setBankAddress2(bankAddress2);
req.setIntermediarySwiftCode2(intermediarySwiftCode2);
req.setBankAccount2(bankAccount2);
req.setPersonalAccount(personalAccount);
req.setBudgetClassificationCode(budgetClassificationCode);
req.setOktmo(oktmo);
return req;
}
@ -173,4 +233,124 @@ public class BankAccountNewAction implements IAction<BankAccountNewRequest> {
public void setIntermediarySwiftCode(String intermediarySwiftCode) {
this.intermediarySwiftCode = intermediarySwiftCode;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBankAddress() {
return bankAddress;
}
public void setBankAddress(String bankAddress) {
this.bankAddress = bankAddress;
}
public String getBankSwiftCode() {
return bankSwiftCode;
}
public void setBankSwiftCode(String bankSwiftCode) {
this.bankSwiftCode = bankSwiftCode;
}
public String getBankAccount() {
return bankAccount;
}
public void setBankAccount(String bankAccount) {
this.bankAccount = bankAccount;
}
public String getBankName1() {
return bankName1;
}
public void setBankName1(String bankName1) {
this.bankName1 = bankName1;
}
public String getBankAddress1() {
return bankAddress1;
}
public void setBankAddress1(String bankAddress1) {
this.bankAddress1 = bankAddress1;
}
public String getBankAccount1() {
return bankAccount1;
}
public void setBankAccount1(String bankAccount1) {
this.bankAccount1 = bankAccount1;
}
public String getBankName2() {
return bankName2;
}
public void setBankName2(String bankName2) {
this.bankName2 = bankName2;
}
public String getBankAddress2() {
return bankAddress2;
}
public void setBankAddress2(String bankAddress2) {
this.bankAddress2 = bankAddress2;
}
public String getIntermediarySwiftCode2() {
return intermediarySwiftCode2;
}
public void setIntermediarySwiftCode2(String intermediarySwiftCode2) {
this.intermediarySwiftCode2 = intermediarySwiftCode2;
}
public String getBankAccount2() {
return bankAccount2;
}
public void setBankAccount2(String bankAccount2) {
this.bankAccount2 = bankAccount2;
}
public String getPersonalAccount() {
return personalAccount;
}
public void setPersonalAccount(String personalAccount) {
this.personalAccount = personalAccount;
}
public String getBudgetClassificationCode() {
return budgetClassificationCode;
}
public void setBudgetClassificationCode(String budgetClassificationCode) {
this.budgetClassificationCode = budgetClassificationCode;
}
public String getOktmo() {
return oktmo;
}
public void setOktmo(String oktmo) {
this.oktmo = oktmo;
}
}

View file

@ -48,6 +48,52 @@ public class BankAccountUpdateAction implements IAction<BankAccountUpdateRequest
@ApiModelProperty(value = "Номер счета", example = "11111222223333344444")
private String account;
@ApiModelProperty(value = "Наименование владельца счета", example = "ABCDE")
@JsonProperty
private String name;
@ApiModelProperty(value = "Адрес владельца счета", example = "ABCDE")
@JsonProperty
private String address;
@ApiModelProperty(value = "Место нахождения банка получателя средств", example = "ABCDE")
@JsonProperty
private String bankAddress;
@ApiModelProperty(value = "SWIFT банка получателя средств", example = "ABCDE")
@JsonProperty
private String bankSwiftCode;
@ApiModelProperty(value = "Номер счета банка получателя средств", example = "ABCDE")
@JsonProperty
private String bankAccount;
@ApiModelProperty(value = "Наименование банка-посредника 1", example = "ABCDE")
@JsonProperty
private String bankName1;
@ApiModelProperty(value = "Место нахождения банка-посредника 1", example = "ABCDE")
@JsonProperty
private String bankAddress1;
@ApiModelProperty(value = "Номер счета банка-посредника 1", example = "ABCDE")
@JsonProperty
private String bankAccount1;
@ApiModelProperty(value = "Наименование банка-посредника 2", example = "ABCDE")
@JsonProperty
private String bankName2;
@ApiModelProperty(value = "Место нахождения банка-посредника 2", example = "ABCDE")
@JsonProperty
private String bankAddress2;
@ApiModelProperty(value = "SWIFT банка-посредника 2", example = "ABCDE")
@JsonProperty
private String intermediarySwiftCode2;
@ApiModelProperty(value = "Номер счета банка-посредника 2", example = "ABCDE")
@JsonProperty
private String bankAccount2;
@ApiModelProperty(value = "Лицевой счет получателя", example = "ABCDE")
@JsonProperty
private String personalAccount;
@ApiModelProperty(value = "КБК", example = "ABCDE")
@JsonProperty
private String budgetClassificationCode;
@ApiModelProperty(value = "ОКТМО получателя средств", example = "ABCDE")
@JsonProperty
private String oktmo;
@Override
public BankAccountUpdateRequest toRequest() {
var req = new BankAccountUpdateRequest();
@ -63,6 +109,21 @@ public class BankAccountUpdateAction implements IAction<BankAccountUpdateRequest
req.setAccount(this.account);
req.setSwiftCode(swiftCode);
req.setIntermediarySwiftCode(intermediarySwiftCode);
req.setName(name);
req.setAddress(address);
req.setBankAddress(bankAddress);
req.setBankSwiftCode(bankSwiftCode);
req.setBankAccount(bankAccount);
req.setBankName1(bankName1);
req.setBankAddress1(bankAddress1);
req.setBankAccount1(bankAccount1);
req.setBankName2(bankName2);
req.setBankAddress2(bankAddress2);
req.setIntermediarySwiftCode2(intermediarySwiftCode2);
req.setBankAccount2(bankAccount2);
req.setPersonalAccount(personalAccount);
req.setBudgetClassificationCode(budgetClassificationCode);
req.setOktmo(oktmo);
return req;
}
@ -167,4 +228,124 @@ public class BankAccountUpdateAction implements IAction<BankAccountUpdateRequest
public void setIntermediarySwiftCode(String intermediarySwiftCode) {
this.intermediarySwiftCode = intermediarySwiftCode;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBankAddress() {
return bankAddress;
}
public void setBankAddress(String bankAddress) {
this.bankAddress = bankAddress;
}
public String getBankSwiftCode() {
return bankSwiftCode;
}
public void setBankSwiftCode(String bankSwiftCode) {
this.bankSwiftCode = bankSwiftCode;
}
public String getBankAccount() {
return bankAccount;
}
public void setBankAccount(String bankAccount) {
this.bankAccount = bankAccount;
}
public String getBankName1() {
return bankName1;
}
public void setBankName1(String bankName1) {
this.bankName1 = bankName1;
}
public String getBankAddress1() {
return bankAddress1;
}
public void setBankAddress1(String bankAddress1) {
this.bankAddress1 = bankAddress1;
}
public String getBankAccount1() {
return bankAccount1;
}
public void setBankAccount1(String bankAccount1) {
this.bankAccount1 = bankAccount1;
}
public String getBankName2() {
return bankName2;
}
public void setBankName2(String bankName2) {
this.bankName2 = bankName2;
}
public String getBankAddress2() {
return bankAddress2;
}
public void setBankAddress2(String bankAddress2) {
this.bankAddress2 = bankAddress2;
}
public String getIntermediarySwiftCode2() {
return intermediarySwiftCode2;
}
public void setIntermediarySwiftCode2(String intermediarySwiftCode2) {
this.intermediarySwiftCode2 = intermediarySwiftCode2;
}
public String getBankAccount2() {
return bankAccount2;
}
public void setBankAccount2(String bankAccount2) {
this.bankAccount2 = bankAccount2;
}
public String getPersonalAccount() {
return personalAccount;
}
public void setPersonalAccount(String personalAccount) {
this.personalAccount = personalAccount;
}
public String getBudgetClassificationCode() {
return budgetClassificationCode;
}
public void setBudgetClassificationCode(String budgetClassificationCode) {
this.budgetClassificationCode = budgetClassificationCode;
}
public String getOktmo() {
return oktmo;
}
public void setOktmo(String oktmo) {
this.oktmo = oktmo;
}
}

View file

@ -0,0 +1,79 @@
package ru.spcex.clearing.backendapi.controller.request.cud.securities;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.time.LocalDate;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.security.RatesNewRequest;
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer;
import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer;
public class RatesNewAction implements IAction<RatesNewRequest> {
@ApiModelProperty(value = "Курс.", example = "1234")
@JsonProperty
private BigDecimal value;
@ApiModelProperty(value = "Дата.", example = "1234")
@JsonSerialize(using = LocalDateSerializer.class)
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonProperty
private LocalDate valueDate;
@ApiModelProperty(value = "Валюта.", example = "1234")
@JsonProperty
private Long currencyId;
@ApiModelProperty(value = "Статус.", example = "1234")
@JsonProperty
private String status;
@Override
public RatesNewRequest toRequest() {
RatesNewRequest request = new RatesNewRequest();
request.setValue(this.value);
request.setValueDate(this.valueDate);
request.setCurrencyId(this.currencyId);
request.setStatus(this.status);
return request;
}
@ApiModelProperty(hidden = true)
@Override
public ActionType getActionType() {
return ActionType.NEW;
}
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public LocalDate getValueDate() {
return valueDate;
}
public void setValueDate(LocalDate valueDate) {
this.valueDate = valueDate;
}
public Long getCurrencyId() {
return currencyId;
}
public void setCurrencyId(Long currencyPairId) {
this.currencyId = currencyPairId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

View file

@ -0,0 +1,60 @@
package ru.spcex.clearing.backendapi.controller.request.cud.securities;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.security.RatesUpdateRequest;
public class RatesUpdateAction implements IAction<RatesUpdateRequest> {
@ApiModelProperty(hidden = true)
@JsonProperty
public Long id;
@ApiModelProperty(value = "Курс.", example = "1234")
@JsonProperty
private BigDecimal value;
@ApiModelProperty(value = "Статус.", example = "1234")
@JsonProperty
private String status;
@Override
public RatesUpdateRequest toRequest() {
RatesUpdateRequest request = new RatesUpdateRequest();
request.setId(this.id);
request.setValue(this.value);
request.setStatus(this.status);
return request;
}
@ApiModelProperty(hidden = true)
@Override
public ActionType getActionType() {
return ActionType.NEW;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

View file

@ -0,0 +1,72 @@
package ru.spcex.clearing.backendapi.controller.request.cud.securities;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.security.RiskParameterNewRequest;
public class RiskParameterNewAction implements IAction<RiskParameterNewRequest> {
@ApiModelProperty(value = "Курс.", example = "1234")
@JsonProperty
private BigDecimal value;
@ApiModelProperty(value = "Код расчёта.", example = "1234")
@JsonProperty
private String settlementType;
@ApiModelProperty(value = "Валютная пара.", example = "1234")
@JsonProperty
private Long currencyPairId;
@ApiModelProperty(value = "Статус.", example = "1234")
@JsonProperty
private String status;
@Override
public RiskParameterNewRequest toRequest() {
RiskParameterNewRequest request = new RiskParameterNewRequest();
request.setValue(this.value);
request.setSettlementType(this.settlementType);
request.setCurrencyPairId(this.currencyPairId);
request.setStatus(this.status);
return request;
}
@ApiModelProperty(hidden = true)
@Override
public ActionType getActionType() {
return ActionType.NEW;
}
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public String getSettlementType() {
return settlementType;
}
public void setSettlementType(String settlementType) {
this.settlementType = settlementType;
}
public Long getCurrencyPairId() {
return currencyPairId;
}
public void setCurrencyPairId(Long currencyPairId) {
this.currencyPairId = currencyPairId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

View file

@ -0,0 +1,60 @@
package ru.spcex.clearing.backendapi.controller.request.cud.securities;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.security.RiskParameterUpdateRequest;
public class RiskParameterUpdateAction implements IAction<RiskParameterUpdateRequest> {
@ApiModelProperty(hidden = true)
@JsonProperty
public Long id;
@ApiModelProperty(value = "Курс.", example = "1234")
@JsonProperty
private BigDecimal value;
@ApiModelProperty(value = "Статус.", example = "1234")
@JsonProperty
private String status;
@Override
public RiskParameterUpdateRequest toRequest() {
RiskParameterUpdateRequest request = new RiskParameterUpdateRequest();
request.setId(this.id);
request.setValue(this.value);
request.setStatus(this.status);
return request;
}
@ApiModelProperty(hidden = true)
@Override
public ActionType getActionType() {
return ActionType.NEW;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

View file

@ -65,6 +65,7 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
.antMatchers("/login").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/backend-api-login/**").permitAll()
.antMatchers("/spcex.config.js").permitAll()
.anyRequest();
if (securityDisabled) {
anyReq.permitAll();

View file

@ -0,0 +1,24 @@
package ru.spcex.clearing.backendapi.security.element;
public class JsConfigSettings {
public final static String SERVER_TITLE_PARAM_NAME = "serverTitle";
public final static String IS_CENTRAL_COUNTER_PARTY_PARAM_NAME = "isCentralCounterparty";
private String serverTitle;
private Boolean centralCounterPartyEnable;
public String getServerTitle() {
return serverTitle;
}
public void setServerTitle(String serverTitle) {
this.serverTitle = serverTitle;
}
public Boolean getCentralCounterPartyEnable() {
return centralCounterPartyEnable;
}
public void setCentralCounterPartyEnable(Boolean centralCounterPartyEnable) {
this.centralCounterPartyEnable = centralCounterPartyEnable;
}
}

View file

@ -26,6 +26,9 @@ backend-api.kafka-consumer.auto-offset-reset=latest
backend-api.kafka-consumer.linger-ms=1
backend-api.kafka-consumer.buffer-memory=33554432
backend-api.security.authorization-disabled=false
backend-api.js-config.server-title=?????? 183
backend-api.js-config.central-counter-party-enable=true
#access logs, sample
#server.tomcat.accesslog.directory=logs
#server.tomcat.accesslog.enabled=true

View file

@ -1,6 +1,6 @@
{
"version": "3.14.105.103",
"version": "3.15.208.113",
"enums": {
@ -6037,6 +6037,17 @@
"fields": []
}
,
{"method":"post",
"destination": "GREC",
"group": "Формирование отчетности",
"name": "Формирование отчетности ЦК",
"fields": []
}
,
{"method":"post",
"destination": "FDFF",
@ -10362,6 +10373,182 @@
]
}
,
"riskParameter": {
"name": "Параметры риска",
"destination": "risk-parameter",
"class": "ru.clearing.classes.statics.data.security.RiskParameter",
"table": "risk-parameter",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"visible": true
}
,
{"code": "currencyPair",
"name": "Код валютной пары","shortname": "Код валютной пары","type": 2,"length": 12
}
,
{"code": "currencyPairId",
"name": "Идентификатор валютной пары","shortname": "Валютная пара","type": 1
}
,
{"code": "settlementType",
"name": "Код расчета","shortname": "Код расчета","type": 2,"length": 4
}
,
{"code": "value",
"name": "Ставка","shortname": "Ставка","type": 10
}
,
{"code": "workflowStatus",
"name": "Статус","shortname": "Статус","type": 2,"length": 4,"link": "workflowStatus"
}
]
,"actions":[
{"method":"post",
"name": "Добавление параметров риска",
"confirmation": "value,settlementType,currencyPairId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterNewAction",
"fields": [
{"code": "currencyPairId",
"name": "Идентификатор валютной пары","shortname": "Валютная пара","type": 1,"link": "currencyPair","linkCode": "code","linkKeyCode": "id"
}
,
{"code": "settlementType",
"name": "Код расчёта","shortname": "Код расчёта","type": 12,"link": "currencySettlementType","linkCode": "code"
}
,
{"code": "value",
"name": "Ставка","shortname": "Ставка","type": 10
}
,
{"code": "status",
"name": "Статус","shortname": "Статус","type": 2,"length": 4,"link": "workflowStatus"
}
]
}
,
{"method":"put",
"name": "Изменение параметров риска",
"confirmation": "value,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "riskParameter","linkCode": "id","required": true
}
,
{"code": "value",
"name": "Ставка","shortname": "Ставка","type": 10
}
,
{"code": "status",
"name": "Статус","shortname": "Статус","type": 2,"length": 4,"link": "workflowStatus"
}
]
}
]
}
,
"rates": {
"name": "Расчетные курсы",
"destination": "rates",
"class": "ru.clearing.classes.statics.data.security.Rates",
"table": "rates",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"visible": true
}
,
{"code": "currencyId",
"name": "Идентификатор валюты","shortname": "Валюта","type": 1
}
,
{"code": "currency",
"name": "Код валюты","shortname": "Код валюты","type": 2,"length": 4
}
,
{"code": "valueDate",
"name": "Дата, на которую расчетный курс","shortname": "Дата","type": 6
}
,
{"code": "value",
"name": "Расчетный курс","shortname": "Расчетный курс","type": 10
}
,
{"code": "workflowStatus",
"name": "Статус","shortname": "Статус","type": 2,"length": 4,"link": "workflowStatus"
}
]
,"actions":[
{"method":"post",
"name": "Добавление расчетного курса",
"confirmation": "value,valueDate,currencyId,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.RatesNewAction",
"fields": [
{"code": "currencyId",
"name": "Идентификатор валюты","shortname": "Валюта","type": 1,"link": "currencyCode","linkCode": "code","linkKeyCode": "id"
}
,
{"code": "valueDate",
"name": "Дата, на которую расчетный курс","shortname": "Дата","type": 6
}
,
{"code": "value",
"name": "Расчетный курс","shortname": "Расчетный курс","type": 10
}
,
{"code": "status",
"name": "Статус","shortname": "Статус","type": 2,"length": 4,"link": "workflowStatus"
}
]
}
,
{"method":"put",
"name": "Изменение расчетного курса",
"confirmation": "value,status",
"class": "ru.spcex.clearing.backendapi.controller.request.cud.securities.RatesUpdateAction",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","link": "rates","linkCode": "id","required": true
}
,
{"code": "value",
"name": "Расчетный курс","shortname": "Расчетный курс","type": 10
}
,
{"code": "status",
"name": "Статус","shortname": "Статус","type": 2,"length": 4,"link": "workflowStatus"
}
]
}
]
}
}

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--?xml-stylesheet type="text/xsl" href="\..\corp-reports\src\data\meta\meta.server.xslt"?-->
<meta version="3.14.105.103">
<meta version="3.15.208.113">
<!-- _xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" _xsi:noNamespaceSchemaLocation="file:///E:/d/projects/meta/from/meta.xsd" -->
<!--Здесь словари-->
<enums>
@ -1398,6 +1398,8 @@
</post>
<post destination="GREF" group="Формирование отчетности" name="Формирование итоговой отчетности">
</post>
<post destination="GREC" group="Формирование отчетности" name="Формирование отчетности ЦК">
</post>
<post destination="FDFF" group="Обмен с расчетной организацией" name="Формирование ДФ-05 с кодом 9 (финальный)">
</post>
<post destination="CHDF" group="Общее" name="Проверка наличия пары ДФ-01/ДФ-57 и ДФ-08/ДФ-21">
@ -2397,6 +2399,48 @@
<code name="Код рынка" shortname="Код рынка" type="2" length="12"/>
<section name="Секция" shortname="Секция" type="12"/>
</blacklistMarket>
<riskParameter name="Параметры риска" destination="risk-parameter" class="ru.clearing.classes.statics.data.security.RiskParameter" table="risk-parameter">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true" visible="true"/>
<currencyPair name="Код валютной пары" shortname="Код валютной пары" type="2" length="12"/>
<currencyPairId name="Идентификатор валютной пары" shortname="Валютная пара" type="1"/>
<settlementType name="Код расчета" shortname="Код расчета" type="2" length="4"/>
<value name="Ставка" shortname="Ставка" type="10"/>
<workflowStatus name="Статус" shortname="Статус" type="2" length="4" link="workflowStatus"/>
<actions>
<post name="Добавление параметров риска" confirmation="value,settlementType,currencyPairId,status" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterNewAction">
<currencyPairId name="Идентификатор валютной пары" shortname="Валютная пара" type="1" link="currencyPair" linkCode="code" linkKeyCode="id"/>
<settlementType name="Код расчёта" shortname="Код расчёта" type="12" link="currencySettlementType" linkCode="code"/>
<value name="Ставка" shortname="Ставка" type="10"/>
<status name="Статус" shortname="Статус" type="2" length="4" link="workflowStatus"/>
</post>
<put name="Изменение параметров риска" confirmation="value,status" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.RiskParameterUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="riskParameter" linkCode="id" required="true"/>
<value name="Ставка" shortname="Ставка" type="10"/>
<status name="Статус" shortname="Статус" type="2" length="4" link="workflowStatus"/>
</put>
</actions>
</riskParameter>
<rates name="Расчетные курсы" destination="rates" class="ru.clearing.classes.statics.data.security.Rates" table="rates">
<id type="1" name="Идентификатор записи" shortname="ID" searchable="true" sortable="true" visible="true"/>
<currencyId name="Идентификатор валюты" shortname="Валюта" type="1"/>
<currency name="Код валюты" shortname="Код валюты" type="2" length="4"/>
<valueDate name="Дата, на которую расчетный курс" shortname="Дата" type="6"/>
<value name="Расчетный курс" shortname="Расчетный курс" type="10"/>
<workflowStatus name="Статус" shortname="Статус" type="2" length="4" link="workflowStatus"/>
<actions>
<post name="Добавление расчетного курса" confirmation="value,valueDate,currencyId,status" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.RatesNewAction">
<currencyId name="Идентификатор валюты" shortname="Валюта" type="1" link="currencyCode" linkCode="code" linkKeyCode="id"/>
<valueDate name="Дата, на которую расчетный курс" shortname="Дата" type="6"/>
<value name="Расчетный курс" shortname="Расчетный курс" type="10"/>
<status name="Статус" shortname="Статус" type="2" length="4" link="workflowStatus"/>
</post>
<put name="Изменение расчетного курса" confirmation="value,status" class="ru.spcex.clearing.backendapi.controller.request.cud.securities.RatesUpdateAction">
<id type="1" name="Идентификатор записи" shortname="ID" link="rates" linkCode="id" required="true"/>
<value name="Расчетный курс" shortname="Расчетный курс" type="10"/>
<status name="Статус" shortname="Статус" type="2" length="4" link="workflowStatus"/>
</put>
</actions>
</rates>
</objects>
<views>
<AccountUnion>

View file

@ -1,6 +1,6 @@
{
"version": "3.12.8.101",
"version": "3.14.105.104",
"enums": {
@ -1523,7 +1523,7 @@
"destination": "db-versions",
"class": "",
"class": "ru.clearing.classes.statics.data.misc.DbVersion",
"table": "db_version",
@ -1535,6 +1535,10 @@
{"code": "version",
"type": 2,"length": 50,"name": "Версия базы данных, привязанная к релизу","shortname": "Версия БД","searchable": true,"sortable": true,"visible": true
}
,
{"code": "dictionaryVersion",
"type": 2,"length": 100,"name": "Версия справочника","shortname": "Версия справочника","searchable": true,"sortable": true,"visible": true
}
]
}
@ -4984,6 +4988,66 @@
{"code": "intermediarySwiftCode",
"type": 2,"length": 255,"name": "Код SWIFT посредника","shortname": "SWIFT посредника","searchable": true,"sortable": true,"visible": true
}
,
{"code": "name",
"type": 2,"length": 255,"name": "Наименование владельца счета","shortname": "Владелец счета","searchable": true,"sortable": true,"visible": true
}
,
{"code": "address",
"type": 2,"length": 255,"name": "Адрес владельца счета","shortname": "Адрес владельца","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress",
"type": 2,"length": 255,"name": "Место нахождения банка получателя средств","shortname": "Место нахождение банка","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankSwiftCode",
"type": 2,"length": 12,"name": "SWIFT банка получателя средств","shortname": "SWIFT банка","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount",
"type": 2,"length": 35,"name": "Номер счета банка получателя средств","shortname": "Номер счёта получателя","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankName1",
"type": 2,"length": 255,"name": "Наименование банка-посредника 1","shortname": "Банк посредник 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress1",
"type": 2,"length": 255,"name": "Место нахождения банка-посредника 1","shortname": "Место нахождения банка-посредника 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount1",
"type": 2,"length": 35,"name": "Номер счета банка-посредника 1","shortname": "Счет банка-посредника 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankName2",
"type": 2,"length": 255,"name": "Наименование банка-посредника 2","shortname": "Банк посредник 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress2",
"type": 2,"length": 255,"name": "Место нахождения банка-посредника 2","shortname": "Место нахождения банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "intermediarySwiftCode2",
"type": 2,"length": 12,"name": "SWIFT банка-посредника 2","shortname": "Счет банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount2",
"type": 2,"length": 35,"name": "Номер счета банка-посредника 2","shortname": "Счет банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "personalAccount",
"type": 2,"length": 20,"name": "Лицевой счет получателя","shortname": "Счет получателя","searchable": true,"sortable": true,"visible": true
}
,
{"code": "budgetClassificationCode",
"type": 2,"length": 20,"name": "КБК","shortname": "КБК","searchable": true,"sortable": true,"visible": true
}
,
{"code": "oktmo",
"type": 2,"length": 20,"name": "ОКТМО получателя средств","shortname": "ОКТМО","searchable": true,"sortable": true,"visible": true
}
]
,"actions":[
{"method":"post",
@ -5042,6 +5106,66 @@
{"code": "intermediarySwiftCode",
"type": 2,"length": 255,"name": "Код SWIFT посредника","shortname": "SWIFT посредника","searchable": true,"sortable": true,"visible": true
}
,
{"code": "name",
"type": 2,"length": 255,"name": "Наименование владельца счета","shortname": "Владелец счета","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "address",
"type": 2,"length": 255,"name": "Адрес владельца счета","shortname": "Адрес владельца","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankAddress",
"type": 2,"length": 255,"name": "Место нахождения банка получателя средств","shortname": "Место нахождение банка","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankSwiftCode",
"type": 2,"length": 12,"name": "SWIFT банка получателя средств","shortname": "SWIFT банка","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankAccount",
"type": 2,"length": 35,"name": "Номер счета банка получателя средств","shortname": "Номер счёта получателя","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankName1",
"type": 2,"length": 255,"name": "Наименование банка-посредника 1","shortname": "Банк посредник 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress1",
"type": 2,"length": 255,"name": "Место нахождения банка-посредника 1","shortname": "Место нахождения банка-посредника 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount1",
"type": 2,"length": 35,"name": "Номер счета банка-посредника 1","shortname": "Счет банка-посредника 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankName2",
"type": 2,"length": 255,"name": "Наименование банка-посредника 2","shortname": "Банк посредник 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress2",
"type": 2,"length": 255,"name": "Место нахождения банка-посредника 2","shortname": "Место нахождения банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "intermediarySwiftCode2",
"type": 2,"length": 12,"name": "SWIFT банка-посредника 2","shortname": "Счет банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount2",
"type": 2,"length": 35,"name": "Номер счета банка-посредника 2","shortname": "Счет банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "personalAccount",
"type": 2,"length": 20,"name": "Лицевой счет получателя","shortname": "Счет получателя","searchable": true,"sortable": true,"visible": true
}
,
{"code": "budgetClassificationCode",
"type": 2,"length": 20,"name": "КБК","shortname": "КБК","searchable": true,"sortable": true,"visible": true
}
,
{"code": "oktmo",
"type": 2,"length": 20,"name": "ОКТМО получателя средств","shortname": "ОКТМО","searchable": true,"sortable": true,"visible": true
}
]
}
,
@ -5101,6 +5225,66 @@
{"code": "intermediarySwiftCode",
"type": 2,"length": 255,"name": "Код SWIFT посредника","shortname": "SWIFT посредника","searchable": true,"sortable": true,"visible": true
}
,
{"code": "name",
"type": 2,"length": 255,"name": "Наименование владельца счета","shortname": "Владелец счета","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "address",
"type": 2,"length": 255,"name": "Адрес владельца счета","shortname": "Адрес владельца","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankAddress",
"type": 2,"length": 255,"name": "Место нахождения банка получателя средств","shortname": "Место нахождение банка","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankSwiftCode",
"type": 2,"length": 12,"name": "SWIFT банка получателя средств","shortname": "SWIFT банка","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankAccount",
"type": 2,"length": 35,"name": "Номер счета банка получателя средств","shortname": "Номер счёта получателя","searchable": true,"sortable": true,"visible": true,"required": true
}
,
{"code": "bankName1",
"type": 2,"length": 255,"name": "Наименование банка-посредника 1","shortname": "Банк посредник 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress1",
"type": 2,"length": 255,"name": "Место нахождения банка-посредника 1","shortname": "Место нахождения банка-посредника 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount1",
"type": 2,"length": 35,"name": "Номер счета банка-посредника 1","shortname": "Счет банка-посредника 1","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankName2",
"type": 2,"length": 255,"name": "Наименование банка-посредника 2","shortname": "Банк посредник 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAddress2",
"type": 2,"length": 255,"name": "Место нахождения банка-посредника 2","shortname": "Место нахождения банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "intermediarySwiftCode2",
"type": 2,"length": 12,"name": "SWIFT банка-посредника 2","shortname": "Счет банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "bankAccount2",
"type": 2,"length": 35,"name": "Номер счета банка-посредника 2","shortname": "Счет банка-посредника 2","searchable": true,"sortable": true,"visible": true
}
,
{"code": "personalAccount",
"type": 2,"length": 20,"name": "Лицевой счет получателя","shortname": "Счет получателя","searchable": true,"sortable": true,"visible": true
}
,
{"code": "budgetClassificationCode",
"type": 2,"length": 20,"name": "КБК","shortname": "КБК","searchable": true,"sortable": true,"visible": true
}
,
{"code": "oktmo",
"type": 2,"length": 20,"name": "ОКТМО получателя средств","shortname": "ОКТМО","searchable": true,"sortable": true,"visible": true
}
]
}
,
@ -10332,6 +10516,32 @@
]
}
,
"blacklistMarket": {
"name": "blacklist площадок",
"destination": "blacklist-market",
"class": "ru.clearing.classes.statics.data.misc.BlacklistMarket",
"table": "blacklist_market",
"fields": [
{"code": "id",
"type": 1,"name": "Идентификатор записи","shortname": "ID","searchable": true,"sortable": true,"visible": true
}
,
{"code": "code",
"name": "Код рынка","shortname": "Код рынка","type": 2,"length": 12
}
,
{"code": "section",
"name": "Секция","shortname": "Секция","type": 12
}
]
}
}

View file

@ -5,7 +5,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -12,7 +12,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<properties>

View file

@ -26,6 +26,21 @@ public class BankAccount extends SpcexObjectBase {
private String account;
private Long companyId;
private String intermediarySwiftCode;
private String name;
private String address;
private String bankAddress;
private String bankSwiftCode;
private String bankAccount;
private String bankName1;
private String bankAddress1;
private String bankAccount1;
private String bankName2;
private String bankAddress2;
private String intermediarySwiftCode2;
private String bankAccount2;
private String personalAccount;
private String budgetClassificationCode;
private String oktmo;
public Long getAccountId() {
return accountId;
@ -143,7 +158,128 @@ public class BankAccount extends SpcexObjectBase {
return intermediarySwiftCode;
}
public void setIntermediarySwiftCode(String intermediarySwiftCode) {
this.intermediarySwiftCode = intermediarySwiftCode;
public void setIntermediarySwiftCode(String value) {
this.intermediarySwiftCode = value;
}
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public String getAddress() {
return address;
}
public void setAddress(String value) {
this.address = value;
}
public String getBankAddress() {
return bankAddress;
}
public void setBankAddress(String value) {
this.bankAddress = value;
}
public String getBankSwiftCode() {
return bankSwiftCode;
}
public void setBankSwiftCode(String value) {
this.bankSwiftCode = value;
}
public String getBankAccount() {
return bankAccount;
}
public void setBankAccount(String value) {
this.bankAccount = value;
}
public String getBankName1() {
return bankName1;
}
public void setBankName1(String value) {
this.bankName1 = value;
}
public String getBankAddress1() {
return bankAddress1;
}
public void setBankAddress1(String value) {
this.bankAddress1 = value;
}
public String getBankAccount1() {
return bankAccount1;
}
public void setBankAccount1(String value) {
this.bankAccount1 = value;
}
public String getBankName2() {
return bankName2;
}
public void setBankName2(String value) {
this.bankName2 = value;
}
public String getBankAddress2() {
return bankAddress2;
}
public void setBankAddress2(String value) {
this.bankAddress2 = value;
}
public String getIntermediarySwiftCode2() {
return intermediarySwiftCode2;
}
public void setIntermediarySwiftCode2(String value) {
this.intermediarySwiftCode2 = value;
}
public String getBankAccount2() {
return bankAccount2;
}
public void setBankAccount2(String value) {
this.bankAccount2 = value;
}
public String getPersonalAccount() {
return personalAccount;
}
public void setPersonalAccount(String value) {
this.personalAccount = value;
}
public String getBudgetClassificationCode() {
return budgetClassificationCode;
}
public void setBudgetClassificationCode(String value) {
this.budgetClassificationCode = value;
}
public String getOktmo() {
return oktmo;
}
public void setOktmo(String value) {
this.oktmo = value;
}
}

View file

@ -60,6 +60,8 @@ public class STrades extends BusinessObject {
private Long tradeTimeMs;
private String bankAccId;
private String section;
private String kind;
private Long linkedTrade;
public Long getTradeNum() {
return tradeNum;
@ -412,4 +414,20 @@ public class STrades extends BusinessObject {
public void setSection(String section) {
this.section = section;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public Long getLinkedTrade() {
return linkedTrade;
}
public void setLinkedTrade(Long linkedTrade) {
this.linkedTrade = linkedTrade;
}
}

View file

@ -0,0 +1,53 @@
package ru.clearing.classes.statics.data.security;
import java.math.BigDecimal;
import java.time.LocalDate;
import ru.clearing.classes.objects.BusinessObject;
public class Rates extends BusinessObject {
private BigDecimal value;
private LocalDate valueDate;
private String currency;
private Long currencyId;
private String workflowStatus;
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public LocalDate getValueDate() {
return valueDate;
}
public void setValueDate(LocalDate valueDate) {
this.valueDate = valueDate;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public Long getCurrencyId() {
return currencyId;
}
public void setCurrencyId(Long currencyId) {
this.currencyId = currencyId;
}
public String getWorkflowStatus() {
return workflowStatus;
}
public void setWorkflowStatus(String workflowStatus) {
this.workflowStatus = workflowStatus;
}
}

View file

@ -0,0 +1,52 @@
package ru.clearing.classes.statics.data.security;
import java.math.BigDecimal;
import ru.clearing.classes.objects.BusinessObject;
public class RiskParameter extends BusinessObject {
private BigDecimal value;
private String settlementType;
private String currencyPair;
private Long currencyPairId;
private String workflowStatus;
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
public String getSettlementType() {
return settlementType;
}
public void setSettlementType(String settlementType) {
this.settlementType = settlementType;
}
public String getCurrencyPair() {
return currencyPair;
}
public void setCurrencyPair(String currencyPair) {
this.currencyPair = currencyPair;
}
public Long getCurrencyPairId() {
return currencyPairId;
}
public void setCurrencyPairId(Long currencyPairId) {
this.currencyPairId = currencyPairId;
}
public String getWorkflowStatus() {
return workflowStatus;
}
public void setWorkflowStatus(String workflowStatus) {
this.workflowStatus = workflowStatus;
}
}

View file

@ -6,13 +6,13 @@
<parent>
<groupId>ru.spcex.clearing</groupId>
<artifactId>clearing-parent</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<artifactId>cleaning-builders</artifactId>
<name>cleaning-builders</name>
<description>Cleaning builders module</description>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<packaging>jar</packaging>
@ -26,7 +26,7 @@
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>classes</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>

View file

@ -5,7 +5,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -15,8 +15,17 @@ public class ClearingServiceSettings {
private KafkaConsumerSettings kafkaConsumer;
private KafkaProducerSettings kafkaProducer;
private SessionStageSettings sessionStage;
private boolean balanceCheckOmt = false;
private TradeSettings trade = new TradeSettings();
public boolean isBalanceCheckOmt() {
return balanceCheckOmt;
}
public void setBalanceCheckOmt(boolean balanceCheckOmt) {
this.balanceCheckOmt = balanceCheckOmt;
}
public HazelcastClientParams getHazelcast() {
return hazelcast;
}

View file

@ -42,6 +42,7 @@ 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.PaymSession;
import ru.spcex.clearing.session.stage.PrimaryAuctionB0Session;
import ru.spcex.clearing.session.stage.PrimaryAuctionBnSession;
import ru.spcex.clearing.session.stage.PrimaryAuctionT0Session;
@ -73,6 +74,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
private final PrimaryAuctionB0Session primaryAuctionB0Session;
private final IntermediateMkrSession intermediateMkrSession;
private final FinalMkrSession finalMkrSession;
private final PaymSession paymSession;
private final UnitedSession unitedSession;
private final ReturnDepositSession returnDepositSession;
private final SessionManager sessionManager;
@ -96,7 +98,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
PrimaryAuctionBnSession primaryAuctionBnSession,
SecondaryAuctionT0Session secondaryAuctionT0Session,
CurrencySession currencySession,
PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, UnitedSession unitedSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager, SessionStateMachineWrapper stateMachineWrapper,
PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, PaymSession paymSession, UnitedSession unitedSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager, SessionStateMachineWrapper stateMachineWrapper,
Sdf06Executor sdf06Executor,
Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender, StatementServiceV2 statementService, SessionTerminator sessionTerminator, PaymentInstructionOutboundService pmtOutboundService, ExecutionCurrencyComponent execCurrUpload, ExecutionDepositComponent execDepUpload, ExecutionFondComponent execFondUpload) {
super(kafkaQueue, kafkaResponseQueue);
@ -111,6 +113,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
this.primaryAuctionT0Session = primaryAuctionT0Session;
this.intermediateMkrSession = intermediateMkrSession;
this.finalMkrSession = finalMkrSession;
this.paymSession = paymSession;
this.unitedSession = unitedSession;
this.returnDepositSession = returnDepositSession;
this.sessionManager = sessionManager;
@ -177,6 +180,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
//finalMkrSession.continueSession(req);
unitedSession.continueSession(req);
returnDepositSession.continueSession(req);
paymSession.continueSession(req);
SessionContinueEvent payload = req.getRequestPayload();
Stream
.ofNullable(payload.getSdfType())

View file

@ -68,6 +68,9 @@ public class Sdf54Creator {
Status.Active.getKey(),
pmt.getCreditLeg_currencyCode()
));
if (anltAcc == null) {
throw new IllegalStateException("couldn't fill acc_deb - no ANLT account for " + pmt.getCreditLeg_currencyCode());
}
// c_acc_deb = c_acc_deb == null ? paymentInstruction.getCreditLeg_account() : c_acc_deb;
c_acc_cred = c_acc_cred == null ? pmt.getDebitLeg_account() : c_acc_cred;
@ -77,6 +80,9 @@ public class Sdf54Creator {
sDf54.setId(idGenerator.nextId());
sDf54.setSeg_type("V");
Long debCompanyId = anltAcc.getCompanyId();
sDf54.setAcc_deb(anltAcc.getAccount());
//**********************
String tranBic = selectSymbolValue(Sender.Prc.getId(), CompanySymbol.BIC);
if (tranBic == null) {
@ -103,22 +109,19 @@ public class Sdf54Creator {
sDf54::setSbanknam5);
sDf54.setOp_type("01");
sDf54.setOp_order("5");
String innDeb = selectSymbolValue(Sender.One.getId(), CompanySymbol.INN);
String innDeb = selectSymbolValue(debCompanyId, CompanySymbol.INN);
if (innDeb == null) {
log.warn("CompanySymbols INN not found for companyId={}", Sender.One.getId());
log.warn("CompanySymbols INN not found for companyId={}", debCompanyId);
} else {
sDf54.setInn_deb(innDeb);
}
String kppDeb = selectSymbolValue(Sender.One.getId(), CompanySymbol.CPP);
String kppDeb = selectSymbolValue(debCompanyId, CompanySymbol.CPP);
if (kppDeb == null) {
log.warn("CompanySymbols CPP not found for companyId={}", Sender.One.getId());
log.warn("CompanySymbols CPP not found for companyId={}", debCompanyId);
} else {
sDf54.setKpp_deb(kppDeb);
}
if (anltAcc != null) {
sDf54.setAcc_deb(anltAcc.getAccount());
}
Account accDebAcc = accountImdg.getSingleObjectByID(pmt.getDebitLeg_accountId());
if (accDebAcc == null || !AccountStatus.ACTIVE.equalsByKey(accDebAcc.getStatus())) {
log.warn("paymentInstruction[{}].DebitLeg_accountId={} account not exist or not active.", pmt.getId(), pmt.getDebitLeg_accountId());
@ -177,7 +180,7 @@ public class Sdf54Creator {
sDf54.setC_acc_cred(c_acc_cred);
{
Company company1 = companyImdg.getSingleObjectByID(Sender.One.getId());
Company company1 = companyImdg.getSingleObjectByID(debCompanyId);
if (company1 != null) { // "АО СПВБ" company.shortName[id = 1]
String sclientn;
if (LocaleUtil.isRus(locale)) {

View file

@ -35,6 +35,7 @@ import ru.spcex.clearing.service.Sdf54Creator;
import ru.spcex.clearing.service.builder.PaymentInstructionBuilderV2;
import ru.spcex.clearing.service.integration.GatewayRequestCreator;
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
import ru.spcex.clearing.service.registry.BalanceChecker;
import ru.spcex.clearing.service.registry.DmiService;
import ru.spcex.clearing.service.registry.RegistryManager;
import ru.spcex.clearing.service.schedule.TradingTimeService;
@ -55,6 +56,7 @@ import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.enumeration.IEnumId;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
import ru.spcex.platform.utils.localization.SpringPropertiesLocalizer;
import ru.spcex.platform.utils.log.ExceptionUtils;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
import ru.spcex.platform.utils.text.TextUtil;
import ru.spcex.platform.utils.validation.IValidator;
@ -82,6 +84,7 @@ public class PaymentInstructionOutboundService {
private final TradingTimeService time;
private final GatewayRequester gateway;
private final NotificationSender notification;
private final BalanceChecker balanceChecker;
private final SpringPropertiesLocalizer resolver;
@Autowired
@ -89,7 +92,7 @@ public class PaymentInstructionOutboundService {
IMessageResolver msgs,
ImdgProvider imdgProvider,
Function<PIClearingOutbondActionNewRequest, IValidator> validation, RegistryManager rgsMng, KafkaSender kafkaSender, AssetTBFProcessing assetsMng, DmiService dmiService, TradingTimeService time, GatewayRequester gateway, NotificationSender notification,
SpringPropertiesLocalizer resolver) {
SpringPropertiesLocalizer resolver, BalanceChecker balanceChecker) {
this.imdgProvider = imdgProvider;
this.rights = rights;
this.msgs = msgs;
@ -101,6 +104,7 @@ public class PaymentInstructionOutboundService {
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.currImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
this.sdf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class);
this.balanceChecker = balanceChecker;
this.sdf54Creator = new Sdf54Creator(imdgProvider, resolver);
this.idGenerator = imdgProvider.getImdgIdGenerator();
this.rgsMng = rgsMng;
@ -172,25 +176,42 @@ public class PaymentInstructionOutboundService {
//fixme pmt.setDocumentNumber(registry.getSecurityId());
pmtImdg.insert(pmt);
log.debug("new PaymentInstruction.id: {}", pmt.getId());
log.debug("PIClearingOutbondActionNewRequest.id={} new PaymentInstruction.id: {}",
req.getId(),
pmt.getId());
Optional<AssetTrio> assets = assetsMng.searchMoneyByAccAndCompany(addressee.getId(), accCred.getId());
if (assets.isEmpty() || assetsMng.insufficientBalance(assets.get().a__f(), amount)) {
log.debug("PIClearingOutbondActionNewRequest.id={} a__f asset id={}",
req.getId(),
assets.map(AssetTrio::a__f).map(Registry::getId).orElse(null));
if (assets.isEmpty() || balanceChecker.insufficientBalance(assets.get().a__f(),
tcr.getId(), //never null because validation
accCred.getCurrency(),
amount)) {
pmt.setTransactionStatus(TransactionStatus.cher.getKey());
pmt.setUpdated(now);
pmtImdg.update(pmt);
log.debug("insufficient balance, pmt.id: {}, am*f.balance={}",
pmt.getId(), assets.map(AssetTrio::a__f).map(Registry::getBalance).orElse(null));
pmt.getId(), assets.map(AssetTrio::a__f).map(Registry::getBalance).orElse(null));
return error(req.getId(), ClearingError.BalanceInsufficient);
}
log.debug("assets found and balance is ok. am*b.id={}, am*t.id={}, am*f.id={}",
assets.get().a__b().getId(), assets.get().a__t().getId(), assets.get().a__f().getId());
SDf54 sDf54 = sdf54Creator.create(pmt);
SDf54 sDf54 = null;
try {
sDf54 = sdf54Creator.create(pmt);
} catch (IllegalStateException e) {
log.error(ExceptionUtils.getStackTrace(e));
pmt.setTransactionStatus(TransactionStatus.fail.getKey());
pmt.setUpdated(now);
pmtImdg.update(pmt);
return error(req.getId(), ClearingError.GeneralError);
}
sDf54.setId(idGenerator.nextId());
sDf54.setGenerationId(pmt.getId());
if (time.isTradingTime()) {
Supplier<AssetOperationRequest> builder = () -> GatewayRequestCreator.from(pmt,
assets.get().a__b().getTradingCode(),
tcr.getCode());
assets.get().a__b().getTradingCode(),
tcr == null ? null : tcr.getCode());
Optional<Boolean> gatewayOk = gateway.gatewayRequestAndWait(builder);
if (gatewayOk.isEmpty() || gatewayOk.get().equals(Boolean.FALSE)) {
String gtwErrMsg = msgs.resolve(mapError(gatewayOk));

View file

@ -0,0 +1,247 @@
package ru.spcex.clearing.service.registry;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.security.CurrencyPairSecurity;
import ru.clearing.classes.statics.data.security.Rates;
import ru.clearing.classes.statics.data.security.RiskParameter;
import ru.spcex.clearing.config.element.ClearingServiceSettings;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import static ru.spcex.clearing.util.NumberUtils.safeCast;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.RegistryStatus;
import static ru.spcex.platform.enumeration.RegistryTradingParams.OM_T;
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;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashCloser;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.key.GenericCashingKey1;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.key.GenericCashingKey2;
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
import ru.spcex.platform.utils.text.TextUtil;
@Component
public class BalanceChecker {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<Registry> rgsImdg;
private final Imdg<Rates> rateImdg;
private final Imdg<RiskParameter> riskParamImdg;
private final Imdg<CurrencyPairSecurity> currPairImdg;
private final boolean balanceCheckOmts;
@Autowired
public BalanceChecker(ImdgProvider imdgProvider, ClearingServiceSettings settings) {
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
this.rateImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_Rates, Rates.class, null);
this.riskParamImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_RiskParameter, RiskParameter.class, null);
this.currPairImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class, null);
this.balanceCheckOmts = settings.isBalanceCheckOmt();
}
public boolean insufficientBalance(Registry a__f,
Long tcrId,
String accCurrency,
BigDecimal amount) {
if (!balanceCheckOmts) {
log.info("{}#id={}#balance={} check for amount {}; OM*T checks disabled",
a__f.getRegistryCode(), a__f.getId(), a__f.getBalance(), amount);
return safeBD(a__f.getBalance()).compareTo(safeBD(amount)) < 0;
}
log.info("{}#id={}#balance={} check for amount {}; OM*T checks enabled",
a__f.getRegistryCode(), a__f.getId(), a__f.getBalance(), amount);
LocalDate today = LocalDate.now();
ImdgPredicateBuilder rgsPb = rgsImdg.predicateBuilder();
ImdgPredicateBuilder ratePb = rateImdg.predicateBuilder();
Function<ImdgPredicate, ImdgPredicate> rgsAnd = p -> rgsPb.and(
rgsPb.sql(RegistryCodeSqlBuilder.getInstance(OM_T).build()),
rgsPb.equals("tradingClearingRegistryId", tcrId),
rgsPb.or(
rgsPb.equals("registryStatus", RegistryStatus.PROC.getKey()),
rgsPb.equals("registryStatus", RegistryStatus.MNG.getKey())
),
p
);
try (BalanceCheckerCash cash = new BalanceCheckerCash()) {
Collection<Registry> omtsToday = rgsImdg.getCollectionObjectsByPredicate(
rgsAnd.apply(
rgsPb.equals("settlementDate", today)
)
);
Collection<Registry> omtsNotToday = rgsImdg.getCollectionObjectsByPredicate(
rgsAnd.apply(
rgsPb.not(rgsPb.equals("settlementDate", today))
)
);
log.debug("a__f.id={} balance checking; omt today: {}, omt !today: {}",
a__f.getId(), omtsToday.size(), omtsNotToday.size());
BiFunction<Collection<Registry>, String, BigDecimal> omtSum = (rgss, settlType)
-> rgss
.stream()
.map(r -> {
Optional<Rates> crossRate = loadRate(r, today, cash);
Optional<RiskParameter> riskParam = loadRisk(r, settlType, cash);
BigDecimal oblAmount = r.getBalance();
BigDecimal rate = crossRate.map(Rates::getValue).orElse(BigDecimal.ONE);
BigDecimal risk = riskParam.map(RiskParameter::getValue).orElse(BigDecimal.ONE);
BigDecimal singleOblSum = safeBD(oblAmount)
.multiply(rate)
.multiply(risk);
log.debug("for {}.id={}: Rate.id={}; RiskParameter.id={}",
r.getRegistryCode(), r.getId(),
crossRate.map(SpcexObjectBase::getId).orElse(null),
riskParam.map(SpcexObjectBase::getId).orElse(null)
);
return singleOblSum;
})
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal todaySum = omtSum.apply(omtsToday, "T0");
BigDecimal notTodaySum = omtSum.apply(omtsNotToday, "T1");
Rates rate = rateImdg.getFirstObjectByPredicate(
ratePb.and(
ratePb.equals("currency", accCurrency),
ratePb.equals("valueDate", today)
)
);
BigDecimal rateValue = (rate != null && rate.getValue() != null) ?
rate.getValue() : BigDecimal.ONE;
BigDecimal sumForObligations = todaySum
.add(notTodaySum)
.divide(rateValue, RoundingMode.HALF_UP);
log.debug("a__f.id={}, today OM*T sum {}; !today OM*T sum {}; rate for final formula: id={}, value={}; overall OM*T sum: {}",
a__f.getId(), todaySum, notTodaySum,
rate != null ? rate.getId() : null,
rateValue,
sumForObligations
);
return safeBD(a__f.getBalance())
.subtract(sumForObligations)
.compareTo(safeBD(amount)) < 0;
}
}
private Optional<Rates> loadRate(Registry rgs,
LocalDate valueDate,
BalanceCheckerCash cash) {
if (TextUtil.isEmpty(rgs.getSecuritySymbol())) {
return Optional.empty();
}
ImdgPredicateBuilder ratePb = rateImdg.predicateBuilder();
ImdgPredicate ratePredicate = ratePb.and(
ratePb.equals("valueDate", valueDate),
ratePb.equals("currency", rgs.getSecuritySymbol())
);
return Optional.ofNullable(rateImdg.getFirstObjectByPredicate(
ratePb.cashed(
ratePredicate,
cash.ratesCash,
new GenericCashingKey2<>(valueDate, rgs.getSecuritySymbol())
)
));
}
private CurrencyPairSecurity loadCurrPairSec(String contract, BalanceCheckerCash cash) {
ImdgPredicateBuilder currPb = currPairImdg.predicateBuilder();
Long contractCasted = safeCast(contract);
if (contractCasted == null) {
return null;
}
ImdgPredicate prdct = currPb.cashed(
currPb.equals("id", contractCasted),
cash.currPairCash,
new GenericCashingKey1<>(contractCasted));
return currPairImdg.getFirstObjectByPredicate(
prdct
);
}
private Optional<RiskParameter> loadRisk(
Registry rgs, String settlementType, BalanceCheckerCash cash
) {
CurrencyPairSecurity pair = loadCurrPairSec(
rgs.getContract(), cash
);
if (pair == null) {
log.warn("cannot find currencyPairSecurity for {}#id={}#contract={}",
rgs.getRegistryCode(),
rgs.getId(),
rgs.getContract());
return Optional.empty();
}
log.debug("found currencyPairSecurity.id={} for {}.id={}",
rgs.getRegistryCode(),
rgs.getId(),
pair.getId());
ImdgPredicateBuilder riskPb = riskParamImdg.predicateBuilder();
ImdgPredicate prdct = riskPb.and(
riskPb.equals("currencyPairId", pair.getCurrencyPairId()),
riskPb.equals("settlementType", settlementType),
riskPb.equals("workflowStatus", WorkflowStatus.Active.getKey())
);
ImdgPredicate prdctF = riskPb.cashed(
prdct,
cash.riskCash,
new GenericCashingKey2<>(pair.getId(), settlementType)
);
return Optional.ofNullable(riskParamImdg.getFirstObjectByPredicate(prdctF));
}
protected static class BalanceCheckerCash extends CashCloser {
protected final CashV2<GenericCashingKey2<LocalDate, String>, Rates> ratesCash;
protected final CashV2<GenericCashingKey2<Long, String>, RiskParameter> riskCash;
protected final CashV2<GenericCashingKey1<Long>, CurrencyPairSecurity> currPairCash;
public BalanceCheckerCash() {
cashes = new ArrayList<>();
ratesCash = add(new CashV2<GenericCashingKey2<LocalDate, String>, Rates>() {
@Override
protected GenericCashingKey2<LocalDate, String> extractKey(Rates obj) {
return new GenericCashingKey2<>(obj.getValueDate(), obj.getCurrency());
}
});
riskCash = add(new CashV2<GenericCashingKey2<Long, String>, RiskParameter>() {
@Override
protected GenericCashingKey2<Long, String> extractKey(RiskParameter obj) {
return new GenericCashingKey2<>(obj.getCurrencyPairId(), obj.getSettlementType());
}
});
currPairCash = add(new CashV2<GenericCashingKey1<Long>, CurrencyPairSecurity>() {
@Override
protected GenericCashingKey1<Long> extractKey(CurrencyPairSecurity obj) {
return new GenericCashingKey1<>(obj.getCurrencyPairId());
}
});
}
}
}

View file

@ -5,7 +5,6 @@ import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.enumeration.AccountType;
import ru.spcex.platform.enumeration.Sender;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
@ -32,9 +31,8 @@ public class AnltAccLoad implements IValidationRule<ImdgValidationContext<Object
Imdg<SpcexObjectBase> accImdg = context.obtainMap(IMDGDistributedNames.Map_Account, SpcexObjectBase.class);
ImdgPredicateBuilder pb = accImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.equals("companyId", Sender.One.getId()),
pb.equals("accountType", AccountType.Anlt.getKey()),
pb.equals("currency", rgs.getSecuritySymbol())
pb.equals("currency", rgs.getSecuritySymbol()),
pb.equals("accountType", AccountType.Anlt.getKey())
);
Object anltAcc = accImdg.getSingleObjectByPredicate(prdct);
if (anltAcc == null) {

View file

@ -21,8 +21,6 @@ import ru.spcex.platform.enumeration.AccountType;
import ru.spcex.platform.enumeration.RegistryTradingParams;
import ru.spcex.platform.enumeration.ServiceStatus;
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.imdg.validation.Stored;
import ru.spcex.platform.utils.enumeration.EnumMessage;
@ -138,22 +136,6 @@ public enum IdentificationFundsValidationRule implements IValidationRule<ImdgVal
context.storeObject(ValidationStored.IdentificationFundsAssetTrio, assetTrio.get());
return Optional.empty();
}
},
AnltLoad() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<IdentificationFundsRequest> context) {
Imdg<Account> accImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
ImdgPredicateBuilder pb = accImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
pb.equals("companyId", 1L),
pb.equals("accountType", AccountType.Anlt.getKey())
);
Account anltAcc = accImdg.getSingleObjectByPredicate(prdct);
if (anltAcc == null) {
return of(ClearingError.GeneralError);
}
return empty();
}
}
;
private final static Logger log = LoggerFactory.getLogger(IdentificationFundsValidationRule.class);

View file

@ -8,6 +8,7 @@ import ru.spcex.clearing.error.ClearingError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.service.validation.RegistryValidationStored;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.Sender;
import ru.spcex.platform.enumeration.ServiceStatus;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
@ -54,6 +55,9 @@ public class ClearingAvailableValidationRule implements IValidationRule<ImdgVali
String section = validatedObject.getSection();
Section sctn = IEnumKey.getEnumByKey(Section.class, validatedObject.getSection());
if (Section.CURR.equals(sctn)) {
if (Sender.CK.equalsById(validatedObject.getCompanyId())) {
return empty();
}
section = Section.MKR.getKey();
}
Imdg<Relation> rltnImdg = context.obtainMap(IMDGDistributedNames.Map_Relation, Relation.class);

View file

@ -0,0 +1,238 @@
package ru.spcex.clearing.session.stage;
import java.time.Instant;
import java.time.LocalDate;
import java.util.List;
import java.util.function.Supplier;
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.execution.ExecutionCommon;
import ru.clearing.classes.statics.data.execution.ExecutionCurrency;
import ru.clearing.classes.statics.data.misc.Session;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.session.stage.impl.BalanceRevise;
import ru.spcex.clearing.session.stage.impl.DealsPrepare;
import ru.spcex.clearing.session.stage.impl.EndStageNotification;
import ru.spcex.clearing.session.stage.impl.FinishingSession;
import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionAssets;
import ru.spcex.clearing.session.stage.impl.InclusionObligations;
import ru.spcex.clearing.session.stage.impl.InspectionObligationsV2;
import ru.spcex.clearing.session.stage.impl.ObligationAdmission;
import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation;
import ru.spcex.clearing.session.stage.monitor.SessionMonitor;
import ru.spcex.clearing.session.stage.task.DealsPreparePayload;
import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload;
import ru.spcex.clearing.session.stage.task.FinishingSessionPayload;
import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload;
import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload;
import ru.spcex.clearing.session.stage.task.InspectionPoolPayload;
import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload;
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.SessionStatus;
import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
@Service
public class PaymSession extends AbstractSession implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final DealsPrepare dealsPrepare;
private final RequirementsAndObligationCreation requirementsAndObligationCreation;
private final ObligationAdmission obligationsAdmission;
private final BalanceRevise balanceRevise;
private final InclusionObligations inclusionObligations;
private final InspectionObligationsV2 inspectionObligations;
private final FormingPaymentInstructionAssets formingPaymentInstructionAssets;
private final FinishingSession finishingSession;
private final EndStageNotification endStageNotification;
private final Imdg<ExecutionCurrency> executionCurrencyImdg;
private final Supplier<List<String>> marketCodes;
private SessionMonitor afterReviseErrorMonitor;
public PaymSession(
ImdgProvider imdgProvider,
DealsPrepare dealsPrepare,
RequirementsAndObligationCreation requirementsAndObligationCreation,
ObligationAdmission obligationsAdmission,
InclusionObligations inclusionObligations,
BalanceRevise balanceRevise,
FormingPaymentInstructionAssets formingPaymentInstructionAssets,
FinishingSession finishingSession,
EndStageNotification endStageNotification,
IMessageResolver messageResolver,
InspectionObligationsV2 inspectionObligations,
@Qualifier("marketCodesForCurr") Supplier<List<String>> marketCodes) {
super(imdgProvider, messageResolver);
this.dealsPrepare = dealsPrepare;
this.requirementsAndObligationCreation = requirementsAndObligationCreation;
this.obligationsAdmission = obligationsAdmission;
this.inclusionObligations = inclusionObligations;
this.balanceRevise = balanceRevise;
this.formingPaymentInstructionAssets = formingPaymentInstructionAssets;
this.finishingSession = finishingSession;
this.endStageNotification = endStageNotification;
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.in("market", marketCodes.get().toArray(new String[0])));
requirementsAndObligationCreation.setSessionType(sessionType());
formingPaymentInstructionAssets.setSessionType(sessionType());
formingPaymentInstructionAssets.setDisableCompanyCondition(true);
inclusionObligations.setSessionType(sessionType());
inspectionObligations.setSection(section());
inspectionObligations.setSessionType(sessionType());
finishingSession.setSection(section());
finishingSession.setSessionType(sessionType());
imdgProvider.waitAvailable();
initSessionIfPresent();
}
@Override
public void runSession(BaseRequest<?> req) {
if (!startSession()) {
return;
}
try {
runStage(TaskType.StartRevisePart1, currSession.getId(), balanceRevise);
//stage 1
StageResult<List<ExecutionCommon>> dealsPreparationResult;
{
DealsPreparePayload payload = new DealsPreparePayload();
payload.setSessionId(currSession.getId());
dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare);
}
{
//stage 2
RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload(
dealsPreparationResult.getStageResult(), currSession.getId()
);
runStage(TaskType.RequirementsAndObligationsCreate, payload, 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 7
{
FormingPaymentInstructionPayload payload = new FormingPaymentInstructionPayload();
payload.setSessionId(currSession.getId());
runStage(TaskType.FormingPaymentInstruction, payload, formingPaymentInstructionAssets);
}
finishPart();
} catch (StageException e) {
//already logged
}
}
public void continueSession(BaseRequest<?> req) {
try {
if (!isRunning()) {
return;
}
log.info("session is running, stage {}, monitors: {}",
currStage.get(),
logMonitors(afterReviseErrorMonitor));
if (afterReviseErrorMonitor != null && isMonitorPassed(afterReviseErrorMonitor, req.getRequestPayload())) {
afterReviseErrorMonitor = null;
finishPart();
return;
}
} catch (StageException e) {
//already logged
}
}
public void finishPart() {
try {
//stage 9 continue revision
{
StageResult<Object> reviseRes = runStage(TaskType.AgainRevise, currSession.getId(), balanceRevise, false);
if (!reviseRes.isSuccess()) {
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().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.CURR;
}
@Override
protected SessionType sessionType() {
return SessionType.PAYM;
}
}

View file

@ -0,0 +1,131 @@
package ru.spcex.clearing.session.stage;
import java.time.Instant;
import java.time.LocalDate;
import java.util.List;
import java.util.function.Supplier;
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.execution.ExecutionCommon;
import ru.clearing.classes.statics.data.execution.ExecutionCurrency;
import ru.clearing.classes.statics.data.misc.Session;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.session.stage.impl.BalanceRevise;
import ru.spcex.clearing.session.stage.impl.DealsPrepare;
import ru.spcex.clearing.session.stage.impl.ObligationAdmission;
import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation;
import ru.spcex.clearing.session.stage.task.DealsPreparePayload;
import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload;
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
import ru.spcex.platform.enumeration.Section;
import ru.spcex.platform.enumeration.SessionStatus;
import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.utils.enumeration.IMessageResolver;
@Service
public class PrepSession extends AbstractSession implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final DealsPrepare dealsPrepare;
private final RequirementsAndObligationCreation requirementsAndObligationCreation;
private final ObligationAdmission obligationsAdmission;
private final Imdg<ExecutionCurrency> executionCurrencyImdg;
private final Supplier<List<String>> marketCodes;
public PrepSession(
ImdgProvider imdgProvider,
BalanceRevise balanceRevise,
DealsPrepare dealsPrepare,
RequirementsAndObligationCreation requirementsAndObligationCreation,
IMessageResolver messageResolver, ObligationAdmission obligationsAdmission,
@Qualifier("marketCodesForCurr") Supplier<List<String>> marketCodes) {
super(imdgProvider, messageResolver);
this.dealsPrepare = dealsPrepare;
this.requirementsAndObligationCreation = requirementsAndObligationCreation;
this.obligationsAdmission = obligationsAdmission;
this.executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class);
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])));
requirementsAndObligationCreation.setSessionType(sessionType());
imdgProvider.waitAvailable();
initSessionIfPresent();
}
@Override
public void runSession(BaseRequest<?> req) {
if (!startSession()) {
return;
}
log.info("session is running, stage {}", currStage.get());
try {
//stage 1
StageResult<List<ExecutionCommon>> dealsPreparationResult;
{
DealsPreparePayload payload = new DealsPreparePayload();
payload.setSessionId(currSession.getId());
dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare);
}
{
//stage 2
RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload(
dealsPreparationResult.getStageResult(), currSession.getId()
);
runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation);
}
//stage 3
runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission);
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().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.CURR;
}
@Override
protected SessionType sessionType() {
return SessionType.PREP;
}
}

View file

@ -37,6 +37,9 @@ public class SessionManager {
private final CurrencySession currencySession;
private final IntermediateMkrSession intermediateMkrSession;
private final FinalMkrSession finalMkrSession;
private final PrepSession prepSession;
private final PaymSession paymSession;
private final ReturnDepositSession returnDepositSession;
private final UnitedSession unitedSession;
private final TradingTimeService time;
@ -46,7 +49,7 @@ public class SessionManager {
PrimaryAuctionBnSession primaryAuctionBnSession,
PrimaryAuctionB0Session primaryAuctionB0Session,
SecondaryAuctionT0Session secondaryAuctionT0Session, CurrencySession currencySession,
IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, UnitedSession unitedSession, TradingTimeService time) {
IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, PrepSession prepSession, PaymSession paymSession, ReturnDepositSession returnDepositSession, UnitedSession unitedSession, TradingTimeService time) {
this.notification = notification;
this.msgs = msgs;
this.primaryAuctionT0Session = primaryAuctionT0Session;
@ -56,6 +59,8 @@ public class SessionManager {
this.currencySession = currencySession;
this.intermediateMkrSession = intermediateMkrSession;
this.finalMkrSession = finalMkrSession;
this.prepSession = prepSession;
this.paymSession = paymSession;
this.returnDepositSession = returnDepositSession;
sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
@ -123,6 +128,8 @@ public class SessionManager {
case CURR -> session = currencySession;
case MEDM -> session = intermediateMkrSession;
case FINL -> session = finalMkrSession;
case PREP -> session = prepSession;
case PAYM -> session = paymSession;
case XDEP -> session = returnDepositSession;
case UNIT -> session = unitedSession;
}

View file

@ -188,7 +188,7 @@ public class FinishingSession implements ISessionStage {
notAllowed,
executions.size() - (allowed + notAllowed));
}
if (IEnumKey.contains(sessionType, SessionType.CURR, SessionType.TRDT, SessionType.IPOB, SessionType.IPO0, SessionType.IPOT, SessionType.UNIT)) {
if (IEnumKey.contains(sessionType, SessionType.CURR, SessionType.PAYM, SessionType.TRDT, SessionType.IPOB, SessionType.IPO0, SessionType.IPOT, SessionType.UNIT)) {
Collection<? extends ExecutionCommon> executions = findExecutionFondBySessionId(sessionId, sessionType);
Map<Long, ExecutionCurrency> execCurr = new HashMap<>();
Map<Long, ExecutionFond> execFond = new HashMap<>();
@ -248,7 +248,9 @@ public class FinishingSession implements ISessionStage {
return sResult;
}
}
sdf05Sender.sendSdf05(pr);
if (!SessionType.PAYM.equals(sessionType)) {
sdf05Sender.sendSdf05(pr);
}
if (Section.FOND.equals(section) || Section.MULT.equals(section)) {
sdf14Sender.sendSdf14(sessionId);
}
@ -336,7 +338,7 @@ public class FinishingSession implements ISessionStage {
return res;
} else {
Imdg<? extends ExecutionCommon> excImdg;
if (sessionType.equals(SessionType.CURR)) {
if (sessionType.equals(SessionType.CURR) || sessionType.equals(SessionType.PAYM)) {
excImdg = executionCurrencyImdg;
} else {
excImdg = executionFondImdg;

View file

@ -7,7 +7,6 @@ import java.time.format.DateTimeFormatter;
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.function.Function;
@ -101,6 +100,7 @@ public class FormingPaymentInstructionAssets implements ISessionStage {
private SessionType sessionType;
private final PaymentStateMarkService dmvSrv;
private final AssetTBFProcessing assets;
private boolean disableCompanyCondition = false;
@Autowired
public FormingPaymentInstructionAssets(ImdgProvider imdgProvider,
@ -137,6 +137,10 @@ public class FormingPaymentInstructionAssets implements ISessionStage {
}
}
public void setDisableCompanyCondition(boolean disableCompanyCondition) {
this.disableCompanyCondition = disableCompanyCondition;
}
private Collection<Registry> selectAMBRegistries(Long sessionId) {
ImdgPredicateBuilder rgsPb = registryImdg.predicateBuilder();
RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(
@ -200,10 +204,14 @@ public class FormingPaymentInstructionAssets implements ISessionStage {
if (AccountType.Clrn.equalsByKey(registry.getAccountType())) {
counterAcc = accountImdg.getSingleObjectByID(registry.getAccountId());
} else if (AccountType.Info.equalsByKey(registry.getAccountType())) {
counterAcc = accountImdg.getFirstObjectByFieldValues(
Map.of("companyId", 1L,
"currency", registry.getSecuritySymbol(),
"accountType", AccountType.Anlt.getKey())
ImdgPredicateBuilder pb = accountImdg.predicateBuilder();
ImdgPredicate prdct = pb.and(
disableCompanyCondition ? pb.alwaysTrue() : pb.equals("companyId", 1L),
pb.equals("currency", registry.getSecuritySymbol()),
pb.equals("accountType", AccountType.Anlt.getKey())
);
counterAcc = accountImdg.getFirstObjectByPredicate(
prdct
);
}
Long senderId;
@ -407,7 +415,7 @@ public class FormingPaymentInstructionAssets implements ISessionStage {
Registry rgs = pair.getSecond();
Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId());
Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId());
if (SessionType.CURR.equals(sessionType) || (rgs != null
if (SessionType.CURR.equals(sessionType) || SessionType.PAYM.equals(sessionType) || (rgs != null
&& RegistryInstrumentType.M.equalsByKey(rgs.getRegistryInstrumentType())
&& !CurrencyCode.isRub(rgs.getSecuritySymbol()))) {
boolean madeStatements = statementsWereMade(paymentInstruction, rgs);
@ -496,7 +504,7 @@ public class FormingPaymentInstructionAssets implements ISessionStage {
private boolean statementsWereMade(PaymentInstruction pmt, Registry am_b) {
ImdgPredicateBuilder pb = stlmHPropsImdg.predicateBuilder();
String curCode = pmt.getCreditLeg_currencyCode();
{
if (!SessionType.PAYM.equals(sessionType)) {
SettlementHouseProperties sttHs = stlmHPropsImdg.getFirstObjectByPredicate(
pb.and(
pb.in("currencyCode", curCode),

View file

@ -41,4 +41,5 @@ public interface IRegistryBuilder {
default IRegistryBuilder dpAccCash(CashV2<Long, DepoAccount> dpAccCash) {return this;}//CashV2<Long, DepoAccount> dpAccCash;
default IRegistryBuilder currCash(CashV2<String, Currency> currCash) {return this;}//CashV2<String, Currency> currCash;
default IRegistryBuilder clrAccCash(CashV2<Long, ClearingAccount> clrAccCash) {return this;}//CashV2<Long, ClearingAccount> clrAccCash;
default IRegistryBuilder ckTcr(TradingClearingRegistry ckTcr) {return this;}
}

View file

@ -175,7 +175,7 @@ public class InclusionObligations implements ISessionStage {
switch (ssnTpe) {
case MEDM, FINL, XDEP -> execImdg = (Imdg<T>) executionDepositImdg;
case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg<T>) executionFondImdg;
case CURR -> execImdg = (Imdg<T>) executionCurrImdg;
case CURR, PAYM -> execImdg = (Imdg<T>) executionCurrImdg;
default -> {
//кейс для "общих" сессий (напр. UNIT) в которых сочетаются разные сделки
//смотрим на секцию регистра.
@ -228,6 +228,11 @@ public class InclusionObligations implements ISessionStage {
rgsPb.equals("sessionType", SessionType.MEDM.getKey()),
rgsPb.equals("sessionType", SessionType.XDEP.getKey())
);
} else if (SessionType.PAYM.equals(sessionType)) {
return rgsPb.or(
rgsPb.equals("sessionType", SessionType.PREP.getKey()),
rgsPb.equals("sessionType", SessionType.PAYM.getKey())
);
} else {
return rgsPb.equals("sessionType", sessionType.getKey());
}

View file

@ -163,7 +163,7 @@ public class InspectionObligationsV2 implements ISessionStage {
boolean isUncovered = false;
List<CheckResult> checkResults = new ArrayList<>();
for (Registry obligation : obligationsInGroup) {
if ((SessionType.FINL.equals(sessionType) || SessionType.UNIT.equals(sessionType) || SessionType.MEDM.equals(sessionType)) && RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType())) {
if ((SessionType.FINL.equals(sessionType) || SessionType.UNIT.equals(sessionType) || SessionType.MEDM.equals(sessionType)) && RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType()) || SessionType.PAYM.equals(sessionType)) {
checkResults.add(new CheckResult(obligation, false));
continue;
}

View file

@ -0,0 +1,275 @@
package ru.spcex.clearing.session.stage.impl;
import java.time.Instant;
import java.time.LocalDate;
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.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.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.platform.dictionary.CurrencyPairDictionary;
import ru.spcex.clearing.component.predicate.cash.account.AccountIdCashingPredicate;
import ru.spcex.clearing.component.predicate.cash.currency.CurrencyCodePredicate;
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.Section;
import ru.spcex.platform.enumeration.Sender;
import ru.spcex.platform.enumeration.Side;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2;
public class RegistryCkBuilder implements IRegistryBuilder {
private CashV2<String, Currency> currCash;
private CashV2<Long, ClearingAccount> clrAccCash;
private Imdg<Company> companyImdg;
private Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
private Imdg<Session> sessionImdg;
private Imdg<ClearingAccount> clearingAccountImdg;
private Imdg<Currency> currencyImdg;
private Imdg<CurrencyPairSecurity> currPairSecImdg;
private Imdg<CurrencyPairDictionary> currPairDictImdg;
private TcrSearcher tcrSearcher;
private ExecutionCommon exec;
private RegistryDesignation regDsgn;
private TradingClearingRegistry ckTcr;
private RegistryCkBuilder() {
}
public static RegistryCkBuilder builder() {
return new RegistryCkBuilder();
}
public IRegistryBuilder cmpImdg(Imdg<Company> cmpImdg) {
this.companyImdg = cmpImdg;
return this;
}
public IRegistryBuilder tcrImdg(Imdg<TradingClearingRegistry> tcrImdg) {
this.tradingClearingRegistryImdg = tcrImdg;
return this;
}
public IRegistryBuilder ssnImdg(Imdg<Session> ssnImdg) {
this.sessionImdg = ssnImdg;
return this;
}
public IRegistryBuilder clAccImdg(Imdg<ClearingAccount> clAccImdg) {
this.clearingAccountImdg = clAccImdg;
return this;
}
public IRegistryBuilder currPairSecImdg(Imdg<CurrencyPairSecurity> currPairSecImdg) {
this.currPairSecImdg = currPairSecImdg;
return this;
}
public IRegistryBuilder currPairDictImdg(Imdg<CurrencyPairDictionary> currPairDictImdg) {
this.currPairDictImdg = currPairDictImdg;
return this;
}
public IRegistryBuilder currImdg(Imdg<Currency> currImdg) {
this.currencyImdg = currImdg;
return this;
}
public IRegistryBuilder tcrSearcher(TcrSearcher tcrSearcher) {
this.tcrSearcher = tcrSearcher;
return this;
}
@Override
public RegistryCkBuilder exec(ExecutionCommon exec) {
this.exec = exec;
return this;
}
@Override
public RegistryCkBuilder 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 IRegistryBuilder ckTcr(TradingClearingRegistry ckTcr) {
this.ckTcr = ckTcr;
return this;
}
@Override
public Registry build() {
ISide side = getSide(exec);
Registry reg = new Registry();
reg.setCompanyId(Sender.CK.getId());
reg.setCounterPartyId(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 = ckTcr;
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.getSingleObjectByID(exec.getSecurityId());
CurrencyPairDictionary curPairDict = null;
if (curPairSec != null) {
curPairDict = currPairDictImdg.getSingleObjectByID(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();
ImdgPredicate currPrdct = CurrencyCodePredicate
.getPredicate(curr)
.cashed(currencyImdg.predicateBuilder(), currCash);
currency = currencyImdg.getFirstObjectByPredicate(currPrdct);
reg.setSecurityId(currency.getId());
reg.setSecuritySymbol(currency.getCurrencyCode());
Optional<Account> acc = tcrSearcher.searchByTcr(tcr.getId(), 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(tcr.getId());
reg.setTradingClearingRegistry(tcr.getCode());
reg.setRegistryStatus(RegistryStatus.PROC.getKey());
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.getCompanyId());
reg.setGroupId(groupId());
reg.setSessionId(exec.getSessionId());
reg.setSessionType(sessionType());
reg.setSection(Section.CURR.getKey());
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.getSingleObjectByID(Sender.CK.getId());
}
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)) {
ImdgPredicate prdct = AccountIdCashingPredicate
.getPredicate(moneyAccountId)
.cashed(clearingAccountImdg.predicateBuilder(), clrAccCash);
ClearingAccount clearingAccount = clearingAccountImdg.getFirstObjectByPredicate(prdct);
if (clearingAccount != null) {
capacityByAccount = clearingAccount.getClearingAccountType();
}
} else if (AccountType.Info.equalsByKey(accountType)) {
capacityByAccount = RegistryCapacity.A.getKey();
}
return capacityByAccount;
}
@Override
public IRegistryBuilder currCash(CashV2<String, Currency> currCash) {
this.currCash = currCash;
return this;
}
@Override
public IRegistryBuilder clrAccCash(CashV2<Long, ClearingAccount> clrAccCash) {
this.clrAccCash = clrAccCash;
return this;
}
}

View file

@ -51,6 +51,8 @@ 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.Sender;
import ru.spcex.platform.enumeration.SessionType;
import ru.spcex.platform.enumeration.Side;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgId;
@ -65,6 +67,7 @@ import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ById;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ByIdAndString;
import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ByString;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.enumeration.IEnumKey;
/**
* LiabilitiesAndClaims
@ -92,7 +95,12 @@ public class RequirementsAndObligationCreation implements ISessionStage {
private final Imdg<Currency> currImdg;
private final TcrSearcher tcrSearcher;
private final SecuritySelector<Security> secSelector;
private SessionType sessionType;
private TradingClearingRegistry ckTcr;
public void setSessionType(SessionType sessionType) {
this.sessionType = sessionType;
}
@Autowired
public RequirementsAndObligationCreation(ImdgProvider imdgProvider) {
@ -193,6 +201,7 @@ public class RequirementsAndObligationCreation implements ISessionStage {
}
protected StageResult<?> createRegisters(List<ExecutionCommon> data, Long sessionId, Map<Long, Registry> rgsStorage) {
this.ckTcr = null;
data.sort(tradeTimeComparator.thenComparing(execIdComparator));
Map<Long, Registry> newRgss = rgsStorage != null ? rgsStorage : storageMap(data);
//см. описание к #matchExecutions
@ -266,6 +275,12 @@ public class RequirementsAndObligationCreation implements ISessionStage {
findAndUpdateOrCreate.accept(counterExec, RegistryDesignation.T, true);
findAndUpdateOrCreate.accept(counterExec, RegistryDesignation.O, true);
}
if (isCk()) {
createRegistryForCK(partyExec, RegistryDesignation.O, newRgss);
createRegistryForCK(partyExec, RegistryDesignation.T, newRgss);
createRegistryForCK(counterExec, RegistryDesignation.O, newRgss);
createRegistryForCK(counterExec, RegistryDesignation.T, newRgss);
}
}
if (rgsStorage == null) {
log.info("batch insert {} registries into map", newRgss.size());
@ -274,6 +289,48 @@ public class RequirementsAndObligationCreation implements ISessionStage {
return new StageResult<>(null, true);
}
private boolean isCk() {
return IEnumKey.contains(sessionType, SessionType.PREP, SessionType.PAYM);
}
private void createRegistryForCK(
ExecutionCommon exec,
RegistryDesignation rgsDsgn,
Map<Long, Registry> newRgss
) {
if (this.ckTcr == null) {
this.ckTcr = tcrImdg.getSingleObjectByPredicate(
tcrImdg.predicateBuilder().equals("companyId", Sender.CK.getId())
);
}
IRegistryBuilder registryBuilder = RegistryCkBuilder.builder();
Registry newRegister = registryBuilder
//cashes
.dpAccCash(cash.dpAccCash)
.currCash(cash.currCash)
.clrAccCash(cash.clrAccCash)
//imdg
.cmpImdg(cmpImdg)
.tcrImdg(tcrImdg)
.accImdg(accImdg)
.ssnImdg(ssnImdg)
.clAccImdg(clAccImdg)
.dpAccImdg(dpAccImdg)
.currPairSecImdg(currPairSecImdg)
.currPairDictImdg(currPairDictImdg)
.currImdg(currImdg)
.tcrSearcher(tcrSearcher)
.secSelector(secSelector)
.imdg(imdgProvider)
.ckTcr(ckTcr)
.exec(exec)
.registryDesignation(rgsDsgn)
.returnDeposit(false)
.build();
newRegister.setId(idGen.nextId());
newRgss.put(newRegister.getId(), newRegister);
log.debug("execution id {}: created rgs.id={}", exec, newRegister.getId());
}
private Optional<Registry> findReg(ExecutionCommon exec, RegistryDesignation des) {
ISide side = getSide(exec);
@ -390,9 +447,16 @@ public class RequirementsAndObligationCreation implements ISessionStage {
invalid = String.format("exchangeExecutionId %d and %d not equal", exec1.getExchangeExecutionId(), exec2.getExchangeExecutionId());
} else if (Objects.equals(getSide(exec1), getSide(exec2))) {
invalid = String.format("side %s and %s equal, must be opposite", getSide(exec1), getSide(exec1));
} else if (!Objects.equals(exec1.getCompanyId(), exec2.getCounterPartyId()) || !Objects.equals(exec1.getCounterPartyId(), exec2.getCompanyId())) {
} else if (!isCk()
&& (!Objects.equals(exec1.getCompanyId(), exec2.getCounterPartyId())
|| !Objects.equals(exec1.getCounterPartyId(), exec2.getCompanyId()))) {
invalid = String.format("Execution#id(%d)#companyId(%d)#counterPartyId(%d), Execution#id(%d)#companyId(%d)#counterPartyId(%d)",
exec1.getId(), exec1.getCompanyId(), exec1.getCounterPartyId(), exec2.getId(), exec2.getCompanyId(), exec2.getCounterPartyId());
exec1.getId(), exec1.getCompanyId(), exec1.getCounterPartyId(), exec2.getId(), exec2.getCompanyId(), exec2.getCounterPartyId());
} else if (isCk()
&& !Objects.equals(exec1.getTradingDate(), exec2.getTradingDate())) {
invalid = String.format("[Execution#id(%d)#tradingDate=%s, Execution#id(%d)#tradingDate=%s] exchangeExecutionId=%d; tradingDate must be equal",
exec1.getId(), exec1.getTradingDate(),
exec2.getId(), exec2.getTradingDate(), exec2.getExchangeExecutionId());
}
if (invalid != null) {
log.error("FATAL couldn't match Execution#id({}) with Execution#id({}) error: {}", exec1.getId(), exec2.getId(), invalid);

View file

@ -0,0 +1,14 @@
package ru.spcex.clearing.util;
import ru.spcex.platform.utils.text.TextUtil;
public class NumberUtils {
public static Long safeCast(String s) {
if (TextUtil.isEmpty(s)) return null;
try {
return Long.parseLong(s);
} catch (NumberFormatException e) {
return null;
}
}
}

View file

@ -22,3 +22,5 @@ clearing-service.kafka-producer.buffer-memory=33554432
clearing-service.session-stage.inspection-gateway-timeout=60
clearing-service.scheduler.check-payment-instruction=*/5 * * * * *
clearing-service.balance-check-omt=false

View file

@ -8,12 +8,12 @@
<name>clearing-validation</name>
<description>Clearing-module, dependency version of platform-utils</description>
<packaging>jar</packaging>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<properties>
@ -35,13 +35,13 @@
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>classes</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>dictionary</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>

View file

@ -5,7 +5,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -7,12 +7,12 @@
<artifactId>db-scripts</artifactId>
<name>db-scripts</name>
<description>db-scripts for PostgreSQL</description>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<build>

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
-- DB version: 3.13
-- DB version: 3.15
/* Dictionaries */
-- allowed - Справочник признаков допустимости использования объектов
@ -2381,7 +2381,7 @@ GRANT ALL PRIVILEGES ON TABLE RELATION_HISTORY TO clearing;
-- bankAccount - Счета вывода средств
DROP TABLE IF EXISTS BANK_ACCOUNT;
CREATE TABLE BANK_ACCOUNT(ACCOUNT_ID bigint, BANK_IDENTIFICATION_CODE varchar(255), BANK_NAME varchar(255), CORRESPONDENT_ACCOUNT varchar(255), CORRESPONDENT_ACCOUNT_NAME varchar(255), CURRENCY varchar(4), DESTINATION varchar(255), IBAN varchar(255), INTERNATIONAL_TRANSFER_SIGN varchar(4), SWIFT_CODE varchar(255), TAXPAYER_IDENTIFICATION_NUMBER varchar(255), TAX_REGISTRATION_REASON_CODE varchar(255), ACCOUNT varchar(50), COMPANY_ID bigint, ID bigint PRIMARY KEY, INTERMEDIARY_SWIFT_CODE varchar(255));
CREATE TABLE BANK_ACCOUNT(ACCOUNT_ID bigint, BANK_IDENTIFICATION_CODE varchar(255), BANK_NAME varchar(255), CORRESPONDENT_ACCOUNT varchar(255), CORRESPONDENT_ACCOUNT_NAME varchar(255), CURRENCY varchar(4), DESTINATION varchar(255), IBAN varchar(255), INTERNATIONAL_TRANSFER_SIGN varchar(4), SWIFT_CODE varchar(255), TAXPAYER_IDENTIFICATION_NUMBER varchar(255), TAX_REGISTRATION_REASON_CODE varchar(255), ACCOUNT varchar(50), COMPANY_ID bigint, ID bigint PRIMARY KEY, INTERMEDIARY_SWIFT_CODE varchar(255), NAME varchar(255), ADDRESS varchar(255), BANK_ADDRESS varchar(255), BANK_SWIFT_CODE varchar(12), BANK_ACCOUNT varchar(35), BANK_NAME1 varchar(255), BANK_ADDRESS1 varchar(255), BANK_ACCOUNT1 varchar(35), BANK_NAME2 varchar(255), BANK_ADDRESS2 varchar(255), INTERMEDIARY_SWIFT_CODE2 varchar(12), BANK_ACCOUNT2 varchar(35), PERSONAL_ACCOUNT varchar(20), BUDGET_CLASSIFICATION_CODE varchar(20), OKTMO varchar(20));
COMMENT ON TABLE BANK_ACCOUNT IS 'Счета вывода средств';
COMMENT ON COLUMN BANK_ACCOUNT.ACCOUNT_ID IS 'Идентификатор счета (linked to account)';
@ -2416,12 +2416,42 @@ COMMENT ON COLUMN BANK_ACCOUNT.ID IS 'Идентификатор записи';
COMMENT ON COLUMN BANK_ACCOUNT.INTERMEDIARY_SWIFT_CODE IS 'Код SWIFT посредника';
COMMENT ON COLUMN BANK_ACCOUNT.NAME IS 'Наименование владельца счета';
COMMENT ON COLUMN BANK_ACCOUNT.ADDRESS IS 'Адрес владельца счета';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ADDRESS IS 'Место нахождения банка получателя средств';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_SWIFT_CODE IS 'SWIFT банка получателя средств';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ACCOUNT IS 'Номер счета банка получателя средств';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_NAME1 IS 'Наименование банка-посредника 1';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ADDRESS1 IS 'Место нахождения банка-посредника 1';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ACCOUNT1 IS 'Номер счета банка-посредника 1';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_NAME2 IS 'Наименование банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ADDRESS2 IS 'Место нахождения банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT.INTERMEDIARY_SWIFT_CODE2 IS 'SWIFT банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ACCOUNT2 IS 'Номер счета банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT.PERSONAL_ACCOUNT IS 'Лицевой счет получателя';
COMMENT ON COLUMN BANK_ACCOUNT.BUDGET_CLASSIFICATION_CODE IS 'КБК';
COMMENT ON COLUMN BANK_ACCOUNT.OKTMO IS 'ОКТМО получателя средств';
GRANT ALL PRIVILEGES ON TABLE BANK_ACCOUNT TO clearing;
-- History log of bankAccount - Счета вывода средств
DROP TABLE IF EXISTS BANK_ACCOUNT_HISTORY;
CREATE TABLE BANK_ACCOUNT_HISTORY(BANK_ACCOUNT_ID BIGINT NOT NULL, EVENT_TIME timestamp, EVENT_USER_ID BIGINT, EVENT_TYPE VARCHAR(4), ACCOUNT_ID bigint, BANK_IDENTIFICATION_CODE varchar(255), BANK_NAME varchar(255), CORRESPONDENT_ACCOUNT varchar(255), CORRESPONDENT_ACCOUNT_NAME varchar(255), CURRENCY varchar(4), DESTINATION varchar(255), IBAN varchar(255), INTERNATIONAL_TRANSFER_SIGN varchar(4), SWIFT_CODE varchar(255), TAXPAYER_IDENTIFICATION_NUMBER varchar(255), TAX_REGISTRATION_REASON_CODE varchar(255), ACCOUNT varchar(50), COMPANY_ID bigint, ID bigint PRIMARY KEY, INTERMEDIARY_SWIFT_CODE varchar(255));
CREATE TABLE BANK_ACCOUNT_HISTORY(BANK_ACCOUNT_ID BIGINT NOT NULL, EVENT_TIME timestamp, EVENT_USER_ID BIGINT, EVENT_TYPE VARCHAR(4), ACCOUNT_ID bigint, BANK_IDENTIFICATION_CODE varchar(255), BANK_NAME varchar(255), CORRESPONDENT_ACCOUNT varchar(255), CORRESPONDENT_ACCOUNT_NAME varchar(255), CURRENCY varchar(4), DESTINATION varchar(255), IBAN varchar(255), INTERNATIONAL_TRANSFER_SIGN varchar(4), SWIFT_CODE varchar(255), TAXPAYER_IDENTIFICATION_NUMBER varchar(255), TAX_REGISTRATION_REASON_CODE varchar(255), ACCOUNT varchar(50), COMPANY_ID bigint, ID bigint PRIMARY KEY, INTERMEDIARY_SWIFT_CODE varchar(255), NAME varchar(255), ADDRESS varchar(255), BANK_ADDRESS varchar(255), BANK_SWIFT_CODE varchar(12), BANK_ACCOUNT varchar(35), BANK_NAME1 varchar(255), BANK_ADDRESS1 varchar(255), BANK_ACCOUNT1 varchar(35), BANK_NAME2 varchar(255), BANK_ADDRESS2 varchar(255), INTERMEDIARY_SWIFT_CODE2 varchar(12), BANK_ACCOUNT2 varchar(35), PERSONAL_ACCOUNT varchar(20), BUDGET_CLASSIFICATION_CODE varchar(20), OKTMO varchar(20));
COMMENT ON TABLE BANK_ACCOUNT_HISTORY IS 'История изменений таблицы bankAccount';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT_ID IS 'Идентификатор записи в таблице BANK_ACCOUNT';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.EVENT_TIME IS 'Дата и время изменения';
@ -2460,6 +2490,36 @@ COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.ID IS 'Идентификатор зап
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.INTERMEDIARY_SWIFT_CODE IS 'Код SWIFT посредника';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.NAME IS 'Наименование владельца счета';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.ADDRESS IS 'Адрес владельца счета';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ADDRESS IS 'Место нахождения банка получателя средств';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_SWIFT_CODE IS 'SWIFT банка получателя средств';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT IS 'Номер счета банка получателя средств';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_NAME1 IS 'Наименование банка-посредника 1';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ADDRESS1 IS 'Место нахождения банка-посредника 1';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT1 IS 'Номер счета банка-посредника 1';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_NAME2 IS 'Наименование банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ADDRESS2 IS 'Место нахождения банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.INTERMEDIARY_SWIFT_CODE2 IS 'SWIFT банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT2 IS 'Номер счета банка-посредника 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.PERSONAL_ACCOUNT IS 'Лицевой счет получателя';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BUDGET_CLASSIFICATION_CODE IS 'КБК';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.OKTMO IS 'ОКТМО получателя средств';
GRANT ALL PRIVILEGES ON TABLE BANK_ACCOUNT_HISTORY TO clearing;
-- informationAccount - Регистр КС
@ -2790,7 +2850,7 @@ GRANT ALL PRIVILEGES ON TABLE SESSION_HISTORY TO clearing;
-- sTrades - Сделки из Торговой системы
DROP TABLE IF EXISTS S_TRADES;
CREATE TABLE S_TRADES(ID bigint PRIMARY KEY, CREATED_AT timestamp, UPDATED_AT timestamp, TRADE_NUM bigint, OPERATION varchar(40), CLASS_CODE varchar(255), TRADE_DATE date, SEC_CODE varchar(255), ACCRUEDINT numeric(72,18), ACCRUEDINT2 numeric(72,18), LOWER_DISCOUNT numeric(72,18), ORDER_NUM bigint, PRICE numeric(72,18), PRICE2 numeric(72,18), REPO_RATE numeric(72,18), REPO_VALUE numeric(72,18), REPO2_VALUE numeric(72,18), START_DISCOUNT numeric(72,18), TS_COMMISSION numeric(72,18), UPPER_DISCOUNT numeric(72,18), VALUE numeric(72,18), YIELD numeric(72,18), QTY numeric(72,18), QTY_PCS numeric(72,18), TRADE_DATE_TIME timestamp, REPO_TERM bigint, CLEARING_COMMISSION numeric(72,18), EXCHANGE_COMMISSION numeric(72,18), TECH_CENTER_COMMISSION numeric(72,18), ACCOUNT varchar(50), BROKER_REF varchar(34), CLIENT_CODE varchar(255), SETTLE_CODE varchar(50), USER_ID varchar(32), EXCHANGE_CODE varchar(64), FIRM_ID varchar(255), FIRM_NAME varchar(255), CP_FIRM_ID varchar(255), CP_FIRM_NAME varchar(255), CLASS_NAME varchar(255), SEC_NAME varchar(255), SETTLE_DATE date, SETTLE_CURRENCY varchar(4), TRADE_CURRENCY varchar(4), TRADE_TIME_MS bigint, BANK_ACC_ID varchar(12), SECTION varchar(4));
CREATE TABLE S_TRADES(ID bigint PRIMARY KEY, CREATED_AT timestamp, UPDATED_AT timestamp, TRADE_NUM bigint, OPERATION varchar(40), CLASS_CODE varchar(255), TRADE_DATE date, SEC_CODE varchar(255), ACCRUEDINT numeric(72,18), ACCRUEDINT2 numeric(72,18), LOWER_DISCOUNT numeric(72,18), ORDER_NUM bigint, PRICE numeric(72,18), PRICE2 numeric(72,18), REPO_RATE numeric(72,18), REPO_VALUE numeric(72,18), REPO2_VALUE numeric(72,18), START_DISCOUNT numeric(72,18), TS_COMMISSION numeric(72,18), UPPER_DISCOUNT numeric(72,18), VALUE numeric(72,18), YIELD numeric(72,18), QTY numeric(72,18), QTY_PCS numeric(72,18), TRADE_DATE_TIME timestamp, REPO_TERM bigint, CLEARING_COMMISSION numeric(72,18), EXCHANGE_COMMISSION numeric(72,18), TECH_CENTER_COMMISSION numeric(72,18), ACCOUNT varchar(50), BROKER_REF varchar(34), CLIENT_CODE varchar(255), SETTLE_CODE varchar(50), USER_ID varchar(32), EXCHANGE_CODE varchar(64), FIRM_ID varchar(255), FIRM_NAME varchar(255), CP_FIRM_ID varchar(255), CP_FIRM_NAME varchar(255), CLASS_NAME varchar(255), SEC_NAME varchar(255), SETTLE_DATE date, SETTLE_CURRENCY varchar(4), TRADE_CURRENCY varchar(4), TRADE_TIME_MS bigint, BANK_ACC_ID varchar(12), SECTION varchar(4), KIND varchar(64), LINKED_TRADE bigint);
COMMENT ON TABLE S_TRADES IS 'Сделки из Торговой системы';
COMMENT ON COLUMN S_TRADES.ID IS 'Идентификатор записи';
@ -2887,6 +2947,10 @@ COMMENT ON COLUMN S_TRADES.BANK_ACC_ID IS 'Идентификатор расче
COMMENT ON COLUMN S_TRADES.SECTION IS 'Код наименования секции (linked to section)';
COMMENT ON COLUMN S_TRADES.KIND IS 'Вид сделки';
COMMENT ON COLUMN S_TRADES.LINKED_TRADE IS 'Номер витринной сделки в торговой системе для сделок';
GRANT ALL PRIVILEGES ON TABLE S_TRADES TO clearing;
-- executionDeposit - Сделки на секции МКР
@ -4505,7 +4569,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, ACC_TYPE 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 'Идентификатор записи';
@ -5117,8 +5181,51 @@ COMMENT ON COLUMN BLACKLIST_MARKET.SECTION IS 'Секция';
GRANT ALL PRIVILEGES ON TABLE BLACKLIST_MARKET TO clearing;
CREATE TABLE RISK_PARAMETER
(
ID BIGINT PRIMARY KEY,
VALUE numeric(72,18),
SETTLEMENT_TYPE VARCHAR(4),
CURRENCY_PAIR VARCHAR(12),
CURRENCY_PAIR_ID BIGINT,
CREATED_AT timestamp,
UPDATED_AT timestamp,
WORKFLOW_STATUS VARCHAR(4)
);
COMMENT ON TABLE RISK_PARAMETER IS 'Риск-параметры';
COMMENT ON COLUMN RISK_PARAMETER.ID IS 'Идентификатор записи';
COMMENT ON COLUMN RISK_PARAMETER.VALUE IS 'Ставка ';
COMMENT ON COLUMN RISK_PARAMETER.SETTLEMENT_TYPE IS 'Код расчета';
COMMENT ON COLUMN RISK_PARAMETER.CURRENCY_PAIR IS 'Код валютной пары';
COMMENT ON COLUMN RISK_PARAMETER.CURRENCY_PAIR_ID IS 'Идентификатор валютной пары';
COMMENT ON COLUMN RISK_PARAMETER.CREATED_AT IS 'Время создания записи';
COMMENT ON COLUMN RISK_PARAMETER.UPDATED_AT IS 'Время изменения записи';
COMMENT ON COLUMN RISK_PARAMETER.WORKFLOW_STATUS IS 'Статус';
GRANT ALL PRIVILEGES ON TABLE RISK_PARAMETER TO clearing;
CREATE TABLE RATES
(
ID BIGINT PRIMARY KEY,
VALUE numeric(72, 18),
VALUE_DATE date,
CURRENCY VARCHAR(4),
CURRENCY_ID BIGINT,
CREATED_AT timestamp,
UPDATED_AT timestamp,
WORKFLOW_STATUS VARCHAR(4)
);
COMMENT ON TABLE RATES IS 'Расчетные курсы';
COMMENT ON COLUMN RATES.ID IS 'Идентификатор записи';
COMMENT ON COLUMN RATES.VALUE IS 'Расчетный курс';
COMMENT ON COLUMN RATES.VALUE_DATE IS 'Дата, на которую расчетный курс';
COMMENT ON COLUMN RATES.CURRENCY IS 'Код валюты';
COMMENT ON COLUMN RATES.CURRENCY_ID IS 'Идентификатор валюты';
COMMENT ON COLUMN RATES.CREATED_AT IS 'Время создания записи';
COMMENT ON COLUMN RATES.UPDATED_AT IS 'Время изменения записи';
COMMENT ON COLUMN RATES.WORKFLOW_STATUS IS 'Статус';
GRANT ALL PRIVILEGES ON TABLE RATES TO clearing;
/* views */
-- Data types
INSERT INTO DB_VERSION(ID, VERSION) values (1, '3.13') ON CONFLICT (ID) DO UPDATE SET VERSION = EXCLUDED.VERSION
INSERT INTO DB_VERSION(ID, VERSION) values (1, '3.15') ON CONFLICT (ID) DO UPDATE SET VERSION = EXCLUDED.VERSION

View file

@ -1,7 +1,3 @@
-- DB version: 3.13
-- DATA version: 3.13.0.95
/* Dictionaries */
INSERT INTO ALLOWED_DICTIONARY(ID, CODE, NAME) values (1, 'ALWD', 'Разрешено') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -188,6 +184,8 @@ INSERT INTO COMPANY_ROLE_DICTIONARY(ID, CODE, NAME) values (6, 'CLRM', 'Учас
INSERT INTO COMPANY_ROLE_DICTIONARY(ID, CODE, NAME) values (7, 'ODEP', 'Участник расчетов по открытым депозитным счетам на секции МКР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO COMPANY_ROLE_DICTIONARY(ID, CODE, NAME) values (8, 'CLCC', 'Центральный контрагент') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO CURRENCY_CODE_DICTIONARY(ID, CODE, NAME) values (643, 'RUB', 'Российский рубль') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO CURRENCY_CODE_DICTIONARY(ID, CODE, NAME) values (840, 'USD', 'Доллар США') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -483,6 +481,7 @@ INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (30, 'CBRR', 'Загрузк
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (31, 'MTCR', 'Формирование файлов с МТКР') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (32, 'LIMC', 'Выгрузка в Торговую систему остатков по валюте (отправка lim)') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO TASK_DICTIONARY(ID, CODE, NAME) values (33, 'GREC', 'Формирование отчетности ЦК') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO TASK_STATUS_DICTIONARY(ID, CODE, NAME) values (1, 'ACTV', 'Активна') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -500,7 +499,9 @@ INSERT INTO PARENT_DICTIONARY(ID, CODE, NAME) values (2, 'PLNR', 'Расписа
INSERT INTO PARENT_DICTIONARY(ID, CODE, NAME) values (3, 'CLND', 'Календарь') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO CURRENCY_SETTLEMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (1, 'TOD', 'Поставка сегодня') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO CURRENCY_SETTLEMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (1, 'T0', 'Сегодня') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO CURRENCY_SETTLEMENT_TYPE_DICTIONARY(ID, CODE, NAME) values (2, 'T1', 'Завтра') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO MAJOR_SIGN_DICTIONARY(ID, CODE, NAME) values (1, 'CONV', 'Конвертируемая валюта') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -556,6 +557,10 @@ INSERT INTO SESSION_TYPE_DICTIONARY(ID, CODE, NAME) values (9, 'CURR', 'Валю
INSERT INTO SESSION_TYPE_DICTIONARY(ID, CODE, NAME) values (10, 'UNIT', 'Клиринговая сессия Т0') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO SESSION_TYPE_DICTIONARY(ID, CODE, NAME) values (11, 'PREP', 'Предварительная сессия с ЦК') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO SESSION_TYPE_DICTIONARY(ID, CODE, NAME) values (12, 'PAYM', 'Расчетная сессия с ЦК') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO MONEY_FLOW_SIDE_DICTIONARY(ID, CODE, NAME) values (1, 'BUY', 'Привлечь') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO MONEY_FLOW_SIDE_DICTIONARY(ID, CODE, NAME) values (2, 'SELL', 'Разместить') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -719,6 +724,8 @@ INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1021, 'SECR', 'Инф
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1022, 'SECR', 'Информация об инструментах Денежного рынка на режимах изменяется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1023, 'SECR', 'Информация об инструментах Денежного рынка на режимах блокируется автоматически.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1024, 'SECR', 'Параметр для инструмента %s на дату уже существует.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (1025, 'SECR', 'Расчетный курс для валюты %s на дату уже существует.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (2000, 'UTIL', 'Общая ошибка модуля utility-service.') ON CONFLICT (ID) DO UPDATE SET CODE = EXCLUDED.CODE, NAME = EXCLUDED.NAME;
@ -1024,4 +1031,4 @@ INSERT INTO ERROR_CODE_DICTIONARY(ID, CODE, NAME) values (10001, 'TRDI', 'Сде
/* Business objects */
INSERT INTO DB_VERSION(ID, DICTIONARY_VERSION) values (1, '3.13.0.95') ON CONFLICT (ID) DO UPDATE SET DICTIONARY_VERSION = EXCLUDED.DICTIONARY_VERSION
INSERT INTO DB_VERSION(ID, DICTIONARY_VERSION) values (1, '3.15.0.96') ON CONFLICT (ID) DO UPDATE SET DICTIONARY_VERSION = EXCLUDED.DICTIONARY_VERSION

View file

@ -0,0 +1,119 @@
-- DB version: 3.14 -> 3.15
-- == alter exist tables ==
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS NAME varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS ADDRESS varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_ADDRESS varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_SWIFT_CODE varchar(12);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_ACCOUNT varchar(35);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_NAME1 varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_ADDRESS1 varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_ACCOUNT1 varchar(35);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_NAME2 varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_ADDRESS2 varchar(255);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS INTERMEDIARY_SWIFT_CODE2 varchar(12);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BANK_ACCOUNT2 varchar(35);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS PERSONAL_ACCOUNT varchar(20);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS BUDGET_CLASSIFICATION_CODE varchar(20);
ALTER TABLE BANK_ACCOUNT ADD COLUMN IF NOT EXISTS OKTMO varchar(20);
COMMENT ON COLUMN BANK_ACCOUNT.NAME IS 'Íàèìåíîâàíèå âëàäåëüöà ñ÷åòà';
COMMENT ON COLUMN BANK_ACCOUNT.ADDRESS IS 'Àäðåñ âëàäåëüöà ñ÷åòà (ïîëó÷àòåëÿ ñðåäñòâ)';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ADDRESS IS 'Ìåñòî íàõîæäåíèÿ áàíêà ïîëó÷àòåëÿ ñðåäñòâ';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_SWIFT_CODE IS 'SWIFT áàíêà ïîëó÷àòåëÿ ñðåäñòâ';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ACCOUNT IS 'Íîìåð ñ÷åòà áàíêà ïîëó÷àòåëÿ ñðåäñòâ';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_NAME1 IS 'Íàèìåíîâàíèå áàíêà-ïîñðåäíèêà 1 (ïðè íàëè÷èè)';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ADDRESS1 IS 'Ìåñòî íàõîæäåíèÿ áàíêà-ïîñðåäíèêà 1 (ïðè íàëè÷èè)';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ACCOUNT1 IS 'Íîìåð ñ÷åòà áàíêà-ïîñðåäíèêà 1';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_NAME2 IS 'Íàèìåíîâàíèå áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ADDRESS2 IS 'Ìåñòî íàõîæäåíèÿ áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT.INTERMEDIARY_SWIFT_CODE2 IS 'SWIFT áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT.BANK_ACCOUNT2 IS 'Íîìåð ñ÷åòà áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT.PERSONAL_ACCOUNT IS 'Ëèöåâîé ñ÷åò ïîëó÷àòåëÿ';
COMMENT ON COLUMN BANK_ACCOUNT.BUDGET_CLASSIFICATION_CODE IS 'ÊÁÊ';
COMMENT ON COLUMN BANK_ACCOUNT.OKTMO IS 'ÎÊÒÌÎ ïîëó÷àòåëÿ ñðåäñòâ';
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS NAME varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS ADDRESS varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_ADDRESS varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_SWIFT_CODE varchar(12);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_ACCOUNT varchar(35);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_NAME1 varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_ADDRESS1 varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_ACCOUNT1 varchar(35);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_NAME2 varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_ADDRESS2 varchar(255);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS INTERMEDIARY_SWIFT_CODE2 varchar(12);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BANK_ACCOUNT2 varchar(35);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS PERSONAL_ACCOUNT varchar(20);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS BUDGET_CLASSIFICATION_CODE varchar(20);
ALTER TABLE BANK_ACCOUNT_HISTORY ADD COLUMN IF NOT EXISTS OKTMO varchar(20);
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.NAME IS 'Íàèìåíîâàíèå âëàäåëüöà ñ÷åòà';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.ADDRESS IS 'Àäðåñ âëàäåëüöà ñ÷åòà (ïîëó÷àòåëÿ ñðåäñòâ)';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ADDRESS IS 'Ìåñòî íàõîæäåíèÿ áàíêà ïîëó÷àòåëÿ ñðåäñòâ';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_SWIFT_CODE IS 'SWIFT áàíêà ïîëó÷àòåëÿ ñðåäñòâ';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT IS 'Íîìåð ñ÷åòà áàíêà ïîëó÷àòåëÿ ñðåäñòâ';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_NAME1 IS 'Íàèìåíîâàíèå áàíêà-ïîñðåäíèêà 1 (ïðè íàëè÷èè)';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ADDRESS1 IS 'Ìåñòî íàõîæäåíèÿ áàíêà-ïîñðåäíèêà 1 (ïðè íàëè÷èè)';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT1 IS 'Íîìåð ñ÷åòà áàíêà-ïîñðåäíèêà 1';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_NAME2 IS 'Íàèìåíîâàíèå áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ADDRESS2 IS 'Ìåñòî íàõîæäåíèÿ áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.INTERMEDIARY_SWIFT_CODE2 IS 'SWIFT áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BANK_ACCOUNT2 IS 'Íîìåð ñ÷åòà áàíêà-ïîñðåäíèêà 2';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.PERSONAL_ACCOUNT IS 'Ëèöåâîé ñ÷åò ïîëó÷àòåëÿ';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.BUDGET_CLASSIFICATION_CODE IS 'ÊÁÊ';
COMMENT ON COLUMN BANK_ACCOUNT_HISTORY.OKTMO IS 'ÎÊÒÌÎ ïîëó÷àòåëÿ ñðåäñòâ';
ALTER TABLE S_TRADES ADD COLUMN IF NOT EXISTS KIND varchar(64);
ALTER TABLE S_TRADES ADD COLUMN IF NOT EXISTS LINKED_TRADE bigint;
COMMENT ON COLUMN S_TRADES.KIND IS 'Âèä ñäåëêè';
COMMENT ON COLUMN S_TRADES.LINKED_TRADE IS 'Íîìåð âèòðèííîé ñäåëêè â òîðãîâîé ñèñòåìå äëÿ ñäåëîê';
DROP TABLE IF EXISTS RISK_PARAMETER;
CREATE TABLE RISK_PARAMETER
(
ID BIGINT PRIMARY KEY,
VALUE numeric(72,18),
SETTLEMENT_TYPE VARCHAR(4),
CURRENCY_PAIR VARCHAR(12),
CURRENCY_PAIR_ID BIGINT,
CREATED_AT timestamp,
UPDATED_AT timestamp,
WORKFLOW_STATUS VARCHAR(4)
);
COMMENT ON TABLE RISK_PARAMETER IS 'Ðèñê-ïàðàìåòðû';
COMMENT ON COLUMN RISK_PARAMETER.ID IS 'Èäåíòèôèêàòîð çàïèñè';
COMMENT ON COLUMN RISK_PARAMETER.VALUE IS 'Ñòàâêà';
COMMENT ON COLUMN RISK_PARAMETER.SETTLEMENT_TYPE IS 'Êîä ðàñ÷åòà';
COMMENT ON COLUMN RISK_PARAMETER.CURRENCY_PAIR IS 'Êîä âàëþòíîé ïàðû';
COMMENT ON COLUMN RISK_PARAMETER.CURRENCY_PAIR_ID IS 'Èäåíòèôèêàòîð âàëþòíîé ïàðû';
COMMENT ON COLUMN RISK_PARAMETER.CREATED_AT IS 'Âðåìÿ ñîçäàíèÿ çàïèñè';
COMMENT ON COLUMN RISK_PARAMETER.UPDATED_AT IS 'Âðåìÿ èçìåíåíèÿ çàïèñè';
COMMENT ON COLUMN RISK_PARAMETER.WORKFLOW_STATUS IS 'Ñòàòóñ';
GRANT ALL PRIVILEGES ON TABLE RISK_PARAMETER TO clearing;
DROP TABLE IF EXISTS RATES;
CREATE TABLE RATES
(
ID BIGINT PRIMARY KEY,
VALUE numeric(72, 18),
VALUE_DATE date,
CURRENCY VARCHAR(4),
CURRENCY_ID BIGINT,
CREATED_AT timestamp,
UPDATED_AT timestamp,
WORKFLOW_STATUS VARCHAR(4)
);
COMMENT ON TABLE RATES IS 'Ðàñ÷åòíûå êóðñû';
COMMENT ON COLUMN RATES.ID IS 'Èäåíòèôèêàòîð çàïèñè';
COMMENT ON COLUMN RATES.VALUE IS 'Ðàñ÷åòíûé êóðñ';
COMMENT ON COLUMN RATES.VALUE_DATE IS 'Äàòà, íà êîòîðóþ ðàñ÷åòíûé êóðñ';
COMMENT ON COLUMN RATES.CURRENCY IS 'Êîä âàëþòû';
COMMENT ON COLUMN RATES.CURRENCY_ID IS 'Èäåíòèôèêàòîð âàëþòû';
COMMENT ON COLUMN RATES.CREATED_AT IS 'Âðåìÿ ñîçäàíèÿ çàïèñè';
COMMENT ON COLUMN RATES.UPDATED_AT IS 'Âðåìÿ èçìåíåíèÿ çàïèñè';
COMMENT ON COLUMN RATES.WORKFLOW_STATUS IS 'Ñòàòóñ';
GRANT ALL PRIVILEGES ON TABLE RATES TO clearing;
INSERT INTO DB_VERSION(ID, VERSION) values (1, '3.15') ON CONFLICT (ID) DO UPDATE SET VERSION = EXCLUDED.VERSION

View file

@ -7,12 +7,12 @@
<artifactId>dbf-exporter</artifactId>
<name>dbf-exporter</name>
<description>DBF exporter for DBF files</description>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<dependencies>

View file

@ -1,11 +1,10 @@
package ru.spcex.clearing.dbf.exporter.logic.data;
import ru.spcex.clearing.dbf.exporter.logic.data.enums.StageResult;
import ru.spcex.clearing.dbf.exporter.logic.data.enums.Table;
import java.io.File;
import java.time.LocalDateTime;
import java.util.UUID;
import ru.spcex.clearing.dbf.exporter.logic.data.enums.StageResult;
import ru.spcex.clearing.dbf.exporter.logic.data.enums.Table;
/**
* Контейнер для передачи результата между стадиями
@ -19,13 +18,15 @@ public class ResultContainer {
private StageResult lastStageResult;
private LocalDateTime registrationDateTime;
private String memberCode;
private String section;
protected ResultContainer() {}
public static ResultContainer createNewTask(Table tableForExport) {
public static ResultContainer createNewTask(Table tableForExport, String section) {
ResultContainer container = new ResultContainer();
container.tableForExport = tableForExport;
container.uuid = UUID.randomUUID();
container.section = section;
return container;
}
@ -92,4 +93,8 @@ public class ResultContainer {
public void setMemberCode(String memberCode) {
this.memberCode = memberCode;
}
public String getSection() {
return section;
}
}

View file

@ -1,19 +1,14 @@
package ru.spcex.clearing.dbf.exporter.logic.data.enums;
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.integration.sftp.session.SftpFileInfo;
import ru.spcex.clearing.dbf.exporter.logic.data.ResultContainer;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import static ru.spcex.clearing.dbf.exporter.logic.stages.PrepareDBFFile.SECTION;
import static ru.spcex.clearing.dbf.exporter.logic.stages.PrepareDBFFile.outDir;
public enum FilenameTemplate {
@ -66,7 +61,7 @@ public enum FilenameTemplate {
result.append(File.separator);
result.append(resultContainer.getTableForExport().getFilePrefix().toUpperCase(Locale.ROOT));
result.append('_');
result.append(SECTION);
result.append(resultContainer.getSection());
return result;
}

View file

@ -26,7 +26,6 @@ import ru.spcex.clearing.dbf.exporter.logic.data.enums.Table;
*/
@Component
public class PrepareDBFFile extends Stage implements InitializingBean {
public static final String SECTION = "S";
private final ExportDBFServiceSettings settings;
public static String outDir;
private final SFTPConfig.DbfGateway gateway;

View file

@ -1,9 +1,12 @@
package ru.spcex.clearing.dbf.exporter.services;
import java.util.Arrays;
import java.util.Optional;
import org.apache.kafka.clients.consumer.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.dbf.exporter.logic.Processor;
import ru.spcex.clearing.dbf.exporter.logic.data.ResultContainer;
@ -17,22 +20,22 @@ import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.platform.enumeration.Task;
import ru.spcex.platform.imdg.api.ImdgProvider;
import java.util.Arrays;
import java.util.Optional;
@Service
public class CommandService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final ImdgProvider imdgProvider;
private final Processor processor;
private final String section;
public CommandService(Consumer<String, Object> kafkaQueue,
ImdgProvider imdgProvider,
Processor processor) {
Processor processor,
@Value("${export-dbf-service.section:S}") String section) {
super(kafkaQueue);
this.imdgProvider = imdgProvider;
this.processor = processor;
this.section = section;
}
@Override
@ -79,7 +82,7 @@ public class CommandService extends QueueConsumer implements InitializingBean {
if (tableForExport.isEmpty()) {
throw new IllegalStateException(String.format("Unsupported table prefix: %s", request.getNameOfTable()));
}
ResultContainer resultContainer = ResultContainer.createNewTask(tableForExport.get());
ResultContainer resultContainer = ResultContainer.createNewTask(tableForExport.get(), section);
resultContainer.setGroupId(request.getSdfGroupId());
resultContainer.setSourceName(request.getFileName());
processor.process(resultContainer);
@ -87,7 +90,7 @@ public class CommandService extends QueueConsumer implements InitializingBean {
private void processSpecial(Table table, BaseRequest<SdfClearingRequest> systemRequest) {
SdfClearingRequest request = systemRequest.getRequestPayload();
ResultContainer resultContainer = ResultContainer.createNewTask(table);
ResultContainer resultContainer = ResultContainer.createNewTask(table, section);
resultContainer.setGroupId(request.getGroupId());
resultContainer.setSourceName(null);
processor.process(resultContainer);
@ -96,7 +99,7 @@ public class CommandService extends QueueConsumer implements InitializingBean {
private void processByLauncher(Table table, BaseRequest<LauncherCommandRequest> systemRequest) {
LauncherCommandRequest request = systemRequest.getRequestPayload();
log.info("RequestId={}, LauncherCommandRequest task={}. Table {}", systemRequest.getId(), request.getTaskName(), table);
ResultContainer resultContainer = ResultContainer.createNewTask(table);
ResultContainer resultContainer = ResultContainer.createNewTask(table, section);
resultContainer.setGroupId(null);
resultContainer.setSourceName(null);
processor.process(resultContainer);

View file

@ -30,3 +30,5 @@ export-dbf-service.kafka-producer.retries=0
export-dbf-service.kafka-producer.batch-size=16384
export-dbf-service.kafka-producer.linger-ms=1
export-dbf-service.kafka-producer.buffer-memory=33554432
export-dbf-service.section=S

View file

@ -1,18 +1,16 @@
package ru.spcex.clearing.dbf.exporter.logic.data.enums;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import org.junit.jupiter.api.Test;
import org.springframework.integration.sftp.session.SftpFileInfo;
import ru.spcex.clearing.dbf.exporter.logic.data.ResultContainer;
import ru.spcex.clearing.dbf.exporter.logic.stages.PrepareDBFFile;
import java.io.File;
import java.time.LocalDateTime;
import java.util.List;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import org.springframework.integration.sftp.session.SftpFileInfo;
import ru.spcex.clearing.dbf.exporter.logic.data.ResultContainer;
import static ru.spcex.clearing.dbf.exporter.logic.data.enums.FilenameTemplate.df_section_sameName;
import ru.spcex.clearing.dbf.exporter.logic.stages.PrepareDBFFile;
class FilenameTemplateTest {
@ -38,7 +36,7 @@ class FilenameTemplateTest {
SftpFileInfo sftpFileInfo = spy(new SftpFileInfo(lsEntry));
doReturn(false).when(sftpFileInfo).isDirectory();
List<SftpFileInfo> files = List.of(sftpFileInfo);
ResultContainer resultContainer = ResultContainer.createNewTask(Table.S_DF02);
ResultContainer resultContainer = ResultContainer.createNewTask(Table.S_DF02, "S");
resultContainer.setGroupId(10L);
resultContainer.setSourceName("DF-01_S_PRC1807230915_1.dbf");
PrepareDBFFile.outDir="TEST_DIR";

View file

@ -8,12 +8,12 @@
<artifactId>dbf-importer</artifactId>
<name>dbf-importer</name>
<description>DBF loader for DBF files</description>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<dependencies>

View file

@ -60,12 +60,12 @@ public class DbfImportKafkaMessenger implements InitializingBean {
}
public void notifyUserAboutErrorParsing(Throwable error, ResultContainer resultContainer) {
if (resultContainer == null || resultContainer.getDbfFile() == null || resultContainer.getDbfFile() == null)
if (resultContainer == null || resultContainer.getDbfFile() == null)
return;
ETable currTable = resultContainer.getDbfTable();
String fileName = resultContainer.getDbfFile().getName();
log.debug("Notify user about error {} \"{}\"",
resultContainer.getDbfTable(), fileName);
currTable, fileName);
sendUserNotification(ObjectType.rgst, String.format("Файл \"%s\" не сохранен", fileName), Priority.HIGH);
}

View file

@ -8,12 +8,12 @@
<name>Clearing dictionary</name>
<description>Clearing dictionary</description>
<packaging>jar</packaging>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<properties>

View file

@ -4,12 +4,12 @@
<parent>
<groupId>ru.spcex.clearing</groupId>
<artifactId>clearing-parent</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<artifactId>extdb-importer</artifactId>
<name>extdb-importer</name>
<description>Extdb importer module. Аналог trade-importer.</description>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<packaging>jar</packaging>
<properties>

View file

@ -5,7 +5,7 @@
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View file

@ -15,6 +15,8 @@ public class GatewayApiSettings {
private KafkaProducerSettings kafkaProducer;
private KafkaConsumerSettings kafkaConsumer;
private InboundServerSettings inboundServer;
private InboundExternalServerSettings inboundExternalServer;
private String clearingSystem;
public HazelcastClientParams getHazelcast() {
return hazelcast;
@ -47,4 +49,20 @@ public class GatewayApiSettings {
public void setInboundServer(InboundServerSettings inboundServer) {
this.inboundServer = inboundServer;
}
public InboundExternalServerSettings getInboundExternalServer() {
return inboundExternalServer;
}
public void setInboundExternalServer(InboundExternalServerSettings inboundExternalServer) {
this.inboundExternalServer = inboundExternalServer;
}
public String getClearingSystem() {
return clearingSystem;
}
public void setClearingSystem(String clearingSystem) {
this.clearingSystem = clearingSystem;
}
}

View file

@ -0,0 +1,61 @@
package ru.spcex.clearing.gatewayapi.config;
import java.util.ArrayList;
import java.util.List;
public class InboundExternalServerSettings {
private String host;
private String pathLOCM;
private String pathLOSC;
private Integer port;
private Boolean enableSsl;
private List<String> allowedTypes = new ArrayList<>();
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Boolean getEnableSsl() {
return enableSsl;
}
public void setEnableSsl(Boolean enableSsl) {
this.enableSsl = enableSsl;
}
public String getPathLOCM() {
return pathLOCM;
}
public void setPathLOCM(String pathLOCM) {
this.pathLOCM = pathLOCM;
}
public String getPathLOSC() {
return pathLOSC;
}
public void setPathLOSC(String pathLOSC) {
this.pathLOSC = pathLOSC;
}
public List<String> getAllowedTypes() {
return allowedTypes;
}
public void setAllowedTypes(List<String> allowedTypes) {
this.allowedTypes = allowedTypes;
}
}

View file

@ -1,11 +1,15 @@
package ru.spcex.clearing.gatewayapi.config;
import java.util.ArrayList;
import java.util.List;
public class InboundServerSettings {
private String host;
private String pathLOCM;
private String pathLOSC;
private Integer port;
private Boolean enableSsl;
private List<String> allowedTypes = new ArrayList<>();
public String getHost() {
return host;
@ -46,4 +50,12 @@ public class InboundServerSettings {
public void setPathLOSC(String pathLOSC) {
this.pathLOSC = pathLOSC;
}
public List<String> getAllowedTypes() {
return allowedTypes;
}
public void setAllowedTypes(List<String> allowedTypes) {
this.allowedTypes = allowedTypes;
}
}

View file

@ -266,6 +266,8 @@ public class GatewayController {
commonResponse.setType(request.getType());
commonResponse.setDatetime(request.getDatetime());
commonResponse.setSection(request.getSection());
commonResponse.setSection(request.getSection());
commonResponse.setClearingSystem(request.getClearingSystem());
if (success) {
commonResponse.setCode(0L);
commonResponse.setMessage("success");

View file

@ -50,6 +50,9 @@ public class CommonRequest {
@JsonProperty("section")
@ApiModelProperty(value = "Секция (FOND или MKR)", example = "FOND")
private String section;
@JsonProperty("clearing_system")
@ApiModelProperty(value = "Клиринговая система", example = "SPVB/LCC")
private String clearingSystem;
public void validate(List<String> typeValidValues, List<Section> sectionValidValues) {
if (!typeValidValues.isEmpty() && !typeValidValues.contains(type.toUpperCase())) {
@ -92,4 +95,12 @@ public class CommonRequest {
public void setSection(String section) {
this.section = section;
}
public String getClearingSystem() {
return clearingSystem;
}
public void setClearingSystem(String clearingSystem) {
this.clearingSystem = clearingSystem;
}
}

View file

@ -45,6 +45,10 @@ public class CommonResponse {
@JsonProperty("message")
private String message;
@JsonProperty("clearing_system")
@ApiModelProperty(value = "Клиринговая система", example = "SPVB/LCC")
private String clearingSystem;
public UUID getId() {
return id;
}
@ -92,4 +96,12 @@ public class CommonResponse {
public void setMessage(String message) {
this.message = message;
}
public String getClearingSystem() {
return clearingSystem;
}
public void setClearingSystem(String clearingSystem) {
this.clearingSystem = clearingSystem;
}
}

View file

@ -48,6 +48,10 @@ public class OutboundRequest {
)
private String section = "";
@JsonProperty("clearing_system")
@ApiModelProperty(value = "Клиринговая система", example = "SPVB/LCC")
private String clearingSystem;
// todo Пока так, чтобы отсылал null, в дальнейшем тип надо заменить на используемый в запросе. Возможно с помощью параметризации
@JsonProperty("content")
@ApiModelProperty(
@ -88,6 +92,14 @@ public class OutboundRequest {
this.section = section;
}
public String getClearingSystem() {
return clearingSystem;
}
public void setClearingSystem(String clearingSystem) {
this.clearingSystem = clearingSystem;
}
public Map<String, Object> getContent() {
return content;
}

View file

@ -0,0 +1,15 @@
package ru.spcex.clearing.gatewayapi.enums;
public enum ClearingSystems {
SPVB("SPVB"),
LCC("LCC");
private final String name;
ClearingSystems(final String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View file

@ -9,6 +9,7 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.producer.Producer;
@ -25,6 +26,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import ru.clearing.classes.statics.data.register.GatewayResult;
import ru.spcex.clearing.gatewayapi.config.GatewayApiSettings;
import ru.spcex.clearing.gatewayapi.config.InboundExternalServerSettings;
import ru.spcex.clearing.gatewayapi.config.InboundServerSettings;
import ru.spcex.clearing.gatewayapi.controller.inbound.request.operations.SentAsset;
import ru.spcex.clearing.gatewayapi.controller.outbound.request.OutboundRequest;
@ -60,10 +62,12 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
private final UserRoleVerification userRoleVerification;
private final RestTemplate restTemplate;
private final InboundServerSettings inboundServerSettings;
private final InboundExternalServerSettings inboundExternalServerSettings;
private final Map<Long, List<SentAsset>> sentAssets;
private final Map<UUID, OutboundRequest> outboundRequestByUuid;
protected final Imdg<GatewayResult> gatewayResultImdg;
private final static Pattern REPORT_FILE_NAME_PATTERN = Pattern.compile("(\\S*)_(\\d{15}).csv");
private final String clearingSystemValue;
public GatewayService(Consumer<String, Object> kafkaQueue,
Producer<String, Object> kafkaProducer,
@ -76,7 +80,10 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
super(kafkaQueue, kafkaProducer);
this.restTemplate = restTemplate;
this.userRoleVerification = userRoleVerification;
this.clearingSystemValue = StringUtils.isNotEmpty(gatewayApiSettings.getClearingSystem()) ?
gatewayApiSettings.getClearingSystem() : "SPVB";
this.inboundServerSettings = gatewayApiSettings.getInboundServer();
this.inboundExternalServerSettings = gatewayApiSettings.getInboundExternalServer();
this.sentAssets = sentAssets;
this.outboundRequestByUuid = outboundRequestByUuid;
this.gatewayResultImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_GatewayResult, GatewayResult.class);
@ -112,42 +119,29 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
if (requestInfoUpdate != null) return;
logUnknownProperties(userRequest);
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
OutboundRequest outboundFondRequest = OutboundRequestBuilder.builder()
.type(OutboundRequestType.MEMBER_ON_DEMAND.getKey())
.clearingSystem(clearingSystemValue)
.build();
HttpEntity<OutboundRequest> request = makeDefaultRequest(outboundFondRequest);
outboundRequestByUuid.put(outboundFondRequest.getId(), outboundFondRequest);
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, request, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOCM task complete, success response : {}", bodyResponse);
}
sendRequest(outboundFondRequest);
}
public void requestOnLimit(BaseRequest<LimExportedRequest> userRequest) {
LimExportedRequest exportedRequest = userRequest.getRequestPayload();
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
Map<String, Object> content = Map.of("file", exportedRequest.getLimFileName());
OutboundRequest outboundFondRequest = OutboundRequestBuilder.builder()
.section(exportedRequest.getSection())
.type(OutboundRequestType.FILL_LIMITS.getKey())
.clearingSystem(clearingSystemValue)
.content(content)
.build();
HttpEntity<OutboundRequest> request = makeDefaultRequest(outboundFondRequest);
outboundRequestByUuid.put(outboundFondRequest.getId(), outboundFondRequest);
gatewayResultImdg.insert(GatewayResultBuilder.builder().outboundRequest(outboundFondRequest).build());
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, request, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("Limit request complete, success response: {}", bodyResponse);
}
sendRequest(outboundFondRequest);
}
public void requestOnDemandSecurity(BaseRequest<GatewayTaskRequest> userRequest) {
@ -158,45 +152,34 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
logUnknownProperties(userRequest);
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
OutboundRequest outboundFondRequest = OutboundRequestBuilder.builder()
.section(Section.FOND.getKey())
.type(OutboundRequestType.ON_DEMAND.getKey())
.clearingSystem(clearingSystemValue)
.build();
OutboundRequest outboundMkrRequest = OutboundRequestBuilder.builder()
.section(Section.MKR.getKey())
.type(OutboundRequestType.ON_DEMAND.getKey())
.clearingSystem(clearingSystemValue)
.build();
OutboundRequest outboundCurrRequest = OutboundRequestBuilder.builder()
.section(Section.CURR.getKey())
.type(OutboundRequestType.ON_DEMAND.getKey())
.clearingSystem(clearingSystemValue)
.build();
HttpEntity<OutboundRequest> requestFond = makeDefaultRequest(outboundFondRequest);
HttpEntity<OutboundRequest> requestMKR = makeDefaultRequest(outboundMkrRequest);
HttpEntity<OutboundRequest> requestCURR = makeDefaultRequest(outboundCurrRequest);
outboundRequestByUuid.put(outboundFondRequest.getId(), outboundFondRequest);
outboundRequestByUuid.put(outboundMkrRequest.getId(), outboundMkrRequest);
outboundRequestByUuid.put(outboundCurrRequest.getId(), outboundCurrRequest);
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, requestFond, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOSC task 1/3 complete (FOND section), success response: {}", bodyResponse);
}
response = restTemplate.exchange(url, HttpMethod.POST, requestMKR, SuccessResponse.class);
bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOSC task 2/3 complete (MKR section), success response: {}", bodyResponse);
}
response = restTemplate.exchange(url, HttpMethod.POST, requestCURR, SuccessResponse.class);
bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("LOSC task 3/3 complete (CURR section), success response: {}", bodyResponse);
}
sendRequest(outboundFondRequest);
log.debug("LOSC task 1/3 complete (FOND section)");
sendRequest(outboundMkrRequest);
log.debug("LOSC task 2/3 complete (MKR section)");
sendRequest(outboundCurrRequest);
log.debug("LOSC task 3/3 complete (CURR section)");
}
public void requestOnAsset(BaseRequest<AssetOperationListRequest> request) {
@ -221,19 +204,14 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
OutboundRequest outboundRequest = OutboundRequestBuilder.builder()
.section(assetOperation.getAmount() != null ? Section.MKR.getKey() : Section.FOND.getKey())
.type(OutboundRequestType.ASSET_OPERATION.getKey())
.clearingSystem(clearingSystemValue)
.content(content).build();
gatewayBuilder.outboundRequest(outboundRequest);
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpEntity<OutboundRequest> r = makeDefaultRequest(outboundRequest);
try {
outboundRequestByUuid.put(outboundRequest.getId(), outboundRequest);
gatewayResultImdg.insert(gatewayBuilder.build());
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, r, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("Response from service: {}", bodyResponse);
}
sendRequest(outboundRequest);
} catch (Throwable err) {
log.error("Exchange error: {}", ExceptionUtils.getStackTrace(err));
} finally {
@ -260,15 +238,10 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
OutboundRequest outboundRequest = OutboundRequestBuilder.builder()
.section(Section.FOND.getKey())
.type(reportType.getKey())
.clearingSystem(clearingSystemValue)
.content(content).build();
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpEntity<OutboundRequest> r = makeDefaultRequest(outboundRequest);
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, r, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("Response from service: {}", bodyResponse);
}
sendRequest(outboundRequest);
}
public void requestOnTkr(BaseRequest<SendTkrRequest> request) {
@ -278,6 +251,7 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
OutboundRequest outboundRequest = OutboundRequestBuilder.builder()
.type(OutboundRequestType.MEMBER_RESPONSE_TKR.getKey())
.content(content)
.clearingSystem(clearingSystemValue)
.build();
if (reportRequest.getRequestId() != null) {
outboundRequest.setId(reportRequest.getRequestId());
@ -286,13 +260,7 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
.outboundRequest(outboundRequest)
.build();
gatewayResultImdg.insert(gatewayResult);
String url = formingInboundUrl(inboundServerSettings.getPathLOCM());
HttpEntity<OutboundRequest> r = makeDefaultRequest(outboundRequest);
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, r, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("Response from service: {}", bodyResponse);
}
sendRequest(outboundRequest);
}
protected void makeContentByReportRequest(Map<String, Object> content, ReportPart reportPart) {
@ -318,12 +286,45 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
case KS_REP_FIRM_DETAILS -> paramName = "ks_rep_firm_details";
case KS_SESSION_LIST -> paramName = "ks_session_list";
case KS_COMMISSION_TRADES -> paramName = "ks_commission_trades";
case KS_REP_LCC_TRADES_REPORT -> paramName = "ks_rep_lcc_trades";
case KS_REP_LCC_NETTO_REPORT -> paramName = "ks_rep_lcc_netto";
}
if (paramName != null) {
content.put(paramName, reportPart.getFileName());
}
}
private void sendRequest(OutboundRequest request) {
if (inboundServerSettings != null &&
(inboundServerSettings.getAllowedTypes().isEmpty() ||
inboundServerSettings.getAllowedTypes().contains(request.getType()))) {
String url = formingInboundUrl(inboundServerSettings.getEnableSsl(),
inboundServerSettings.getHost(),
inboundServerSettings.getPort(),
inboundServerSettings.getPathLOCM());
exchange(request, url);
}
if (inboundExternalServerSettings != null &&
(inboundExternalServerSettings.getAllowedTypes().isEmpty() ||
inboundExternalServerSettings.getAllowedTypes().contains(request.getType()))) {
String url = formingInboundUrl(inboundExternalServerSettings.getEnableSsl(),
inboundExternalServerSettings.getHost(),
inboundExternalServerSettings.getPort(),
inboundExternalServerSettings.getPathLOCM());
exchange(request, url);
}
}
private void exchange(OutboundRequest request, String url) {
HttpEntity<OutboundRequest> r = makeDefaultRequest(request);
ResponseEntity<SuccessResponse> response = restTemplate.exchange(url, HttpMethod.POST, r, SuccessResponse.class);
SuccessResponse bodyResponse = response.getBody();
if (bodyResponse != null) {
log.debug("Response from service: {}", bodyResponse);
}
}
public String formingInboundUrl(String path) {
return "%s://%s:%s/%s".formatted(
inboundServerSettings.getEnableSsl() ? "https" : "http",
@ -333,6 +334,15 @@ public class GatewayService extends QueueConsumer implements InitializingBean {
);
}
public String formingInboundUrl(Boolean enableSsl, String host, Integer port, String path) {
return "%s://%s:%s/%s".formatted(
enableSsl ? "https" : "http",
host,
port,
path
);
}
private void logUnknownProperties(BaseRequest<GatewayTaskRequest> request) {
Map<String, Object> unknownProperties = request.getUnknownProperties();
for (Map.Entry<String, Object> unknownProperty : unknownProperties.entrySet()) {

View file

@ -26,6 +26,9 @@ public class TkrService {
if (tkrRequest.getErrors() != null && !tkrRequest.getErrors().isEmpty()) {
return;
}
if (tkrRequest.getInfoAccount() == null || tkrRequest.getInfoAccount().isEmpty()) {
return;
}
List<TkrAccount> tkrAccountsForCheck = tkrRequest.getInfoAccount()
.stream().filter(infoAccount -> TypeOperations.CHECK.equalsByKey(infoAccount.getTypeOperationClient()))
.map(tkrAdapter::toTkrResponse)

View file

@ -1,15 +1,15 @@
package ru.spcex.clearing.gatewayapi.service.builders;
import ru.spcex.clearing.gatewayapi.controller.outbound.request.OutboundRequest;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import ru.spcex.clearing.gatewayapi.controller.outbound.request.OutboundRequest;
public class OutboundRequestBuilder {
private String section;
private String requestType;
private String clearingSystem;
private Map<String, Object> content;
private OutboundRequestBuilder() {
@ -34,11 +34,16 @@ public class OutboundRequestBuilder {
this.content = content;
return this;
}
public OutboundRequestBuilder clearingSystem(String val) {
this.clearingSystem = val;
return this;
}
public OutboundRequest build() {
OutboundRequest outboundRequest = new OutboundRequest();
outboundRequest.setId(UUID.randomUUID());
outboundRequest.setDatetime(Instant.now());
outboundRequest.setClearingSystem(clearingSystem);
if (section != null) {
outboundRequest.setSection(section);
}

View file

@ -25,8 +25,17 @@ gateway-api.kafka-consumer.auto-offset-reset=latest
gateway-api.kafka-consumer.linger-ms=1
gateway-api.kafka-consumer.buffer-memory=33554432
gateway-api.clearing-system=LCC
gateway-api.inbound-server.enable-ssl=false
gateway-api.inbound-server.host=10.200.200.183
gateway-api.inbound-server.port=8084
gateway-api.inbound-server.pathLOCM=test_rest/inbound_request
gateway-api.inbound-server.pathLOSC=test_rest/inbound_request
gateway-api.inbound-server.pathLOSC=test_rest/inbound_request
gateway-api.inbound-server.allowed-types=ASSET_OPERATION,ON_DEMAND
gateway-api.inbound-external-server.enable-ssl=false
gateway-api.inbound-external-server.host=10.200.200.183
gateway-api.inbound-external-server.port=8084
gateway-api.inbound-external-server.pathLOCM=test_rest/inbound_request
gateway-api.inbound-external-server.allowed-types=FILL_LIMITS,MEMBER_ON_DEMAND

View file

@ -5,12 +5,12 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>imdg-hist</artifactId>
<packaging>jar</packaging>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
@ -36,13 +36,13 @@
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>classes</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>dictionary</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
@ -82,7 +82,7 @@
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>cleaning-builders</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>

View file

@ -7,12 +7,12 @@
<artifactId>imdg</artifactId>
<name>Clearing in memory data grid</name>
<packaging>jar</packaging>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<parent>
<artifactId>clearing-parent</artifactId>
<groupId>ru.spcex.clearing</groupId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
</parent>
<properties>
@ -32,13 +32,13 @@
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>classes</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>dictionary</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
@ -89,7 +89,7 @@
<dependency>
<groupId>ru.spcex.clearing</groupId>
<artifactId>cleaning-builders</artifactId>
<version>SPCEX-3.14.106</version>
<version>SPCEX-3.15.209</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -118,6 +118,18 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.20.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.20.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>

View file

@ -1,6 +1,22 @@
package ru.spcex.clearing.imdg.base;
import com.hazelcast.core.MapStore;
import java.math.BigDecimal;
import java.sql.ParameterMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -8,18 +24,11 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.lang.NonNull;
import ru.spcex.clearing.imdg.util.ColumnMetaData;
import ru.spcex.clearing.imdg.util.PostgresColumnTypeUtil;
import ru.spcex.platform.classes.base.SpcexObjectBase;
import ru.spcex.platform.utils.text.TextUtil;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
/**
* MapStore для выгрузки обычных объектов
*
@ -29,7 +38,7 @@ public abstract class SimpleObjectMapStore<T extends SpcexObjectBase> implements
private final static int BATCH_SIZE = 1000;
protected final Logger log = LoggerFactory.getLogger(this.getClass());
protected final JdbcTemplate jdbcTemplate;
protected SimpleDateFormat DB_DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd");
protected Map<String, ColumnMetaData> columnMetaDataMap;
protected SimpleObjectMapStore(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
@ -135,8 +144,8 @@ public abstract class SimpleObjectMapStore<T extends SpcexObjectBase> implements
List<Long> keys;
try {
keys = jdbcTemplate.query("select id from " + getTableName() + " where " + dateField + (canBeGreat ? " >= ?" : " = ?"),
(resultSet, i) -> resultSet.getLong("id"),
new Object[]{today});
(resultSet, i) -> resultSet.getLong("id"),
new Object[]{today});
} catch (Throwable e) {
log.error("At load keys from {} (by field {}): {}", getTableName(), dateField, ExceptionUtils.getStackTrace(e));
throw e;
@ -149,10 +158,16 @@ public abstract class SimpleObjectMapStore<T extends SpcexObjectBase> implements
}
protected void batchInsertUpdate(@NonNull String insertStatement, @NonNull List<Object[]> args) {
batchInsertUpdate(insertStatement, args, getTableName(), getFields());
}
protected void batchInsertUpdate(@NonNull String insertStatement, @NonNull List<Object[]> args, String tableName, String[] fields) {
readMetaData(tableName);
try {
int[][] ret = jdbcTemplate.batchUpdate(insertStatement, args, BATCH_SIZE, (ps, params) -> {
for (int i = 0; i < params.length; i++) {
Object value = params[i];
value = normalizeValue(value, ps.getParameterMetaData(), columnMetaDataMap, i, insertStatement, params, tableName, fields);
try {
StatementCreatorUtils.setParameterValue(ps, i + 1, SqlTypeValue.TYPE_UNKNOWN, value);
} catch (SQLException e) {
@ -161,13 +176,120 @@ public abstract class SimpleObjectMapStore<T extends SpcexObjectBase> implements
}
});
int batchSize = ret.length > 0 ? ret[0].length : ret.length;
log.debug("{} {} rows stored", getTableName(), batchSize);
log.debug("{} {} rows stored", tableName, batchSize);
} catch (Exception e) {
log.error("SQL error at batch UPDATE OR INSERT INTO {}\n{}", getTableName(), ExceptionUtils.getStackTrace(e));
log.error("SQL error at batch UPDATE OR INSERT INTO {}\n{}", tableName, ExceptionUtils.getStackTrace(e));
throw e;
}
}
Object normalizeValue(Object value, ParameterMetaData metaData, Map<String, ColumnMetaData> columnMetaDataMap, int i,
String insertStatement, Object[] params, String tableName, String[] fields) throws SQLException {
if (value == null)
return null;
i++; // нумерация в ParameterMetaData начинается с 1
final int type = metaData.getParameterType(i);
final String fieldName = fields[i - 1].toLowerCase();
if (columnMetaDataMap == null) {
log.trace("Column metadata was empty, can not verify {}.{}", tableName, fieldName);
}
if ((type == Types.VARCHAR || type == Types.CHAR) && value instanceof String stringValue) {
int length;
if (columnMetaDataMap == null) {
length = metaData.getPrecision(i + 1);
} else {
// в postgresql для String ParameterMetaData.getPrecision возвращает 0, используется columnMetaDataMap
length = columnMetaDataMap.get(fieldName).getPrecision();
}
if (length > 0 && stringValue.length() > length) {
value = stringValue.substring(0, length);
log.error("String value is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, stringValue, value);
}
} else if ((type == Types.DECIMAL || type == Types.NUMERIC || type == Types.BIGINT || type == Types.INTEGER) &&
(value instanceof BigDecimal || value instanceof Long || value instanceof Integer)) {
if (value instanceof Integer && (type == Types.INTEGER || type == Types.BIGINT)) {
return value; // ok
}
if (value instanceof Long vl) {
if (type == Types.BIGINT) {
return value; // ok
}
if (type == Types.INTEGER) {
if (vl > Integer.MAX_VALUE) {
value = Integer.MAX_VALUE;
log.error("Long value for insert is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, vl, value);
}
if (vl < Integer.MIN_VALUE) {
value = Integer.MIN_VALUE;
log.error("Long value for insert is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, vl, value);
}
return value;
}
}
BigDecimal bigDecimalValue;
if (value instanceof Integer intValue) {
bigDecimalValue = BigDecimal.valueOf(intValue);
} else if (value instanceof Long longValue) {
bigDecimalValue = BigDecimal.valueOf(longValue);
} else {
bigDecimalValue = (BigDecimal) value;
}
if (type == Types.BIGINT) {
if (bigDecimalValue.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) > 0) {
Object oldValue = value;
value = Long.MAX_VALUE;
log.error("Double value as BIGINT is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, oldValue, value);
} else if (bigDecimalValue.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0) {
Object oldValue = value;
value = Long.MIN_VALUE;
log.error("Double value as BIGINT is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, oldValue, value);
}
return value; // value ok
}
if (type == Types.INTEGER) {
if (bigDecimalValue.compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) > 0) {
Object oldValue = value;
value = Integer.MAX_VALUE;
log.error("Double value as INTEGER is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, oldValue, value);
} else if (bigDecimalValue.compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) < 0) {
Object oldValue = value;
value = Integer.MIN_VALUE;
log.error("Double value as INTEGER is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, oldValue, value);
}
return value; // value ok
}
int dbScalePartLength;
int precision;
if (columnMetaDataMap == null) {
dbScalePartLength = metaData.getScale(i);
precision = metaData.getPrecision(i);
} else {
dbScalePartLength = columnMetaDataMap.get(fieldName).getScale();
precision = columnMetaDataMap.get(fieldName).getPrecision();
}
if (!checkBigDecimalSize(bigDecimalValue, precision, dbScalePartLength)) {
boolean negative = bigDecimalValue.signum() < 0;
value = new BigDecimal(BigDecimal.valueOf(Math.pow(10, precision - dbScalePartLength)).longValue() - 1);
if (negative)
value = ((BigDecimal) value).negate();
log.error("BigDecimal value is too large [insertSql: {}, params: {}, i: {}, incorrect value: {}, normalized value: {}]",
insertStatement, Arrays.toString(params), i, bigDecimalValue, value);
}
}
return value;
}
protected Instant getInstantFromTimestamp(ResultSet rs, String column) throws SQLException {
Timestamp date = rs.getTimestamp(column);
return date != null ? date.toInstant() : null;
@ -191,4 +313,16 @@ public abstract class SimpleObjectMapStore<T extends SpcexObjectBase> implements
return TextUtil.format(INSERT_TEMPLATE, params);
}
private void readMetaData(String tableName) {
synchronized (this) {
columnMetaDataMap = PostgresColumnTypeUtil.extractTableMetadata(jdbcTemplate, tableName);
}
}
private boolean checkBigDecimalSize(BigDecimal value, int dbSize, int dbScale) {
if (value == null)
return true;
return value.precision() - value.scale() <= dbSize - dbScale;
}
}

View file

@ -79,6 +79,6 @@ public abstract class ASecurityHistoryMapStore<STH extends BusinessEvent<? exten
securityArgs.add(securityItemArgs);
}
batchInsertUpdate(insertStatement, tableArgs);
batchInsertUpdate(insertToSecurityStatement, securityArgs);
batchInsertUpdate(insertToSecurityStatement, securityArgs, "SECURITY_HISTORY", this.getFieldsSecurity());
}
}

View file

@ -27,8 +27,8 @@ public class BankAccountHistoryMapStore extends TemplateEventMapStore<BankAccoun
@Override
public String[] getFields() {
return new String[]{"ID", "EVENT_TIME", "EVENT_TYPE", "EVENT_USER_ID",
"BANK_ACCOUNT_ID", "ACCOUNT_ID", "BANK_IDENTIFICATION_CODE", "BANK_NAME", "CORRESPONDENT_ACCOUNT", "CORRESPONDENT_ACCOUNT_NAME", "CURRENCY", "DESTINATION", "IBAN", "INTERNATIONAL_TRANSFER_SIGN", "SWIFT_CODE", "TAXPAYER_IDENTIFICATION_NUMBER", "TAX_REGISTRATION_REASON_CODE", "ACCOUNT", "COMPANY_ID", "INTERMEDIARY_SWIFT_CODE"
return new String[]{"ID", "EVENT_TIME", "EVENT_USER_ID", "EVENT_TYPE",
"BANK_ACCOUNT_ID", "ACCOUNT_ID", "BANK_IDENTIFICATION_CODE", "BANK_NAME", "CORRESPONDENT_ACCOUNT", "CORRESPONDENT_ACCOUNT_NAME", "CURRENCY", "DESTINATION", "IBAN", "INTERNATIONAL_TRANSFER_SIGN", "SWIFT_CODE", "TAXPAYER_IDENTIFICATION_NUMBER", "TAX_REGISTRATION_REASON_CODE", "ACCOUNT", "COMPANY_ID", "INTERMEDIARY_SWIFT_CODE", "NAME", "ADDRESS", "BANK_ADDRESS", "BANK_SWIFT_CODE", "BANK_ACCOUNT", "BANK_NAME1", "BANK_ADDRESS1", "BANK_ACCOUNT1", "BANK_NAME2", "BANK_ADDRESS2", "INTERMEDIARY_SWIFT_CODE2", "BANK_ACCOUNT2", "PERSONAL_ACCOUNT", "BUDGET_CLASSIFICATION_CODE", "OKTMO"
};
}
@ -38,8 +38,8 @@ public class BankAccountHistoryMapStore extends TemplateEventMapStore<BankAccoun
Object[] args = new Object[]{
historyLog.getId(),
TimeUtil.toDateFromInstant(historyLog.getEventTime()),
historyLog.getEventType(),
historyLog.getUserId(),
historyLog.getEventType(),
object.getId(),
object.getAccountId(),
@ -56,7 +56,22 @@ public class BankAccountHistoryMapStore extends TemplateEventMapStore<BankAccoun
object.getTaxRegistrationReasonCode(),
object.getAccount(),
object.getCompanyId(),
object.getIntermediarySwiftCode()
object.getIntermediarySwiftCode(),
object.getName(),
object.getAddress(),
object.getBankAddress(),
object.getBankSwiftCode(),
object.getBankAccount(),
object.getBankName1(),
object.getBankAddress1(),
object.getBankAccount1(),
object.getBankName2(),
object.getBankAddress2(),
object.getIntermediarySwiftCode2(),
object.getBankAccount2(),
object.getPersonalAccount(),
object.getBudgetClassificationCode(),
object.getOktmo()
};
return args;
}

View file

@ -100,7 +100,7 @@ public abstract class ASecurityMapStore <S extends Security> extends TemplateMap
securityArgs.add(argsSecurityItem);
}
batchInsertUpdate(insertStatement, childTableArgs);
batchInsertUpdate(insertToSecurityStatement, securityArgs);
batchInsertUpdate(insertToSecurityStatement, securityArgs, "SECURITY", this.getFieldsSecurity());
}

View file

@ -3,6 +3,9 @@ package ru.spcex.clearing.imdg.businessobject;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.List;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.execution.ExecutionCurrency;
@ -33,7 +36,20 @@ public class ExecutionCurrencyMapStore extends TemplateMapStore<ExecutionCurrenc
@Override
public Iterable<Long> loadAllKeys() {
return defaultLoadAllKeysOnTodayByField("TRADING_DATE", false);
LocalDate today = LocalDate.now();
String dateField = "TRADING_DATE";
log.debug("loadAllKeys from {}", getTableName());
List<Long> keys;
try {
keys = jdbcTemplate.query("select id from " + getTableName()
+ " where TRADING_DATE" + " = ? or SETTLEMENT_DATE >= ?",
(resultSet, i) -> resultSet.getLong("id"),
new Object[]{today, today});
} catch (Throwable e) {
log.error("At load keys from {} (by field {}): {}", getTableName(), dateField, ExceptionUtils.getStackTrace(e));
throw e;
}
return keys;
}
@Override

View file

@ -33,7 +33,7 @@ public class BankAccountMapStore extends TemplateMapStore<BankAccount> {
@Override
public String[] getFields() {
return new String[]{
"ID", "ACCOUNT_ID", "BANK_IDENTIFICATION_CODE", "BANK_NAME", "CORRESPONDENT_ACCOUNT", "CORRESPONDENT_ACCOUNT_NAME", "CURRENCY", "DESTINATION", "IBAN", "INTERNATIONAL_TRANSFER_SIGN", "SWIFT_CODE", "TAXPAYER_IDENTIFICATION_NUMBER", "TAX_REGISTRATION_REASON_CODE", "ACCOUNT", "COMPANY_ID", "INTERMEDIARY_SWIFT_CODE"
"ID", "ACCOUNT_ID", "BANK_IDENTIFICATION_CODE", "BANK_NAME", "CORRESPONDENT_ACCOUNT", "CORRESPONDENT_ACCOUNT_NAME", "CURRENCY", "DESTINATION", "IBAN", "INTERNATIONAL_TRANSFER_SIGN", "SWIFT_CODE", "TAXPAYER_IDENTIFICATION_NUMBER", "TAX_REGISTRATION_REASON_CODE", "ACCOUNT", "COMPANY_ID", "INTERMEDIARY_SWIFT_CODE", "NAME", "ADDRESS", "BANK_ADDRESS", "BANK_SWIFT_CODE", "BANK_ACCOUNT", "BANK_NAME1", "BANK_ADDRESS1", "BANK_ACCOUNT1", "BANK_NAME2", "BANK_ADDRESS2", "INTERMEDIARY_SWIFT_CODE2", "BANK_ACCOUNT2", "PERSONAL_ACCOUNT", "BUDGET_CLASSIFICATION_CODE", "OKTMO"
};
}
@ -56,6 +56,21 @@ public class BankAccountMapStore extends TemplateMapStore<BankAccount> {
object.setAccount(resultSet.getObject("ACCOUNT", String.class));
object.setCompanyId(resultSet.getObject("COMPANY_ID", Long.class));
object.setIntermediarySwiftCode(resultSet.getObject("INTERMEDIARY_SWIFT_CODE", String.class));
object.setName(resultSet.getObject("NAME", String.class));
object.setAddress(resultSet.getObject("ADDRESS", String.class));
object.setBankAddress(resultSet.getObject("BANK_ADDRESS", String.class));
object.setBankSwiftCode(resultSet.getObject("BANK_SWIFT_CODE", String.class));
object.setBankAccount(resultSet.getObject("BANK_ACCOUNT", String.class));
object.setBankName1(resultSet.getObject("BANK_NAME1", String.class));
object.setBankAddress1(resultSet.getObject("BANK_ADDRESS1", String.class));
object.setBankAccount1(resultSet.getObject("BANK_ACCOUNT1", String.class));
object.setBankName2(resultSet.getObject("BANK_NAME2", String.class));
object.setBankAddress2(resultSet.getObject("BANK_ADDRESS2", String.class));
object.setIntermediarySwiftCode2(resultSet.getObject("INTERMEDIARY_SWIFT_CODE2", String.class));
object.setBankAccount2(resultSet.getObject("BANK_ACCOUNT2", String.class));
object.setPersonalAccount(resultSet.getObject("PERSONAL_ACCOUNT", String.class));
object.setBudgetClassificationCode(resultSet.getObject("BUDGET_CLASSIFICATION_CODE", String.class));
object.setOktmo(resultSet.getObject("OKTMO", String.class));
return object;
}
@ -77,7 +92,22 @@ public class BankAccountMapStore extends TemplateMapStore<BankAccount> {
object.getTaxRegistrationReasonCode(),
object.getAccount(),
object.getCompanyId(),
object.getIntermediarySwiftCode()
object.getIntermediarySwiftCode(),
object.getName(),
object.getAddress(),
object.getBankAddress(),
object.getBankSwiftCode(),
object.getBankAccount(),
object.getBankName1(),
object.getBankAddress1(),
object.getBankAccount1(),
object.getBankName2(),
object.getBankAddress2(),
object.getIntermediarySwiftCode2(),
object.getBankAccount2(),
object.getPersonalAccount(),
object.getBudgetClassificationCode(),
object.getOktmo()
};
return args;
}

View file

@ -0,0 +1,66 @@
package ru.spcex.clearing.imdg.object;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.security.Rates;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.imdg.base.TemplateMapStore;
import ru.spcex.platform.utils.time.TimeUtil;
@Component
public class RatesMapStore extends TemplateMapStore<Rates> {
public RatesMapStore(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}
@Override
public String getMapName() {
return IMDGDistributedNames.Map_Rates;
}
@Override
public String getTableName() {
return "RATES";
}
@Override
public String[] getFields() {
return new String[]{
"ID", "VALUE", "VALUE_DATE", "CURRENCY", "CURRENCY_ID", "CREATED_AT", "UPDATED_AT", "WORKFLOW_STATUS"
};
}
@Override
public Rates objectReader(ResultSet resultSet) throws SQLException {
Rates object = new Rates();
object.setId(resultSet.getObject("ID", Long.class));
object.setValue(resultSet.getObject("VALUE", BigDecimal.class));
object.setValueDate(getLocalDateFromSqlDate(resultSet,"VALUE_DATE"));
object.setCurrency(resultSet.getObject("CURRENCY", String.class));
object.setCurrencyId(resultSet.getObject("CURRENCY_ID", Long.class));
object.setCreated(getInstantFromTimestamp(resultSet, "CREATED_AT"));
object.setUpdated(getInstantFromTimestamp(resultSet, "UPDATED_AT"));
object.setWorkflowStatus(resultSet.getObject("WORKFLOW_STATUS", String.class));
return object;
}
@Override
public Object[] objectToField(Rates object) {
Object[] args = new Object[]{
object.getId(),
object.getValue(),
TimeUtil.toDateFromLocalDate(object.getValueDate()),
object.getCurrency(),
object.getCurrencyId(),
TimeUtil.toDateFromInstant(object.getCreated()),
TimeUtil.toDateFromInstant(object.getUpdated()),
object.getWorkflowStatus()
};
return args;
}
}

View file

@ -0,0 +1,66 @@
package ru.spcex.clearing.imdg.object;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.security.RiskParameter;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.imdg.base.TemplateMapStore;
import ru.spcex.platform.utils.time.TimeUtil;
@Component
public class RiskParameterMapStore extends TemplateMapStore<RiskParameter> {
public RiskParameterMapStore(JdbcTemplate jdbcTemplate) {
super(jdbcTemplate);
}
@Override
public String getMapName() {
return IMDGDistributedNames.Map_RiskParameter;
}
@Override
public String getTableName() {
return "RISK_PARAMETER";
}
@Override
public String[] getFields() {
return new String[]{
"ID", "VALUE", "SETTLEMENT_TYPE", "CURRENCY_PAIR", "CURRENCY_PAIR_ID", "CREATED_AT", "UPDATED_AT", "WORKFLOW_STATUS"
};
}
@Override
public RiskParameter objectReader(ResultSet resultSet) throws SQLException {
RiskParameter object = new RiskParameter();
object.setId(resultSet.getObject("ID", Long.class));
object.setValue(resultSet.getObject("VALUE", BigDecimal.class));
object.setSettlementType(resultSet.getObject("SETTLEMENT_TYPE", String.class));
object.setCurrencyPair(resultSet.getObject("CURRENCY_PAIR", String.class));
object.setCurrencyPairId(resultSet.getObject("CURRENCY_PAIR_ID", Long.class));
object.setCreated(getInstantFromTimestamp(resultSet, "CREATED_AT"));
object.setUpdated(getInstantFromTimestamp(resultSet, "UPDATED_AT"));
object.setWorkflowStatus(resultSet.getObject("WORKFLOW_STATUS", String.class));
return object;
}
@Override
public Object[] objectToField(RiskParameter object) {
Object[] args = new Object[]{
object.getId(),
object.getValue(),
object.getSettlementType(),
object.getCurrencyPair(),
object.getCurrencyPairId(),
TimeUtil.toDateFromInstant(object.getCreated()),
TimeUtil.toDateFromInstant(object.getUpdated()),
object.getWorkflowStatus()
};
return args;
}
}

View file

@ -40,7 +40,8 @@ public class STradesMapStore extends TemplateMapStore<STrades> {
"QTY", "QTY_PCS", "TRADE_DATE_TIME", "REPO_TERM", "CLEARING_COMMISSION", "EXCHANGE_COMMISSION",
"TECH_CENTER_COMMISSION", "ACCOUNT", "BROKER_REF", "CLIENT_CODE", "SETTLE_CODE", "USER_ID",
"EXCHANGE_CODE", "FIRM_ID", "FIRM_NAME", "CP_FIRM_ID", "CP_FIRM_NAME", "CLASS_NAME", "SEC_NAME",
"SETTLE_DATE", "SETTLE_CURRENCY", "TRADE_CURRENCY", "TRADE_TIME_MS", "BANK_ACC_ID", "SECTION"
"SETTLE_DATE", "SETTLE_CURRENCY", "TRADE_CURRENCY", "TRADE_TIME_MS", "BANK_ACC_ID", "SECTION",
"KIND", "LINKED_TRADE"
};
}
@ -103,6 +104,8 @@ public class STradesMapStore extends TemplateMapStore<STrades> {
object.setTradeTimeMs(resultSet.getObject("TRADE_TIME_MS", Long.class));
object.setBankAccId(resultSet.getObject("BANK_ACC_ID", String.class));
object.setSection(resultSet.getObject("SECTION", String.class));
object.setKind(resultSet.getObject("KIND", String.class));
object.setLinkedTrade(resultSet.getObject("LINKED_TRADE", Long.class));
return object;
}
@ -155,7 +158,9 @@ public class STradesMapStore extends TemplateMapStore<STrades> {
object.getTradeCurrency(),
object.getTradeTimeMs(),
object.getBankAccId(),
object.getSection()
object.getSection(),
object.getKind(),
object.getLinkedTrade()
};
return args;
}

View file

@ -4,6 +4,14 @@ import com.hazelcast.config.MapStoreConfig;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.core.IdGenerator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
@ -16,10 +24,6 @@ import ru.spcex.clearing.imdg.base.SimpleObjectMapStore;
import ru.spcex.clearing.imdg.object.DbVersionMapStore;
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
//todo почистить класс
public abstract class AbstractHazelcastLifecycleSupport implements InitializingBean, DisposableBean {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@ -48,7 +52,7 @@ public abstract class AbstractHazelcastLifecycleSupport implements InitializingB
@Override
public void afterPropertiesSet() {
// HazelcastCommon.loadClassesVersionsByStorage(hazelcastServerInstance, getSerialVersionUIDClasses());
// databaseVersionCheck();
databaseVersionCheck();
long loadTime = System.currentTimeMillis();
@ -119,11 +123,38 @@ public abstract class AbstractHazelcastLifecycleSupport implements InitializingB
HazelcastHelper.imdgSystem_setStorageState(true, hazelcastServerInstance);
loadTime = System.currentTimeMillis() - loadTime;
log.info("All map load time {} ms", loadTime);
}
@Override
public void destroy() {
hazelcastServerInstance.shutdown();
}
private void databaseVersionCheck() {
log.debug("Validating database version, expected \"{}\"", getCheckDbVersion());
String dbVersion = jdbcTemplate.queryForObject("SELECT version FROM db_version", String.class);
log.trace("Database version is \"{}\"", dbVersion);
if (dbVersion == null || dbVersion.isBlank()) {
log.error("Database version is empty");
System.exit(1);
} else {
List<Integer> expectedVersion = Arrays.stream(getCheckDbVersion().split("\\."))
.map(Integer::parseInt)
.toList();
List<Integer> actualVersion = Arrays.stream(dbVersion.split("\\."))
.map(Integer::parseInt)
.toList();
if (expectedVersion.size() < 2 || actualVersion.size() < 2) {
log.error("Database version have wrong format, expected = {}, actual = {}", expectedVersion, actualVersion);
System.exit(1);
}
if (!expectedVersion.get(0).equals(actualVersion.get(0)) || expectedVersion.get(1) > actualVersion.get(1)) {
log.error("Database version is older than expected version, expected = {}, actual = {}", expectedVersion, actualVersion);
System.exit(1);
}
}
}
}

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