diff --git a/.gitignore b/.gitignore index 46b4063fb..e0561bef5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ target *.iml logs tmp_notes.** +tmp +clearing-parent/backend-api/src/main/resources/meta.json diff --git a/build_without_tests.cmd b/build_without_tests.cmd new file mode 100644 index 000000000..6f7ba14e0 --- /dev/null +++ b/build_without_tests.cmd @@ -0,0 +1,2 @@ +start mvn clean install -Dmaven.test.skip=true -P distributive +pause diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/KafkaConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/KafkaConfig.java index 34973fffa..58a707200 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/KafkaConfig.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/KafkaConfig.java @@ -1,18 +1,50 @@ package ru.spcex.clearing.account.config; import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; import ru.spcex.clearing.account.config.settings.AccountServiceSettings; +import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory; +import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory; +import ru.spcex.clearing.platform.messaging.service.RequestInfo; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; @Configuration public class KafkaConfig { @Autowired + @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Bean - public Consumer createProducer(AccountServiceSettings settings) { - return KafkaConsumerFactory.consumer(settings.getKafka()); + public Consumer createConsumer(AccountServiceSettings settings) { + return KafkaConsumerFactory.consumer(settings.getKafkaConsumer()); + } + + @Autowired + @Bean + public Producer createProducer(AccountServiceSettings settings) { + return KafkaProducerFactory.producer(settings.getKafkaProducer()); + } + + @Autowired + @Bean + public KafkaSender kafkaSender(Producer kafkaProducer, ImdgProvider imdgProvider) { + ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); + return KafkaSender + .setup() + .producer(kafkaProducer) + .idGenerator(imdgIdGenerator::nextId) + .imdgProvider(s -> { + Imdg imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + return imdg::insert; + }) + .build(); } } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/settings/AccountServiceSettings.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/settings/AccountServiceSettings.java index f6f1166bb..1848ace41 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/settings/AccountServiceSettings.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/settings/AccountServiceSettings.java @@ -4,6 +4,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; 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; @Component @@ -11,7 +12,8 @@ import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams; @ConfigurationProperties("account-service") public class AccountServiceSettings { private HazelcastClientParams hazelcast; - private KafkaConsumerSettings kafka; + private KafkaConsumerSettings kafkaConsumer; + private KafkaProducerSettings kafkaProducer; public HazelcastClientParams getHazelcast() { return hazelcast; @@ -21,11 +23,19 @@ public class AccountServiceSettings { this.hazelcast = hazelcast; } - public KafkaConsumerSettings getKafka() { - return kafka; + public KafkaConsumerSettings getKafkaConsumer() { + return kafkaConsumer; } - public void setKafka(KafkaConsumerSettings kafka) { - this.kafka = kafka; + public void setKafkaConsumer(KafkaConsumerSettings kafkaConsumer) { + this.kafkaConsumer = kafkaConsumer; + } + + public KafkaProducerSettings getKafkaProducer() { + return kafkaProducer; + } + + public void setKafkaProducer(KafkaProducerSettings kafkaProducer) { + this.kafkaProducer = kafkaProducer; } } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java new file mode 100644 index 000000000..358390a8e --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java @@ -0,0 +1,76 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.account.Account; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdf01Request; +import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountSdfToStatementRequestPart; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class AccountService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg accountMap; + private final KafkaSender kafkaSender; + + @Autowired + public AccountService(Consumer kafkaQueue, ImdgProvider imdgProvider, KafkaSender kafkaSender) { + super(kafkaQueue); + this.accountMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.kafkaSender = kafkaSender; + } + + @Override + public void afterPropertiesSet() { + callback(AccountSdf01Request.class) + .setConsumer(this::accountNew) + .forDestination(Consts.ACCOUNT_NEW, callbacks::put); + init(); + } + + private void accountNew(BaseRequest userRequest) { + AccountSdf01Request req = userRequest.getRequestPayload(); + log.debug("AccountSdf01Request received"); + List accountToStatement = new ArrayList<>(); + for (AccountSdfRequestPart accountReq : req.getAccounts()) { + Account account = new Account(); + account.setAccount(accountReq.getAccount()); + //fixme account.setCompany(); + accountMap.insert(account); + AccountSdfToStatementRequestPart responsePart = responsePart(accountReq.getSdfId()); + accountToStatement.add(responsePart); + } + sendStatementRequestBack(req.getGroupingSdf01Id(), accountToStatement); + log.debug("successfully processed, grouping id={}, processed number={}", req.getGroupingSdf01Id(), accountToStatement.size()); + } + + private AccountSdfToStatementRequestPart responsePart(Long sdf01Id) { + AccountSdfToStatementRequestPart responsePart = new AccountSdfToStatementRequestPart(); + responsePart.setSdfId(sdf01Id); + responsePart.setErrorCode(null); + responsePart.setErrorText(null); + return responsePart; + } + + private void sendStatementRequestBack(Long groupingSdf01Id, List results) { + StatementRequest request = new StatementRequest(); + request.setGroupId(groupingSdf01Id); + request.setAccountCreationResults(results); + kafkaSender.sendRequestToQueue(Consts.STATEMENT_PROCESS, request); + } +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java index 37e39d377..3c1ad9ed6 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java @@ -1,6 +1,7 @@ package ru.spcex.clearing.account.service; import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -23,8 +24,8 @@ public class BankAccountService extends QueueConsumer implements InitializingBea private final Imdg bankAccountMap; @Autowired - public BankAccountService(Consumer kafkaQueue, ImdgProvider imdgProvider) { - super(kafkaQueue); + public BankAccountService(Consumer kafkaQueue, Producer kafkaProducer, ImdgProvider imdgProvider) { + super(kafkaQueue, kafkaProducer); this.bankAccountMap = imdgProvider.getImdg(IMDGDistributedNames.Map_BankAccount, BankAccount.class); } diff --git a/clearing-parent/account-service/src/main/resources/application.properties b/clearing-parent/account-service/src/main/resources/application.properties index f2d6fe4d8..b778da132 100644 --- a/clearing-parent/account-service/src/main/resources/application.properties +++ b/clearing-parent/account-service/src/main/resources/application.properties @@ -1,11 +1,19 @@ spring.main.web-application-type=none -account-service.hazelcast.cluster-members=127.0.0.1 +account-service.hazelcast.cluster-members=127.0.0.1:5701 account-service.hazelcast.login=dev account-service.hazelcast.password=dev-pass -account-service.kafka.bootstrap-servers=localhost:9092 -account-service.kafka.group-id=dev-group -account-service.kafka.enable-auto-commit=false -account-service.kafka.session-timeout-ms=30000 -account-service.kafka.auto-offset-reset=latest -account-service.kafka.linger-ms=1 -account-service.kafka.buffer-memory=33554432 \ No newline at end of file + +account-service.kafka-consumer.bootstrap-servers=localhost:9092 +account-service.kafka-consumer.group-id=dev-group-account-service +account-service.kafka-consumer.enable-auto-commit=true +account-service.kafka-consumer.session-timeout-ms=30000 +account-service.kafka-consumer.auto-offset-reset=latest +account-service.kafka-consumer.linger-ms=1 +account-service.kafka-consumer.buffer-memory=33554432 + +account-service.kafka-producer.bootstrap-servers=localhost:9092 +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 \ No newline at end of file diff --git a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java index 027c1d3e6..14077bfac 100644 --- a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java +++ b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java @@ -6,6 +6,7 @@ import com.hazelcast.core.IMap; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.MockConsumer; import org.apache.kafka.clients.consumer.OffsetResetStrategy; +import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.common.TopicPartition; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -47,10 +48,12 @@ public class BankAccountServiceTest { @Qualifier("hazelcastServiceTest") private HazelcastService hazelcastServiceTest; private MockConsumer mockConsumer; + private MockProducer mockProducer; @BeforeEach void setUp() { mockConsumer = new MockConsumer<>(OffsetResetStrategy.EARLIEST); + mockProducer = new MockProducer<>(); } /** @@ -118,7 +121,7 @@ public class BankAccountServiceTest { //ACT //service set up - BankAccountService bankAccountService = new BankAccountService(mockConsumer, hazelcastServiceTest); + BankAccountService bankAccountService = new BankAccountService(mockConsumer, mockProducer, hazelcastServiceTest); Thread.sleep(10000); //callbacks set up bankAccountService.afterPropertiesSet(); @@ -220,7 +223,7 @@ public class BankAccountServiceTest { //ACT //service set up - BankAccountService bankAccountService = new BankAccountService(mockConsumer, hazelcastServiceTest); + BankAccountService bankAccountService = new BankAccountService(mockConsumer, mockProducer, hazelcastServiceTest); Thread.sleep(10000); //callbacks set up bankAccountService.afterPropertiesSet(); @@ -304,7 +307,7 @@ public class BankAccountServiceTest { //ACT //service set up - BankAccountService bankAccountService = new BankAccountService(mockConsumer, hazelcastServiceTest); + BankAccountService bankAccountService = new BankAccountService(mockConsumer, mockProducer, hazelcastServiceTest); Thread.sleep(10000); //callbacks set up bankAccountService.afterPropertiesSet(); diff --git a/clearing-parent/backend-api/pom.xml b/clearing-parent/backend-api/pom.xml index 1eb563bed..ad0714978 100644 --- a/clearing-parent/backend-api/pom.xml +++ b/clearing-parent/backend-api/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 backend-api @@ -8,12 +8,12 @@ Clearing backend API module jar - - clearing-parent + + clearing-parent ru.spcex.clearing SPCEX-1.0.0.0 - + 17.0.1 @@ -25,9 +25,9 @@ spring-boot-starter-web - org.springframework.boot - spring-boot-starter-security - + org.springframework.boot + spring-boot-starter-security + org.keycloak keycloak-spring-boot-starter @@ -53,6 +53,14 @@ ru.spcex.clearing classes + + ru.spcex.clearing + dictionary + + + ru.spcex.platform + platform-enum + org.springframework @@ -74,18 +82,17 @@ assertj-core test - - org.keycloak.bom - keycloak-adapter-bom - ${keycloak-spring-boot-starter.version} - pom - import - + org.keycloak.bom + keycloak-adapter-bom + ${keycloak-spring-boot-starter.version} + pom + import + @@ -96,6 +103,7 @@ application.properties keycloak.json + meta/** false @@ -117,6 +125,59 @@ + + org.codehaus.mojo + xml-maven-plugin + + + + transform + + + + + + + src/main/resources/meta + + meta.server.xslt + + src/main/resources/meta/meta.server.xslt + + + .json + + + + + + + + maven-resources-plugin + + + copy-meta + process-classes + + copy-resources + + + ${basedir}/src/main/resources + + + ${basedir}/target/generated-resources/xml/xslt + + meta.json + + false + + + + + + + org.apache.maven.plugins maven-surefire-plugin diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/KafkaConfig.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/KafkaConfig.java index f64045cb9..9046c9bc8 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/KafkaConfig.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/KafkaConfig.java @@ -1,5 +1,8 @@ package ru.spcex.clearing.backendapi.config; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.consumer.OffsetResetStrategy; import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.clients.producer.Producer; import org.springframework.beans.factory.annotation.Autowired; @@ -7,6 +10,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import ru.spcex.clearing.backendapi.config.element.BackendApiSettings; +import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory; import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory; @Configuration @@ -16,7 +20,7 @@ public class KafkaConfig { @Autowired @Bean public Producer createProducer(BackendApiSettings settings) { - return KafkaProducerFactory.producer(settings.getKafka()); + return KafkaProducerFactory.producer(settings.getKafkaProducer()); } @Profile("kafkaDisabled") @@ -25,4 +29,17 @@ public class KafkaConfig { return new MockProducer<>(true, (topic, data) -> data != null ? data.getBytes() : new byte[0], (topic, data) -> data.toString().getBytes()); } + @Profile("!kafkaDisabled") + @Autowired + @Bean + public Consumer createConsumer(BackendApiSettings settings) { + return KafkaConsumerFactory.consumer(settings.getKafkaConsumer()); + } + + @Profile("kafkaDisabled") + @Bean + public Consumer createConsumerMock() { + return new MockConsumer<>(OffsetResetStrategy.NONE); + } + } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/MetaConfiguration.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/MetaConfiguration.java new file mode 100644 index 000000000..96e961be5 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/MetaConfiguration.java @@ -0,0 +1,21 @@ +package ru.spcex.clearing.backendapi.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; + +import java.io.IOException; +import java.nio.file.Files; + +@Configuration +public class MetaConfiguration { + @Value("file:${spring.config.location}/meta.json") + private Resource meta; + + @Bean("metaJson") + public String metaJsonConfiguration() throws IOException { + if (!meta.isReadable()) throw new IllegalStateException("cannot read meta.json from spring.config.location"); + return Files.readString(meta.getFile().toPath()); + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java index 005fa63aa..a3a296a94 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/WebConfig.java @@ -2,8 +2,10 @@ package ru.spcex.clearing.backendapi.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.web.server.Cookie; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.boot.web.servlet.server.CookieSameSiteSupplier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; @@ -12,6 +14,7 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.context.request.RequestContextListener; import org.springframework.web.servlet.config.annotation.*; +import ru.spcex.clearing.backendapi.config.element.BackendApiSettings; import java.util.List; import java.util.function.Consumer; @@ -23,10 +26,14 @@ import java.util.function.Consumer; @CrossOrigin public class WebConfig implements WebMvcConfigurer { private final MappingJackson2HttpMessageConverter customJsonHttpConverter; + private final String sameSite; @Autowired - public WebConfig(@Qualifier("customJsonHttpConverter") MappingJackson2HttpMessageConverter customJsonHttpConverter) { + public WebConfig(@Qualifier("customJsonHttpConverter") MappingJackson2HttpMessageConverter customJsonHttpConverter, + BackendApiSettings backendSettings + ) { this.customJsonHttpConverter = customJsonHttpConverter; + this.sameSite = backendSettings.getSecurity().getSameSite(); } @Override @@ -75,4 +82,19 @@ public class WebConfig implements WebMvcConfigurer { public RequestContextListener requestContextListener() { return new RequestContextListener(); } + + @Bean + public CookieSameSiteSupplier applicationCookieSameSiteSupplier() { + if (sameSite == null) { + return null; + } else if (sameSite.equalsIgnoreCase(Cookie.SameSite.NONE.attributeValue())) { + return CookieSameSiteSupplier.ofNone(); + } else if (sameSite.equalsIgnoreCase(Cookie.SameSite.LAX.attributeValue())) { + return CookieSameSiteSupplier.ofNone(); + } else if (sameSite.equalsIgnoreCase(Cookie.SameSite.STRICT.attributeValue())) { + return CookieSameSiteSupplier.ofStrict(); + } else { + throw new IllegalStateException("unknown SameSite setting"); + } + } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java index 422d18323..79ba99f2d 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/config/element/BackendApiSettings.java @@ -4,6 +4,7 @@ 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.SecuritySettings; +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; @@ -12,7 +13,8 @@ import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams; @ConfigurationProperties("backend-api") public class BackendApiSettings { private HazelcastClientParams hazelcast; - private KafkaProducerSettings kafka; + private KafkaProducerSettings kafkaProducer; + private KafkaConsumerSettings kafkaConsumer; private SecuritySettings security; private String exampleSetting; @@ -24,12 +26,20 @@ public class BackendApiSettings { this.hazelcast = hazelcast; } - public KafkaProducerSettings getKafka() { - return kafka; + public KafkaProducerSettings getKafkaProducer() { + return kafkaProducer; } - public void setKafka(KafkaProducerSettings kafka) { - this.kafka = kafka; + public void setKafkaProducer(KafkaProducerSettings kafkaProducer) { + this.kafkaProducer = kafkaProducer; + } + + public KafkaConsumerSettings getKafkaConsumer() { + return kafkaConsumer; + } + + public void setKafkaConsumer(KafkaConsumerSettings kafkaConsumer) { + this.kafkaConsumer = kafkaConsumer; } public String getExampleSetting() { diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/QueueExceptionHandler.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/QueueExceptionHandler.java index f2c2036a9..70dafb130 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/QueueExceptionHandler.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/QueueExceptionHandler.java @@ -39,7 +39,7 @@ public class QueueExceptionHandler extends ResponseEntityExceptionHandler { @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public BasicSpcexResponse handleValidationException(ActionValidationException e) { - log.error("Default scoring exception handler: {}", ExceptionUtils.getStackTrace(e)); + log.error("Default exception handler: {}", ExceptionUtils.getStackTrace(e)); EnumMessage firstError = e.getErrors().iterator().next(); BasicSpcexResponse errorResponse = new BasicSpcexResponse(); errorResponse.setCode(firstError.getSubject().getId()); @@ -55,7 +55,7 @@ public class QueueExceptionHandler extends ResponseEntityExceptionHandler { UnrecognizedPropertyException jacksonException = (UnrecognizedPropertyException) ex.getCause(); message = new EnumMessage(BackEndError.UnknownJsonProperty, jacksonException.getPropertyName()); } catch (ClassCastException e) { - log.error(ExceptionUtils.getStackTrace(e)); + log.error(ExceptionUtils.getStackTrace(ex)); message = new EnumMessage(BackEndError.FailedToReadHttpMessage); } errorResponse.setCode(message.getSubject().getId()); @@ -68,7 +68,7 @@ public class QueueExceptionHandler extends ResponseEntityExceptionHandler { @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ResponseBody public BasicSpcexResponse handleDefault(Throwable e) { - log.error("Default scoring exception handler: {}", ExceptionUtils.getStackTrace(e)); + log.error("Default exception handler: {}", ExceptionUtils.getStackTrace(e)); BasicSpcexResponse errorResponse = new BasicSpcexResponse(); errorResponse.setCode(-1); errorResponse.setMessage("internal server error"); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/EditClearingMemberCategoryController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/EditClearingMemberCategoryController.java index ddb708f4d..c97c71b17 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/EditClearingMemberCategoryController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/EditClearingMemberCategoryController.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.*; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; +import ru.spcex.clearing.backendapi.controller.request.cud.company.ClearingMemberCategoryNewAction; import ru.spcex.clearing.backendapi.controller.request.cud.company.ClearingMemberCategoryUpdateAction; import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse; @@ -34,6 +35,16 @@ public class EditClearingMemberCategoryController extends AbstractQueueControlle this.stateLoader = stateLoader; } + @ApiOperation(value = "new clearing category.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse add( + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody ClearingMemberCategoryNewAction clearingMemberCategoryNewAction) throws ExecutionException, InterruptedException { + return processRequest(Consts.DESTINATION_CLEARING_MEMBER_CATEGORY_NEW, clearingMemberCategoryNewAction); + } + @ApiOperation(value = "update clearing member category.") @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) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/TaskRunnerController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/TaskRunnerController.java index a57d0d4f8..b76a1f163 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/TaskRunnerController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/TaskRunnerController.java @@ -1,28 +1,49 @@ package ru.spcex.clearing.backendapi.controller.queue.scheduler; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; 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 org.springframework.web.bind.annotation.*; import ru.clearing.classes.statics.data.scheduler.TaskRunner; +import ru.clearing.classes.statics.data.user.User; +import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; +import ru.spcex.clearing.backendapi.controller.request.cud.schedule.TaskRunnerNew; +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.schedule.TaskRunnerBackendGetAll; +import ru.spcex.clearing.backendapi.errors.NotFound404Exception; +import ru.spcex.clearing.backendapi.security.KeycloakUtils; +import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IMessageResolver; import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ExecutionException; @Controller -@RequestMapping("/schedule/task-runners") -public class TaskRunnerController { +@RequestMapping("/task-runners") +public class TaskRunnerController extends AbstractQueueController { private final IStateLoader stateLoader; + private final Imdg userImdg; @Autowired - public TaskRunnerController(IStateLoader stateLoader) { + public TaskRunnerController(IStateLoader stateLoader, IOperator operator, ImdgProvider imdgProvider) { + super(operator); this.stateLoader = stateLoader; + this.userImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class); } @ApiOperation(value = "get all TaskRunners.") @@ -35,4 +56,36 @@ public class TaskRunnerController { response.fromEntity(all); return response; } + + @ApiOperation(value = "create task runner.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/{task-code}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse add(@ApiParam(value = "Код задания из taskDictionary", required = true, example = "ABLK") + @PathVariable("task-code") String dictionaryName) throws ExecutionException, InterruptedException { + TaskRunnerNew taskRunnerCommand = new TaskRunnerNew(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String username = KeycloakUtils.getUserNameFromAuthentication(authentication); + User user = userImdg.getSingleObjectByFieldValues(Map.of("identifier", username)); + if (user == null) { + throw new IllegalStateException("cannot obtain userId from logged in user " + username); + } + taskRunnerCommand.setTask(dictionaryName); + taskRunnerCommand.setUserId(user.getId()); + return processRequest(Consts.TASK_RUNNER_NEW, taskRunnerCommand); + } + + @Autowired + private IMessageResolver errorResolver; + + @ResponseStatus(value = HttpStatus.NOT_FOUND) + @ResponseBody + @ExceptionHandler(NotFound404Exception.class) + public BasicSpcexResponse conflict(NotFound404Exception ex) { + BasicSpcexResponse response = new BasicSpcexResponse(); + EnumMessage message = ex.getError(); + response.setCode(message.getSubject().getId()); + response.setMessage(errorResolver.resolve(message)); + return response; + } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/user/UserSettingsSessionController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/user/UserSettingsSessionController.java deleted file mode 100644 index 549d04aee..000000000 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/user/UserSettingsSessionController.java +++ /dev/null @@ -1,38 +0,0 @@ -package ru.spcex.clearing.backendapi.controller.queue.user; - -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import org.springframework.beans.factory.annotation.Autowired; -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.clearing.classes.statics.data.user.UserSettings; -import ru.spcex.clearing.backendapi.controller.response.entity.user.UserSettingsBackendGetAll; -import ru.spcex.clearing.backendapi.service.IStateLoader; -import ru.spcex.clearing.imdg.IMDGDistributedNames; - -import java.util.Collection; - -@Controller -@RequestMapping("/user-settings") -public class UserSettingsSessionController { - private final IStateLoader stateLoader; - - @Autowired - public UserSettingsSessionController(IStateLoader stateLoader) { - this.stateLoader = stateLoader; - } - - @ApiOperation(value = "get all user settings.") - @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = UserSettingsBackendGetAll.class)}) - @RequestMapping(method = RequestMethod.GET) - @ResponseBody - public UserSettingsBackendGetAll getAll() { - Collection all = stateLoader.getAll(IMDGDistributedNames.Map_UserSettings, UserSettings.class); - var response = new UserSettingsBackendGetAll(); - response.fromEntity(all); - return response; - } -} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/utilities/UserSettingsController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/utilities/UserSettingsController.java new file mode 100644 index 000000000..7a52b494b --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/utilities/UserSettingsController.java @@ -0,0 +1,76 @@ +package ru.spcex.clearing.backendapi.controller.queue.utilities; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +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.user.User; +import ru.clearing.classes.statics.data.user.UserSettings; +import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; +import ru.spcex.clearing.backendapi.controller.request.cud.utilities.UserSettingsUpdateAction; +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.user.UserSettingsBackendGetAll; +import ru.spcex.clearing.backendapi.security.KeycloakUtils; +import ru.spcex.clearing.backendapi.service.IOperator; +import ru.spcex.clearing.backendapi.service.IStateLoader; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +@Controller +@RequestMapping("/utilities/user-settings") +public class UserSettingsController extends AbstractQueueController { + private final IStateLoader stateLoader; + private final Imdg userImdg; + + @Autowired + public UserSettingsController(IOperator operator, IStateLoader stateLoader, ImdgProvider imdgProvider) { + super(operator); + this.stateLoader = stateLoader; + this.userImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class); + } + + @ApiOperation(value = "get all user settings.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = UserSettingsBackendGetAll.class)}) + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public UserSettingsBackendGetAll getAll() { + Collection all = stateLoader.getAll(IMDGDistributedNames.Map_UserSettings, UserSettings.class); + var response = new UserSettingsBackendGetAll(); + response.fromEntity(all); + return response; + } + + @ApiOperation(value = "update user settings.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse update( + @ApiParam(value = "Новые значения полей объекта.", required = true) + @RequestBody UserSettingsUpdateAction userSettingsUpdateAction) throws ExecutionException, InterruptedException { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String username = KeycloakUtils.getUserNameFromAuthentication(authentication); + User user = userImdg.getSingleObjectByFieldValues(Map.of("identifier", username)); + if (user == null) { + throw new IllegalStateException("cannot obtain userId from logged in user " + username); + } + userSettingsUpdateAction.setUserId(user.getId()); + return processRequest(Consts.USER_SETTINGS_UPDATE, userSettingsUpdateAction); + } + +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/common/CommonDeleteAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/common/CommonDeleteAction.java index 7b09743f8..c2c72cd46 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/common/CommonDeleteAction.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/common/CommonDeleteAction.java @@ -5,13 +5,14 @@ import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.errors.BackEndError; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; +import ru.spcex.platform.classes.base.interfaces.WithId; import ru.spcex.platform.utils.enumeration.EnumMessage; import java.util.Collection; import java.util.Collections; import java.util.List; -public class CommonDeleteAction implements IAction { +public class CommonDeleteAction implements IAction, WithId { @JsonProperty public Long id; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ClearingMemberCategoryNewAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ClearingMemberCategoryNewAction.java new file mode 100644 index 000000000..d220f0f11 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ClearingMemberCategoryNewAction.java @@ -0,0 +1,48 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.company; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.company.ClearingMemberCategoryNewRequest; + +public class ClearingMemberCategoryNewAction implements IAction { + + @ApiModelProperty(value = "Идентификатор компании", example = "1234") + @JsonProperty + private Long companyId; + + @ApiModelProperty(value = "Идентификатор категории участника клиринга", example = "ABCD") + @JsonProperty + private String clearingMemberCategory; + + @Override + public ClearingMemberCategoryNewRequest toRequest() { + ClearingMemberCategoryNewRequest request = new ClearingMemberCategoryNewRequest(); + request.setCompanyId(companyId); + request.setClearingMemberCategory(this.clearingMemberCategory); + return request; + } + + @ApiModelProperty(hidden = true) + @Override + public ActionType getActionType() { + return ActionType.NEW; + } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + public String getClearingMemberCategory() { + return clearingMemberCategory; + } + + public void setClearingMemberCategory(String clearingMemberCategory) { + this.clearingMemberCategory = clearingMemberCategory; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/TaskRunnerNew.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/TaskRunnerNew.java new file mode 100644 index 000000000..6c10f0c70 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/TaskRunnerNew.java @@ -0,0 +1,60 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.schedule; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.backendapi.errors.BackEndError; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.schedule.TaskRunnerCommandRequest; +import ru.spcex.platform.utils.enumeration.EnumMessage; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class TaskRunnerNew implements IAction { + @ApiModelProperty(value = "Идентификатор единоличного исполнительного органа", example = "ABCD") + @JsonProperty + private String task; + + @JsonIgnore + private Long userId; + + @Override + public TaskRunnerCommandRequest toRequest() { + TaskRunnerCommandRequest taskRunnerCommandRequest = new TaskRunnerCommandRequest(); + taskRunnerCommandRequest.setTaskName(task); + taskRunnerCommandRequest.setUserId(userId); + return taskRunnerCommandRequest; + } + + @Override + public ActionType getActionType() { + return ActionType.NEW; + } + + @Override + public Collection validate() { + if (task == null) { + return List.of(new EnumMessage(BackEndError.ValidationError,"url parameter 'task-code'")); + } + return Collections.emptyList(); + } + + public String getTask() { + return task; + } + + public void setTask(String task) { + this.task = task; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/MoneyMarketSecurityNewAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/MoneyMarketSecurityNewAction.java index 66de901c0..829b85d86 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/MoneyMarketSecurityNewAction.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/securities/MoneyMarketSecurityNewAction.java @@ -8,10 +8,10 @@ import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.errors.BackEndError; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest; -import ru.spcex.clearing.platform.messaging.domain.json.deserialize.InstantDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; import ru.spcex.platform.utils.enumeration.EnumMessage; -import java.time.Instant; +import java.time.LocalDate; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -19,14 +19,14 @@ import java.util.List; public class MoneyMarketSecurityNewAction implements IAction { @ApiModelProperty(value = "Дата начала действия", example = "2022-01-20") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant startDate; + public LocalDate startDate; @ApiModelProperty(value = "Дата окончания действия", example = "2022-02-21") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant endDate; + public LocalDate endDate; @ApiModelProperty(value = "Номинал", example = "20.5") @JsonProperty public Double nominalValue; @@ -73,19 +73,19 @@ public class MoneyMarketSecurityNewAction implements IAction { +public class MoneyMarketSecurityUpdateAction implements IAction, WithId { @ApiModelProperty(hidden = true) @JsonProperty public Long id; @ApiModelProperty(value = "Дата окончания действия", example = "2022-02-21") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant endDate; + public LocalDate endDate; @ApiModelProperty(value = "Номинал", example = "20.5") @JsonProperty public Double nominalValue; @@ -56,11 +57,11 @@ public class MoneyMarketSecurityUpdateAction implements IAction { @ApiModelProperty(value = "Ключевая ставка ЦБ РФ", example = "12.5") @JsonProperty - public Double keyRate; + public BigDecimal keyRate; @ApiModelProperty(value = "Дата начала действия ключевой ставки", example = "2022-01-20") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant startDate; + public LocalDate startDate; @ApiModelProperty(value = "Дата окончания действия ключевой ставки", example = "2022-04-20") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant endDate; + public LocalDate endDate; @ApiModelProperty(value = "Документ ЦБ", example = "Lorem ipsum") @JsonProperty public String document; @@ -57,27 +58,27 @@ public class KeyRateNewAction implements IAction { return req; } - public Double getKeyRate() { + public BigDecimal getKeyRate() { return keyRate; } - public void setKeyRate(Double keyRate) { + public void setKeyRate(BigDecimal keyRate) { this.keyRate = keyRate; } - public Instant getStartDate() { + public LocalDate getStartDate() { return startDate; } - public void setStartDate(Instant startDate) { + public void setStartDate(LocalDate startDate) { this.startDate = startDate; } - public Instant getEndDate() { + public LocalDate getEndDate() { return endDate; } - public void setEndDate(Instant endDate) { + public void setEndDate(LocalDate endDate) { this.endDate = endDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/KeyRateUpdateAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/KeyRateUpdateAction.java index f15dfe623..4c5a1b3d2 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/KeyRateUpdateAction.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/KeyRateUpdateAction.java @@ -7,9 +7,10 @@ import io.swagger.annotations.ApiModelProperty; import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.cud.utilities.KeyRateUpdateRequest; -import ru.spcex.clearing.platform.messaging.domain.json.deserialize.InstantDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; -import java.time.Instant; +import java.math.BigDecimal; +import java.time.LocalDate; public class KeyRateUpdateAction implements IAction { @ApiModelProperty(hidden = true) @@ -17,17 +18,17 @@ public class KeyRateUpdateAction implements IAction { public Long id; @ApiModelProperty(value = "Ключевая ставка ЦБ РФ", example = "12.5") @JsonProperty - public Double keyRate; + public BigDecimal keyRate; @ApiModelProperty(value = "Дата начала действия ключевой ставки", example = "2022-01-20") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant startDate; + public LocalDate startDate; @ApiModelProperty(value = "Дата окончания действия ключевой ставки", example = "2022-04-20") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow") - @JsonDeserialize(using = InstantDeserializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) @JsonProperty - public Instant endDate; + public LocalDate endDate; @ApiModelProperty(value = "Документ ЦБ", example = "Lorem ipsum") @JsonProperty public String document; @@ -49,27 +50,27 @@ public class KeyRateUpdateAction implements IAction { return req; } - public Double getKeyRate() { + public BigDecimal getKeyRate() { return keyRate; } - public void setKeyRate(Double keyRate) { + public void setKeyRate(BigDecimal keyRate) { this.keyRate = keyRate; } - public Instant getStartDate() { + public LocalDate getStartDate() { return startDate; } - public void setStartDate(Instant startDate) { + public void setStartDate(LocalDate startDate) { this.startDate = startDate; } - public Instant getEndDate() { + public LocalDate getEndDate() { return endDate; } - public void setEndDate(Instant endDate) { + public void setEndDate(LocalDate endDate) { this.endDate = endDate; } @@ -77,6 +78,10 @@ public class KeyRateUpdateAction implements IAction { return document; } + public void setDocument(String document) { + this.document = document; + } + public Long getId() { return id; } @@ -84,8 +89,4 @@ public class KeyRateUpdateAction implements IAction { public void setId(Long id) { this.id = id; } - - public void setDocument(String document) { - this.document = document; - } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/UserSettingsUpdateAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/UserSettingsUpdateAction.java new file mode 100644 index 000000000..cc4bbf384 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/utilities/UserSettingsUpdateAction.java @@ -0,0 +1,54 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.utilities; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.utilities.UserSettingsUpdateRequest; + +public class UserSettingsUpdateAction implements IAction { + @ApiModelProperty(hidden = true) + @JsonProperty + public Long userId; + + @JsonProperty + public String version; + public String json; + + @JsonProperty("json") + public void unpackRawJson(JsonNode json) { + this.json = json.toString(); + } + + @ApiModelProperty(hidden = true) + @Override + public ActionType getActionType() { + return ActionType.UPDATE; + } + + @Override + public UserSettingsUpdateRequest toRequest() { + var req = new UserSettingsUpdateRequest(); + req.setVersion(version); + req.setJson(json); + req.setUserId(userId); + return req; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/account/AccountBackendGetAll.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/account/AccountBackendGetAll.java index f05c0ccfd..03bf7a7e4 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/account/AccountBackendGetAll.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/account/AccountBackendGetAll.java @@ -17,18 +17,6 @@ public class AccountBackendGetAll extends BasicSpcexResponse { @ApiModelProperty(value = "Полезная нагрузка") private AccountBackendPayload payload = new AccountBackendPayload(); - private static class AccountBackendPayload { - private List items = new ArrayList<>(); - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } - } - public AccountBackendPayload getPayload() { return payload; } @@ -45,7 +33,7 @@ public class AccountBackendGetAll extends BasicSpcexResponse { singleItem.setAccount(account.getAccount()); singleItem.setAccountType(account.getAccountType()); singleItem.setRelationId(account.getRelationId()); - singleItem.setStatus(account.getStatus()); + singleItem.setStatus(account.getAccountStatus()); singleItem.setProcessingSign(account.getProcessingSign()); singleItem.setCreated(account.getCreated()); singleItem.setUpdated(account.getUpdated()); @@ -53,4 +41,16 @@ public class AccountBackendGetAll extends BasicSpcexResponse { } } + private static class AccountBackendPayload { + private List items = new ArrayList<>(); + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + } + } \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetAll.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetAll.java index c657efe39..0c6948dbc 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetAll.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetAll.java @@ -51,26 +51,23 @@ public class CompanyBackendGetAll extends BasicSpcexResponse { singleItem.setFullName(company.getFullName()); singleItem.setCreated(company.getCreated()); singleItem.setUpdated(company.getUpdated()); - CompanyBackendGetFields.CompanyInfoFields companyInfoFields = new CompanyBackendGetFields.CompanyInfoFields(); CompanyInfo profile = company.getProfile(); - companyInfoFields.setId(profile.getId()); - companyInfoFields.setCompanyId(profile.getCompanyId()); - companyInfoFields.setClearingMemberCategory(profile.getClearingMemberCategory()); - companyInfoFields.setCorporationSoleType(profile.getCorporationSoleType()); - companyInfoFields.setCountryCode(profile.getCountryCode()); - companyInfoFields.setDescription(profile.getDescription()); - companyInfoFields.setProfessionalSign(profile.getProfessionalSign()); - companyInfoFields.setLegalKind(profile.getLegalKind()); - companyInfoFields.setOrganizationType(profile.getOrganizationType()); - companyInfoFields.setResidence(profile.getResidence()); - companyInfoFields.setShortName(profile.getShortName()); - companyInfoFields.setFullName(profile.getFullName()); - companyInfoFields.setShortNameEng(profile.getShortNameEng()); - companyInfoFields.setFullNameEng(profile.getFullNameEng()); - companyInfoFields.setTradingCode(profile.getTradingCode()); - companyInfoFields.setClearingCode(profile.getClearingCode()); - companyInfoFields.setRegistrationCode(profile.getRegistrationCode()); - singleItem.setProfile(companyInfoFields); + if (profile != null) { + singleItem.setCorporationSoleType(profile.getCorporationSoleType()); + singleItem.setCountryCode(profile.getCountryCode()); + singleItem.setDescription(profile.getDescription()); + singleItem.setProfessionalSign(profile.getProfessionalSign()); + singleItem.setLegalKind(profile.getLegalKind()); + singleItem.setOrganizationType(profile.getOrganizationType()); + singleItem.setResidence(profile.getResidence()); + singleItem.setShortName(profile.getShortName()); + singleItem.setFullName(profile.getFullName()); + singleItem.setShortNameEng(profile.getShortNameEng()); + singleItem.setFullNameEng(profile.getFullNameEng()); + singleItem.setTradingCode(profile.getTradingCode()); + singleItem.setClearingCode(profile.getClearingCode()); + singleItem.setRegistrationCode(profile.getRegistrationCode()); + } payload.getItems().add(singleItem); } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetFields.java index b07140d91..97b4fb072 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendGetFields.java @@ -28,7 +28,25 @@ public class CompanyBackendGetFields { @JsonProperty private Instant updated; @JsonProperty - private CompanyInfoFields profile; + private String clearingMemberCategory; // ref CHAR(4), + @JsonProperty + private String corporationSoleType; // ref CHAR(4), + @JsonProperty + private String countryCode; //ref CHAR(4), + @JsonProperty + private String description; + @JsonProperty + private String professionalSign; // ref CHAR(4), + @JsonProperty + private String legalKind; // ref CHAR(4), + @JsonProperty + private String organizationType; // ref CHAR(4), + @JsonProperty + private String residence; // ref CHAR(4), + @JsonProperty + private String shortNameEng; + @JsonProperty + private String fullNameEng; public Long getId() { return id; @@ -102,184 +120,256 @@ public class CompanyBackendGetFields { this.updated = updated; } - public CompanyInfoFields getProfile() { - return profile; + public String getClearingMemberCategory() { + return clearingMemberCategory; } - public void setProfile(CompanyInfoFields profile) { - this.profile = profile; + public void setClearingMemberCategory(String clearingMemberCategory) { + this.clearingMemberCategory = clearingMemberCategory; } - static class CompanyInfoFields { - @JsonProperty - private Long id; - @JsonProperty - private Long companyId; // Company.CompanyInfo.companyId = CompanyInfo.id - @JsonProperty - private String clearingMemberCategory; // ref CHAR(4), - @JsonProperty - private String corporationSoleType; // ref CHAR(4), - @JsonProperty - private String countryCode; //ref CHAR(4), - @JsonProperty - private String description; - @JsonProperty - private String professionalSign; // ref CHAR(4), - @JsonProperty - private String legalKind; // ref CHAR(4), - @JsonProperty - private String organizationType; // ref CHAR(4), - @JsonProperty - private String residence; // ref CHAR(4), - @JsonProperty - private String shortName; - @JsonProperty - private String fullName; - @JsonProperty - private String shortNameEng; - @JsonProperty - private String fullNameEng; - @JsonProperty - private String tradingCode; - @JsonProperty - private String clearingCode; - @JsonProperty - private String registrationCode; - - public Long getCompanyId() { - return companyId; - } - - public void setCompanyId(Long companyId) { - this.companyId = companyId; - } - - public String getClearingMemberCategory() { - return clearingMemberCategory; - } - - public void setClearingMemberCategory(String clearingMemberCategory) { - this.clearingMemberCategory = clearingMemberCategory; - } - - public String getCorporationSoleType() { - return corporationSoleType; - } - - public void setCorporationSoleType(String corporationSoleType) { - this.corporationSoleType = corporationSoleType; - } - - public String getCountryCode() { - return countryCode; - } - - public void setCountryCode(String countryCode) { - this.countryCode = countryCode; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getProfessionalSign() { - return professionalSign; - } - - public void setProfessionalSign(String professionalSign) { - this.professionalSign = professionalSign; - } - - public String getLegalKind() { - return legalKind; - } - - public void setLegalKind(String legalKind) { - this.legalKind = legalKind; - } - - public String getOrganizationType() { - return organizationType; - } - - public void setOrganizationType(String organizationType) { - this.organizationType = organizationType; - } - - public String getResidence() { - return residence; - } - - public void setResidence(String residence) { - this.residence = residence; - } - - public String getShortName() { - return shortName; - } - - public void setShortName(String shortName) { - this.shortName = shortName; - } - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public String getShortNameEng() { - return shortNameEng; - } - - public void setShortNameEng(String shortNameEng) { - this.shortNameEng = shortNameEng; - } - - public String getFullNameEng() { - return fullNameEng; - } - - public void setFullNameEng(String fullNameEng) { - this.fullNameEng = fullNameEng; - } - - public String getTradingCode() { - return tradingCode; - } - - public void setTradingCode(String tradingCode) { - this.tradingCode = tradingCode; - } - - public String getClearingCode() { - return clearingCode; - } - - public void setClearingCode(String clearingCode) { - this.clearingCode = clearingCode; - } - - public String getRegistrationCode() { - return registrationCode; - } - - public void setRegistrationCode(String registrationCode) { - this.registrationCode = registrationCode; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } + public String getCorporationSoleType() { + return corporationSoleType; } + + public void setCorporationSoleType(String corporationSoleType) { + this.corporationSoleType = corporationSoleType; + } + + public String getCountryCode() { + return countryCode; + } + + public void setCountryCode(String countryCode) { + this.countryCode = countryCode; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getProfessionalSign() { + return professionalSign; + } + + public void setProfessionalSign(String professionalSign) { + this.professionalSign = professionalSign; + } + + public String getLegalKind() { + return legalKind; + } + + public void setLegalKind(String legalKind) { + this.legalKind = legalKind; + } + + public String getOrganizationType() { + return organizationType; + } + + public void setOrganizationType(String organizationType) { + this.organizationType = organizationType; + } + + public String getResidence() { + return residence; + } + + public void setResidence(String residence) { + this.residence = residence; + } + + public String getShortNameEng() { + return shortNameEng; + } + + public void setShortNameEng(String shortNameEng) { + this.shortNameEng = shortNameEng; + } + + public String getFullNameEng() { + return fullNameEng; + } + + public void setFullNameEng(String fullNameEng) { + this.fullNameEng = fullNameEng; + } + + // static class CompanyInfoFields { +// @JsonProperty +// private Long id; +// @JsonProperty +// private Long companyId; // Company.CompanyInfo.companyId = CompanyInfo.id +// @JsonProperty +// private String clearingMemberCategory; // ref CHAR(4), +// @JsonProperty +// private String corporationSoleType; // ref CHAR(4), +// @JsonProperty +// private String countryCode; //ref CHAR(4), +// @JsonProperty +// private String description; +// @JsonProperty +// private String professionalSign; // ref CHAR(4), +// @JsonProperty +// private String legalKind; // ref CHAR(4), +// @JsonProperty +// private String organizationType; // ref CHAR(4), +// @JsonProperty +// private String residence; // ref CHAR(4), +// @JsonProperty +// private String shortName; +// @JsonProperty +// private String fullName; +// @JsonProperty +// private String shortNameEng; +// @JsonProperty +// private String fullNameEng; +// @JsonProperty +// private String tradingCode; +// @JsonProperty +// private String clearingCode; +// @JsonProperty +// private String registrationCode; +// +// public Long getCompanyId() { +// return companyId; +// } +// +// public void setCompanyId(Long companyId) { +// this.companyId = companyId; +// } +// +// public String getClearingMemberCategory() { +// return clearingMemberCategory; +// } +// +// public void setClearingMemberCategory(String clearingMemberCategory) { +// this.clearingMemberCategory = clearingMemberCategory; +// } +// +// public String getCorporationSoleType() { +// return corporationSoleType; +// } +// +// public void setCorporationSoleType(String corporationSoleType) { +// this.corporationSoleType = corporationSoleType; +// } +// +// public String getCountryCode() { +// return countryCode; +// } +// +// public void setCountryCode(String countryCode) { +// this.countryCode = countryCode; +// } +// +// public String getDescription() { +// return description; +// } +// +// public void setDescription(String description) { +// this.description = description; +// } +// +// public String getProfessionalSign() { +// return professionalSign; +// } +// +// public void setProfessionalSign(String professionalSign) { +// this.professionalSign = professionalSign; +// } +// +// public String getLegalKind() { +// return legalKind; +// } +// +// public void setLegalKind(String legalKind) { +// this.legalKind = legalKind; +// } +// +// public String getOrganizationType() { +// return organizationType; +// } +// +// public void setOrganizationType(String organizationType) { +// this.organizationType = organizationType; +// } +// +// public String getResidence() { +// return residence; +// } +// +// public void setResidence(String residence) { +// this.residence = residence; +// } +// +// public String getShortName() { +// return shortName; +// } +// +// public void setShortName(String shortName) { +// this.shortName = shortName; +// } +// +// public String getFullName() { +// return fullName; +// } +// +// public void setFullName(String fullName) { +// this.fullName = fullName; +// } +// +// public String getShortNameEng() { +// return shortNameEng; +// } +// +// public void setShortNameEng(String shortNameEng) { +// this.shortNameEng = shortNameEng; +// } +// +// public String getFullNameEng() { +// return fullNameEng; +// } +// +// public void setFullNameEng(String fullNameEng) { +// this.fullNameEng = fullNameEng; +// } +// +// public String getTradingCode() { +// return tradingCode; +// } +// +// public void setTradingCode(String tradingCode) { +// this.tradingCode = tradingCode; +// } +// +// public String getClearingCode() { +// return clearingCode; +// } +// +// public void setClearingCode(String clearingCode) { +// this.clearingCode = clearingCode; +// } +// +// public String getRegistrationCode() { +// return registrationCode; +// } +// +// public void setRegistrationCode(String registrationCode) { +// this.registrationCode = registrationCode; +// } +// +// public Long getId() { +// return id; +// } +// +// public void setId(Long id) { +// this.id = id; +// } +// } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendInfoGetAll.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendInfoGetAll.java index ddb1692a7..effd0af08 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendInfoGetAll.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/CompanyBackendInfoGetAll.java @@ -43,7 +43,6 @@ public class CompanyBackendInfoGetAll extends BasicSpcexResponse { var singleItem = new CompanyBackendInfoGetFields(); singleItem.setId(companyInfo.getId()); singleItem.setCompanyId(companyInfo.getCompanyId()); - singleItem.setClearingMemberCategory(companyInfo.getClearingMemberCategory()); singleItem.setCorporationSoleType(companyInfo.getCorporationSoleType()); singleItem.setCountryCode(companyInfo.getCountryCode()); singleItem.setDescription(companyInfo.getDescription()); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/ProfileDocumentBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/ProfileDocumentBackendGetFields.java index 5b6c51d49..27cd18d89 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/ProfileDocumentBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/company/ProfileDocumentBackendGetFields.java @@ -2,9 +2,9 @@ package ru.spcex.clearing.backendapi.controller.response.entity.company; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; -import java.time.Instant; +import java.time.LocalDate; public class ProfileDocumentBackendGetFields { @JsonProperty @@ -14,8 +14,8 @@ public class ProfileDocumentBackendGetFields { @JsonProperty private String documentType; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant issueDate; + @JsonSerialize(using = LocalDateSerializer.class) + private LocalDate issueDate; @JsonProperty private String issuePlace; @JsonProperty @@ -29,11 +29,11 @@ public class ProfileDocumentBackendGetFields { @JsonProperty private String place; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant validFromDate; + @JsonSerialize(using = LocalDateSerializer.class) + private LocalDate validFromDate; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant validToDate; + @JsonSerialize(using = LocalDateSerializer.class) + private LocalDate validToDate; @JsonProperty private String link; @@ -61,11 +61,11 @@ public class ProfileDocumentBackendGetFields { this.documentType = documentType; } - public Instant getIssueDate() { + public LocalDate getIssueDate() { return issueDate; } - public void setIssueDate(Instant issueDate) { + public void setIssueDate(LocalDate issueDate) { this.issueDate = issueDate; } @@ -117,19 +117,19 @@ public class ProfileDocumentBackendGetFields { this.place = place; } - public Instant getValidFromDate() { + public LocalDate getValidFromDate() { return validFromDate; } - public void setValidFromDate(Instant validFromDate) { + public void setValidFromDate(LocalDate validFromDate) { this.validFromDate = validFromDate; } - public Instant getValidToDate() { + public LocalDate getValidToDate() { return validToDate; } - public void setValidToDate(Instant validToDate) { + public void setValidToDate(LocalDate validToDate) { this.validToDate = validToDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java new file mode 100644 index 000000000..3d6c11aeb --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java @@ -0,0 +1,49 @@ +package ru.spcex.clearing.backendapi.controller.response.entity.dictionary; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import ru.clearing.platform.dictionary.AbstractDictionary; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@ApiModel(description = "Ответ при получении объектов словаря.") +public class DictionaryBackendGetAll extends BasicSpcexResponse { + + @JsonProperty + @ApiModelProperty(value = "Полезная нагрузка") + private DictionaryBackendPayload payload = new DictionaryBackendPayload(); + + public void fromEntity(Collection dictionaryValues) { + var payload = this.getPayload(); + for (AbstractDictionary dictionaryValue : dictionaryValues) { + var singleItem = new DictionaryBackendGetFields(); + singleItem.fromEntity(dictionaryValue); + payload.getItems().add(singleItem); + } + } + + + private static class DictionaryBackendPayload { + private List items = new ArrayList<>(); + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + } + + public DictionaryBackendPayload getPayload() { + return payload; + } + + public void setPayload(DictionaryBackendPayload payload) { + this.payload = payload; + } +} \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java new file mode 100644 index 000000000..fa27898c9 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java @@ -0,0 +1,48 @@ +package ru.spcex.clearing.backendapi.controller.response.entity.dictionary; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import ru.clearing.platform.dictionary.AbstractDictionary; + +public class DictionaryBackendGetFields { + @JsonProperty + @ApiModelProperty(value = "Идентификатор", example = "1234") + private Long id; + @JsonProperty + @ApiModelProperty(value = "", example = "") + private String code; + @JsonProperty + @ApiModelProperty(value = "Имя банка", example = "Сбербанк") + private String name; + + public void fromEntity(AbstractDictionary dictionaryValue) { + this.id = dictionaryValue.getId(); + this.code = dictionaryValue.getCode(); + this.name = dictionaryValue.getName(); + } + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetSingleValue.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetSingleValue.java new file mode 100644 index 000000000..b58ccd807 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetSingleValue.java @@ -0,0 +1,30 @@ +package ru.spcex.clearing.backendapi.controller.response.entity.dictionary; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import ru.clearing.platform.dictionary.AbstractDictionary; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; + +@ApiModel(description = "Ответ при получении объекта BankAccount.") +public class DictionaryBackendGetSingleValue extends BasicSpcexResponse { + + @JsonProperty + @ApiModelProperty(value = "Поля объекта") + private DictionaryBackendGetFields payload; + + public DictionaryBackendGetFields getPayload() { + return payload; + } + + public void fromEntity(AbstractDictionary dictionaryValue) { + var payload = new DictionaryBackendGetFields(); + this.setPayload(payload); + payload.fromEntity(dictionaryValue); + } + + + public void setPayload(DictionaryBackendGetFields payload) { + this.payload = payload; + } +} \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerAllTodayBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerAllTodayBackendGetFields.java index 941b8b404..ae70af9f1 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerAllTodayBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerAllTodayBackendGetFields.java @@ -2,9 +2,11 @@ package ru.spcex.clearing.backendapi.controller.response.entity.schedule; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalTimeSerializer; -import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; public class SchedulerAllTodayBackendGetFields { @JsonProperty @@ -12,11 +14,11 @@ public class SchedulerAllTodayBackendGetFields { @JsonProperty private String task; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant taskTime; + @JsonSerialize(using = LocalTimeSerializer.class) + private LocalTime taskTime; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant clearingDate; + @JsonSerialize(using = LocalDateSerializer.class) + private LocalDate clearingDate; @JsonProperty private String market; @JsonProperty @@ -44,19 +46,19 @@ public class SchedulerAllTodayBackendGetFields { this.task = task; } - public Instant getTaskTime() { + public LocalTime getTaskTime() { return taskTime; } - public void setTaskTime(Instant taskTime) { + public void setTaskTime(LocalTime taskTime) { this.taskTime = taskTime; } - public Instant getClearingDate() { + public LocalDate getClearingDate() { return clearingDate; } - public void setClearingDate(Instant clearingDate) { + public void setClearingDate(LocalDate clearingDate) { this.clearingDate = clearingDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerBackendGetFields.java index 7220f301f..71561a8d1 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/SchedulerBackendGetFields.java @@ -3,8 +3,12 @@ package ru.spcex.clearing.backendapi.controller.response.entity.schedule; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalTimeSerializer; import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalTime; public class SchedulerBackendGetFields { @JsonProperty @@ -12,11 +16,11 @@ public class SchedulerBackendGetFields { @JsonProperty private String task; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant taskTime; + @JsonSerialize(using = LocalTimeSerializer.class) + private LocalTime taskTime; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant clearingDate; + @JsonSerialize(using = LocalDateSerializer.class) + private LocalDate clearingDate; @JsonProperty private String market; @JsonProperty @@ -46,19 +50,19 @@ public class SchedulerBackendGetFields { this.task = task; } - public Instant getTaskTime() { + public LocalTime getTaskTime() { return taskTime; } - public void setTaskTime(Instant taskTime) { + public void setTaskTime(LocalTime taskTime) { this.taskTime = taskTime; } - public Instant getClearingDate() { + public LocalDate getClearingDate() { return clearingDate; } - public void setClearingDate(Instant clearingDate) { + public void setClearingDate(LocalDate clearingDate) { this.clearingDate = clearingDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TimetableBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TimetableBackendGetFields.java index c3a53ba86..a348b0799 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TimetableBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TimetableBackendGetFields.java @@ -3,8 +3,10 @@ package ru.spcex.clearing.backendapi.controller.response.entity.schedule; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalTimeSerializer; import java.time.Instant; +import java.time.LocalTime; public class TimetableBackendGetFields { @JsonProperty @@ -12,8 +14,8 @@ public class TimetableBackendGetFields { @JsonProperty private String task; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant taskTime; + @JsonSerialize(using = LocalTimeSerializer.class) + private LocalTime taskTime; @JsonProperty private String taskStatus; @JsonProperty @@ -39,11 +41,11 @@ public class TimetableBackendGetFields { this.task = task; } - public Instant getTaskTime() { + public LocalTime getTaskTime() { return taskTime; } - public void setTaskTime(Instant taskTime) { + public void setTaskTime(LocalTime taskTime) { this.taskTime = taskTime; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TradingCalendarBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TradingCalendarBackendGetFields.java index f4418c4de..121ee7b59 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TradingCalendarBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/schedule/TradingCalendarBackendGetFields.java @@ -3,15 +3,17 @@ package ru.spcex.clearing.backendapi.controller.response.entity.schedule; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; import java.time.Instant; +import java.time.LocalDate; public class TradingCalendarBackendGetFields { @JsonProperty private Long id; @JsonProperty - @JsonSerialize(using = InstantSerializer.class) - private Instant clearingDate; + @JsonSerialize(using = LocalDateSerializer.class) + private LocalDate clearingDate; @JsonProperty private Long companyId; @JsonProperty @@ -31,11 +33,11 @@ public class TradingCalendarBackendGetFields { this.id = id; } - public Instant getClearingDate() { + public LocalDate getClearingDate() { return clearingDate; } - public void setClearingDate(Instant clearingDate) { + public void setClearingDate(LocalDate clearingDate) { this.clearingDate = clearingDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/securities/MoneyMarketSecurityBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/securities/MoneyMarketSecurityBackendGetFields.java index aa8139e07..5699d9e0c 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/securities/MoneyMarketSecurityBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/securities/MoneyMarketSecurityBackendGetFields.java @@ -2,10 +2,10 @@ package ru.spcex.clearing.backendapi.controller.response.entity.securities; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; import java.math.BigDecimal; -import java.time.Instant; +import java.time.LocalDate; public class MoneyMarketSecurityBackendGetFields { @JsonProperty @@ -14,12 +14,12 @@ public class MoneyMarketSecurityBackendGetFields { private Long securityId;// (linked to security) @JsonProperty private String description; - @JsonSerialize(using = InstantSerializer.class) + @JsonSerialize(using = LocalDateSerializer.class) @JsonProperty - private Instant startDate; - @JsonSerialize(using = InstantSerializer.class) + private LocalDate startDate; + @JsonSerialize(using = LocalDateSerializer.class) @JsonProperty - private Instant endDate; + private LocalDate endDate; @JsonProperty private BigDecimal nominalValue; @JsonProperty @@ -55,19 +55,19 @@ public class MoneyMarketSecurityBackendGetFields { this.description = description; } - public Instant getStartDate() { + public LocalDate getStartDate() { return startDate; } - public void setStartDate(Instant startDate) { + public void setStartDate(LocalDate startDate) { this.startDate = startDate; } - public Instant getEndDate() { + public LocalDate getEndDate() { return endDate; } - public void setEndDate(Instant endDate) { + public void setEndDate(LocalDate endDate) { this.endDate = endDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetAll.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetAll.java index ec3fc7bd0..0e777aa67 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetAll.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetAll.java @@ -42,7 +42,7 @@ public class KeyRateBackendGetAll extends BasicSpcexResponse { for (var keyRate : keyRates) { var singleItem = new KeyRateBackendGetFields(); singleItem.setId(keyRate.getId()); - singleItem.setRate(keyRate.getRate()); + singleItem.setKeyRate(keyRate.getRate()); singleItem.setStartDate(keyRate.getStartDate()); singleItem.setEndDate(keyRate.getEndDate()); singleItem.setDocument(keyRate.getDocument()); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetFields.java index d82f78ec4..0a26e33de 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/utilities/KeyRateBackendGetFields.java @@ -2,21 +2,22 @@ package ru.spcex.clearing.backendapi.controller.response.entity.utilities; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; -import java.time.Instant; +import java.math.BigDecimal; +import java.time.LocalDate; public class KeyRateBackendGetFields { @JsonProperty private Long id; @JsonProperty - private Double rate; - @JsonSerialize(using = InstantSerializer.class) + private BigDecimal keyRate; + @JsonSerialize(using = LocalDateSerializer.class) @JsonProperty - private Instant startDate; - @JsonSerialize(using = InstantSerializer.class) + private LocalDate startDate; + @JsonSerialize(using = LocalDateSerializer.class) @JsonProperty - private Instant endDate; + private LocalDate endDate; @JsonProperty private String document; @JsonProperty @@ -30,27 +31,27 @@ public class KeyRateBackendGetFields { this.id = id; } - public Double getRate() { - return rate; + public BigDecimal getKeyRate() { + return keyRate; } - public void setRate(Double rate) { - this.rate = rate; + public void setKeyRate(BigDecimal keyRate) { + this.keyRate = keyRate; } - public Instant getStartDate() { + public LocalDate getStartDate() { return startDate; } - public void setStartDate(Instant startDate) { + public void setStartDate(LocalDate startDate) { this.startDate = startDate; } - public Instant getEndDate() { + public LocalDate getEndDate() { return endDate; } - public void setEndDate(Instant endDate) { + public void setEndDate(LocalDate endDate) { this.endDate = endDate; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/system/RequestInfoResponse.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/system/RequestInfoResponse.java new file mode 100644 index 000000000..ed21ea44d --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/system/RequestInfoResponse.java @@ -0,0 +1,51 @@ +package ru.spcex.clearing.backendapi.controller.response.system; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.EnumSerializer; +import ru.spcex.clearing.platform.messaging.service.Status; + + +/** + * Банковские реквизиты для перечисления денежных средств + * @ApiModel(description = "Ответ в результате отправки операции в топик Kafka.") + * @ApiModelProperty(value = "Информация о принятом запросе") + **/ +@ApiModel(description = "Ответ при получении статуса запроса.") +public class RequestInfoResponse extends BasicSpcexResponse { + + @JsonProperty + @ApiModelProperty(value = "Поля объекта") + private RequestInfoPayload payload; + + public RequestInfoPayload getPayload() { + return payload; + } + + public void setStatus(Status status) { + this.payload = new RequestInfoPayload(); + payload.setStatus(status); + } + + public void setPayload(RequestInfoPayload payload) { + this.payload = payload; + } + + private static class RequestInfoPayload { + @JsonProperty + @JsonSerialize(using = EnumSerializer.class) + private Status status; + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + } + +} \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java new file mode 100644 index 000000000..425bd1876 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java @@ -0,0 +1,139 @@ +package ru.spcex.clearing.backendapi.controller.system; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import ru.clearing.platform.dictionary.AbstractDictionary; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; +import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetAll; +import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetSingleValue; +import ru.spcex.clearing.backendapi.errors.ActionValidationException; +import ru.spcex.clearing.backendapi.errors.BackEndError; +import ru.spcex.clearing.backendapi.errors.NotFound404Exception; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IMessageResolver; + +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@Controller +@RequestMapping("/dictionaries") +public class DictionaryController { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Map> allDictionaryMaps; + private final ImdgProvider imdgProvider; + + @Autowired + public DictionaryController(ImdgProvider imdgProvider) { + this.imdgProvider = imdgProvider; + this.allDictionaryMaps = new ConcurrentHashMap<>(); + } + + @ApiOperation(value = "get all dictionary value.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetAll.class)}) + @RequestMapping(value = "/{dictionary-name}", method = RequestMethod.GET) + @ResponseBody + public DictionaryBackendGetAll getAll(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") + @PathVariable("dictionary-name") String dictionaryName) { + Imdg dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); + Collection allValues = dictionary.getAllValues(); + DictionaryBackendGetAll response = new DictionaryBackendGetAll(); + response.fromEntity(allValues); + return response; + } + + @ApiOperation(value = "get dictionary value by id.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/{dictionary-name}/{id}", method = RequestMethod.GET) + @ResponseBody + public DictionaryBackendGetSingleValue getById(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") + @PathVariable("dictionary-name") String dictionaryName, + @ApiParam(value = "Идентификатор объекта", required = true, example = "1234") + @PathVariable("id") Long id) { + Imdg dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); + AbstractDictionary value = dictionary.getSingleObjectByID(id); + if (value == null) throw new NotFound404Exception(dictionaryName + " id='" + id + "'"); + DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue(); + response.fromEntity(value); + return response; + } + + @ApiOperation(value = "get dictionary value by code.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/{dictionary-name}/code/{code}", method = RequestMethod.GET) + @ResponseBody + public DictionaryBackendGetSingleValue getByCode(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") + @PathVariable("dictionary-name") String dictionaryName, + @ApiParam(value = "Код словаря", required = true, example = "1234") + @PathVariable("code") String code) { + Imdg dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); + AbstractDictionary value = dictionary.getSingleObjectByFieldValues(Map.of("code", code)); + if (value == null) throw new NotFound404Exception(dictionaryName + " code='" + code + "'"); + DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue(); + response.fromEntity(value); + return response; + } + + @SuppressWarnings("unchecked") + private Imdg extractDictionaryImdgFromUrlParameter(String dictionaryNameFromUrl, Class clazz) { + if (dictionaryNameFromUrl == null || dictionaryNameFromUrl.length() < 1) { + throw new ActionValidationException(BackEndError.ValidationError, "dictionary-name"); + } + + String actualDictionaryName = "Map_" + + dictionaryNameFromUrl.substring(0, 1).toUpperCase() + + dictionaryNameFromUrl.substring(1) + + "Dictionary"; + + Imdg dictionary = (Imdg) allDictionaryMaps.computeIfAbsent(actualDictionaryName, (mapName1) -> { + Imdg potentialImdg = imdgProvider.getImdg(actualDictionaryName, clazz); + if (potentialImdg.size() == 0) { + log.warn("coudln't find dictionary {}", actualDictionaryName); + return null; + } + return potentialImdg; + }); + + if (dictionary == null) { + throw new ActionValidationException(BackEndError.DictionaryNotFound, dictionaryNameFromUrl); + } + + return dictionary; + } + + @Autowired + private IMessageResolver errorResolver; + + @ResponseStatus(value = HttpStatus.BAD_REQUEST) + @ResponseBody + @ExceptionHandler(ActionValidationException.class) + public BasicSpcexResponse conflict(ActionValidationException ex) { + BasicSpcexResponse response = new BasicSpcexResponse(); + EnumMessage message = ex.getErrors().stream().findFirst().orElseThrow(); + response.setCode(message.getSubject().getId()); + response.setMessage(errorResolver.resolve(message)); + return response; + } + + @ResponseStatus(value = HttpStatus.NOT_FOUND) + @ResponseBody + @ExceptionHandler(NotFound404Exception.class) + public BasicSpcexResponse conflict(NotFound404Exception ex) { + BasicSpcexResponse response = new BasicSpcexResponse(); + EnumMessage message = ex.getError(); + response.setCode(message.getSubject().getId()); + response.setMessage(errorResolver.resolve(message)); + return response; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/MetaController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/MetaController.java new file mode 100644 index 000000000..0aa9f5e3b --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/MetaController.java @@ -0,0 +1,31 @@ +package ru.spcex.clearing.backendapi.controller.system; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.MediaType; +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; + +@Controller +@RequestMapping("/meta") +public class MetaController { + private final String metaRawJson; + + @Autowired + public MetaController(@Qualifier("metaJson") String meta) { + this.metaRawJson = meta; + } + + @ApiOperation(value = "get meta.json") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK")}) + @RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public String getAll() { + return metaRawJson; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/RequestStatusController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/RequestStatusController.java new file mode 100644 index 000000000..cebfc2d57 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/RequestStatusController.java @@ -0,0 +1,48 @@ +package ru.spcex.clearing.backendapi.controller.system; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +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.controller.response.BasicSpcexResponse; +import ru.spcex.clearing.backendapi.controller.response.system.RequestInfoResponse; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.service.RequestInfo; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +@Controller +@RequestMapping("/requests") +public class RequestStatusController { + + private final Imdg imdg; + + @Autowired + public RequestStatusController(ImdgProvider imdgProvider) { + this.imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + } + + @ApiOperation(value = "get request status.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = RequestInfoResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + @ResponseBody + public RequestInfoResponse getById(@ApiParam(value = "Идентификатор объекта", required = true, example = "1234") + @PathVariable("id") Long id) { + RequestInfo singleObjectByID; + if (id == null || (singleObjectByID = imdg.getSingleObjectByID(id)) == null) { + RequestInfoResponse response = new RequestInfoResponse(); + response.setCode(-1L); + response.setMessage("cannot find request with id='" + id + "'."); + return response; + } + RequestInfoResponse response = new RequestInfoResponse(); + response.setStatus(singleObjectByID.getStatus()); + return response; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/ActionValidationException.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/ActionValidationException.java index 251695991..b117f4c11 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/ActionValidationException.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/ActionValidationException.java @@ -1,6 +1,7 @@ package ru.spcex.clearing.backendapi.errors; import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumId; import java.util.Collection; import java.util.List; @@ -16,6 +17,10 @@ public class ActionValidationException extends RuntimeException { this.errors = List.of(error); } + public ActionValidationException(IEnumId subject, Object... args) { + this.errors = List.of(new EnumMessage(subject, args)); + } + public Collection getErrors() { return errors; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/BackEndError.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/BackEndError.java index 5808d3e7e..8508e0778 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/BackEndError.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/BackEndError.java @@ -3,10 +3,13 @@ package ru.spcex.clearing.backendapi.errors; import ru.spcex.platform.utils.enumeration.IEnumId; public enum BackEndError implements IEnumId { - ValidationError(3000L), - UnknownJsonProperty(3001L), - FailedToReadHttpMessage(3002L), - KeycloakRepeatedRoles(3003L); + ValidationError(9000L), + UnknownJsonProperty(9001L), + FailedToReadHttpMessage(9002L), + KeycloakRepeatedRoles(9003L), + DictionaryNotFound(9004L), + ResourceNotFound(9005L) + ; private final Long id; BackEndError(Long id) { diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/NotFound404Exception.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/NotFound404Exception.java new file mode 100644 index 000000000..1483749e5 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/errors/NotFound404Exception.java @@ -0,0 +1,16 @@ +package ru.spcex.clearing.backendapi.errors; + +import ru.spcex.platform.utils.enumeration.EnumMessage; + +public class NotFound404Exception extends RuntimeException { + + private final EnumMessage error; + + public NotFound404Exception(String comment) { + this.error = new EnumMessage(BackEndError.ResourceNotFound, comment); + } + + public EnumMessage getError() { + return error; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/filter/ClearingCorsFilter.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/filter/ClearingCorsFilter.java index e805b0671..b0346ffd0 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/filter/ClearingCorsFilter.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/filter/ClearingCorsFilter.java @@ -70,7 +70,7 @@ public class ClearingCorsFilter extends OncePerRequestFilter { // } else { // methods = "*"; // } -// setHeaderValue(httpServletResponse, H_ACCESS_CONTROL_ALLOW_METHODS, methods); + setHeaderValue(httpServletResponse, H_ACCESS_CONTROL_ALLOW_METHODS, "*"); // String headers; // if (head.length > 0) { @@ -78,7 +78,7 @@ public class ClearingCorsFilter extends OncePerRequestFilter { // } else { // headers = "*"; // } -// setHeaderValue(httpServletResponse, H_ACCESS_CONTROL_ALLOW_HEADERS, headers); + setHeaderValue(httpServletResponse, H_ACCESS_CONTROL_ALLOW_HEADERS, "*"); setHeaderValue(httpServletResponse, H_ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); log.trace("cors filter -> added ok"); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java index 938127416..9c1f3d891 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java @@ -27,13 +27,11 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import ru.spcex.clearing.backendapi.service.UserAuthProcessor; +import ru.spcex.platform.enumeration.UserRole; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @Component("keycloakRestAuthenticationProvider") @@ -44,6 +42,13 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio private final HttpServletResponse currentHttpResponse; private final RestTemplate restTemplate; private final UserAuthProcessor userAutoCreation; + private final static Map roleMapping = new HashMap<>(); + + static { + roleMapping.put("CS_MKR_ADMIN", UserRole.Admin); + roleMapping.put("CS_MKR_SUPERVISER", UserRole.Superviser); + roleMapping.put("CS_MKR_SECURITY", UserRole.Security); + } public KeycloakRestTemplateAuthenticationProvider(KeycloakConfigResolver resolver, HttpServletRequest currentHttpRequest, HttpServletResponse currentHttpResponse, @Qualifier("clearing-rest") RestTemplate restTemplate, UserAuthProcessor userAutoCreation) { @@ -82,16 +87,28 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio AccessToken accessToken = AdapterTokenVerifier.verifyToken(accessTokenString, deployment); //todo cors settings accessToken.setAllowedOrigins(Collections.singleton("*")); - List realmRoles = accessToken.getRealmAccess().getRoles().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(deployment, null, accessTokenString, accessToken, null, null, refreshTokenString); String principalName = AdapterUtils.getPrincipalName(deployment, accessToken); final KeycloakPrincipal principal = new KeycloakPrincipal<>(principalName, skSession); - final Set roles = AdapterUtils.getRolesFromSecurityContext(skSession); - final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, skSession); + Set roles = AdapterUtils.getRolesFromSecurityContext(skSession); + Set effectiveRoles = roles + .stream() + .map(s -> { + UserRole userRole = roleMapping.get(s); + return userRole != null ? userRole.getKey() : null; + }) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + List realmRoles = effectiveRoles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); + final KeycloakAccount account = new SimpleKeycloakAccount(principal, effectiveRoles, skSession); KeycloakAuthenticationToken keycloakAuthenticationToken = new KeycloakAuthenticationToken(account, false, realmRoles); keycloakAuthenticationToken.setAuthenticated(true); - log.debug("login successful: login {}, roles {}", principalName, String.join(";", roles)); + log.debug("login successful: login {}, roles from keycloak: {}; effective roles {}", + authentication.getName(), + String.join(";", roles), + String.join(";", effectiveRoles) + ); return keycloakAuthenticationToken; } catch (VerificationException vex) { diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakUtils.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakUtils.java new file mode 100644 index 000000000..52bc02e40 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakUtils.java @@ -0,0 +1,20 @@ +package ru.spcex.clearing.backendapi.security; + +import org.keycloak.KeycloakPrincipal; +import org.keycloak.adapters.spi.KeycloakAccount; +import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; +import org.springframework.security.core.Authentication; + +public class KeycloakUtils { + /** + * Достать username из Keycloak имплементации Authentication + */ + public static String getUserNameFromAuthentication(Authentication authentication) { + KeycloakAuthenticationToken auth = (KeycloakAuthenticationToken) authentication; + KeycloakAccount details = (KeycloakAccount) auth.getDetails(); + return ((KeycloakPrincipal) details.getPrincipal()) + .getKeycloakSecurityContext() + .getToken() + .getPreferredUsername(); + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java index 3d5a25a21..2100f9166 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/WebSecurityConfig.java @@ -18,6 +18,7 @@ import org.springframework.security.web.authentication.session.SessionAuthentica import ru.spcex.clearing.backendapi.config.element.BackendApiSettings; import ru.spcex.clearing.backendapi.security.handlers.AuthAuditSuccessLoginHandler; import ru.spcex.clearing.backendapi.security.handlers.LogoutAuditSuccessHandler; +import ru.spcex.platform.enumeration.UserRole; @KeycloakConfiguration @EnableGlobalMethodSecurity(prePostEnabled = true) @@ -68,7 +69,7 @@ public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter { if (securityDisabled) { anyReq.permitAll(); } else { - anyReq.hasAnyRole("admin", "default-roles-master") + anyReq.hasAnyRole(UserRole.Admin.getKey(), UserRole.Security.getKey(), UserRole.Superviser.getKey()) .and() .formLogin() .successHandler(loginSuccessHandler) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java index d2b48b879..ac66f3ee8 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/element/SecuritySettings.java @@ -2,6 +2,7 @@ package ru.spcex.clearing.backendapi.security.element; public class SecuritySettings { private Boolean authorizationDisabled = false; + private String sameSite; public Boolean getAuthorizationDisabled() { return authorizationDisabled; @@ -10,4 +11,12 @@ public class SecuritySettings { public void setAuthorizationDisabled(Boolean authorizationDisabled) { this.authorizationDisabled = authorizationDisabled; } + + public String getSameSite() { + return sameSite; + } + + public void setSameSite(String sameSite) { + this.sameSite = sameSite; + } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/RequestInfoAccepter.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/RequestInfoAccepter.java new file mode 100644 index 000000000..a1eaff115 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/RequestInfoAccepter.java @@ -0,0 +1,48 @@ +package ru.spcex.clearing.backendapi.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.RequestInfo; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +@Service +public class RequestInfoAccepter extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg requestInfoImdg; + + + public RequestInfoAccepter(Consumer kafkaQueue, ImdgProvider imdgProvider) { + super(kafkaQueue); + this.requestInfoImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + } + + + @Override + public void afterPropertiesSet() throws Exception { + callback(RequestInfoUpdate.class) + .setConsumer(this::updateRequestInfo) + .forDestination(Consts.REQUEST_INFO_UPDATE, callbacks::put); + init(); + } + + private void updateRequestInfo(BaseRequest requestInfoUpdateBaseRequest) { + //will throw exception for any class other than RequestInfoUpdate + RequestInfoUpdate statusInfo = requestInfoUpdateBaseRequest.getRequestPayload(); + RequestInfo requestInfo = requestInfoImdg.getSingleObjectByID(statusInfo.getId()); + if (requestInfo == null) { + log.warn("unknown requestInfo id={}", statusInfo.getId()); + return; + } + requestInfo.setStatus(statusInfo.getStatus()); + requestInfoImdg.update(requestInfo); + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/OperatorImpl.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/OperatorImpl.java index dabfee7e6..dedc83844 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/OperatorImpl.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/OperatorImpl.java @@ -7,13 +7,18 @@ import org.springframework.stereotype.Service; import ru.spcex.clearing.backendapi.controller.response.cud.QueueSuccessResponse; import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.errors.ActionValidationException; +import ru.spcex.clearing.backendapi.errors.BackEndError; +import ru.spcex.clearing.backendapi.errors.NotFound404Exception; import ru.spcex.clearing.backendapi.service.IOperator; +import ru.spcex.clearing.backendapi.service.validation.ActionValidationProvider; +import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.service.RequestInfo; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidator; import java.util.Collection; import java.util.concurrent.ExecutionException; @@ -24,16 +29,18 @@ public class OperatorImpl implements IOperator { private final Producer kafka; private final ImdgId idGenerator; private final ImdgProvider imdgProvider; + private final ActionValidationProvider validation; - public OperatorImpl(Producer kafka, ImdgProvider imdgProvider) { + public OperatorImpl(Producer kafka, ImdgProvider imdgProvider, ActionValidationProvider validation) { this.kafka = kafka; this.idGenerator = imdgProvider.getImdgIdGenerator(); this.imdgProvider = imdgProvider; + this.validation = validation; } @Override public QueueSuccessResponse sendRequestToQueue(String destination, IAction iAction) throws ExecutionException, InterruptedException { - throwValidate(iAction); + throwValidate(destination, iAction); BaseRequest request = new BaseRequest<>(); request.setId(idGenerator.nextId()); request.setActionType(iAction.getActionType()); @@ -46,15 +53,25 @@ public class OperatorImpl implements IOperator { } private void saveRequestToStorage(String destination, BaseRequest request) { - Imdg requestStorage = imdgProvider.getImdg(destination, RequestInfo.class); + Imdg requestStorage = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); RequestInfo requestInfo = RequestInfo.create(request.getId()); requestStorage.insert(requestInfo); } - private void throwValidate(IAction iAction) { + private void throwValidate(String destination, IAction iAction) { Collection validationErrors = iAction.validate(); if (validationErrors.size() > 0) { throw new ActionValidationException(validationErrors); } + IValidator validator = validation.getValidator(destination, iAction); + if (validator != null) { + validator.tillFirstError().ifPresent(enumMessage -> { + if (enumMessage.getSubject().equalsById(BackEndError.ResourceNotFound.getId())) { + throw new NotFound404Exception((String) enumMessage.getArgs()[0]); + } else { + throw new ActionValidationException(enumMessage); + } + }); + } } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/ActionValidationProvider.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/ActionValidationProvider.java new file mode 100644 index 000000000..d20ff3db8 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/ActionValidationProvider.java @@ -0,0 +1,82 @@ +package ru.spcex.clearing.backendapi.service.validation; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; +import ru.clearing.platform.dictionary.AbstractDictionary; +import ru.spcex.clearing.backendapi.controller.request.cud.schedule.TaskRunnerNew; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.backendapi.service.validation.rules.PresentById; +import ru.spcex.clearing.backendapi.service.validation.rules.TaskRunnerNewValidationRule; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.classes.base.interfaces.WithId; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +@Component +public class ActionValidationProvider implements InitializingBean { + private final Map> allImdgMaps; + private final ImdgProvider imdgProvider; + private final Map> validators; + + public ActionValidationProvider(ImdgProvider imdgProvider) { + this.validators = new HashMap<>(); + this.allImdgMaps = new HashMap<>(); + this.imdgProvider = imdgProvider; + } + + @Override + public void afterPropertiesSet() { + getImdg(IMDGDistributedNames.Map_TaskDictionary, AbstractDictionary.class); + getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, SpcexObjectBase.class); + + validators.put(Consts.DESTINATION_MONEY_MARKET_SECURITY_UPDATE, idPresent(IMDGDistributedNames.Map_MoneyMarketSecurity)); + validators.put(Consts.DESTINATION_MONEY_MARKET_SECURITY_DELETE, idPresent(IMDGDistributedNames.Map_MoneyMarketSecurity)); + validators.put(Consts.TASK_RUNNER_NEW, taskRunnerNew()); + } + + @SuppressWarnings("unchecked") + public IValidator getValidator(String destination, Object action) { + Function constructor = (Function) validators.get(destination); + if (constructor != null) + return constructor.apply(action); + return null; + } + + private & WithId> Function idPresent(String mapName) { + return iAction -> { + ImdgValidationContext ctx = new ImdgValidationContext<>(); + ctx.setValidatedObject(iAction); + ValidatorImpl> iValidator = new ValidatorImpl<>(ctx); + iValidator.addRule(new PresentById(getImdg(mapName, SpcexObjectBase.class))); + return iValidator; + }; + } + + private Function taskRunnerNew() { + return taskRunnerNew -> { + ImdgValidationContext ctx = new ImdgValidationContext<>(); + ctx.setValidatedObject(taskRunnerNew); + ctx.addImdg(IMDGDistributedNames.Map_TaskDictionary, getImdg(IMDGDistributedNames.Map_TaskDictionary, AbstractDictionary.class)); + ValidatorImpl> iValidator = new ValidatorImpl<>(ctx); + iValidator.addRule(TaskRunnerNewValidationRule.knownTaskDictionary); + return iValidator; + }; + } + + + @SuppressWarnings("unchecked") + private Imdg getImdg(String mapName, Class clazz) { + return (Imdg) allImdgMaps.computeIfAbsent(mapName, (mapName1) -> imdgProvider.getImdg(mapName, clazz)); + } + + +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/rules/PresentById.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/rules/PresentById.java new file mode 100644 index 000000000..032767967 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/rules/PresentById.java @@ -0,0 +1,28 @@ +package ru.spcex.clearing.backendapi.service.validation.rules; +import ru.spcex.clearing.backendapi.errors.BackEndError; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.classes.base.interfaces.WithId; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Optional; + +public class PresentById implements IValidationRule> { + private final Imdg map; + + public PresentById(Imdg map) { + this.map = map; + } + + @Override + public Optional validate(ImdgValidationContext context) { + WithId actionById = context.getValidatedObject(); + if (map.getSingleObjectByID(actionById.getId()) == null) { + return of(BackEndError.ResourceNotFound, actionById.getId()); + } else { + return empty(); + } + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/rules/TaskRunnerNewValidationRule.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/rules/TaskRunnerNewValidationRule.java new file mode 100644 index 000000000..0b72d0a7d --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/validation/rules/TaskRunnerNewValidationRule.java @@ -0,0 +1,33 @@ +package ru.spcex.clearing.backendapi.service.validation.rules; + +import ru.clearing.platform.dictionary.AbstractDictionary; +import ru.spcex.clearing.backendapi.controller.request.cud.schedule.TaskRunnerNew; +import ru.spcex.clearing.backendapi.errors.BackEndError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Map; +import java.util.Optional; + +public enum TaskRunnerNewValidationRule implements IValidationRule> { + knownTaskDictionary() { + @Override + public Optional validate(ImdgValidationContext context) { + TaskRunnerNew validatedObject = context.getValidatedObject(); + Imdg taskDictionaryImdg = context.obtainMap(IMDGDistributedNames.Map_TaskDictionary, AbstractDictionary.class); + AbstractDictionary taskEnum = taskDictionaryImdg.getSingleObjectByFieldValues(Map.of("code", validatedObject.getTask())); + if (taskEnum == null) { + return of(BackEndError.ResourceNotFound, "taskDictionary " + validatedObject.getTask()); + } + return empty(); + } + }; + + @Override + public String ruleName() { + return "TaskRunnerNewValidationRule." + name(); + } +} diff --git a/clearing-parent/backend-api/src/main/resources/application.properties b/clearing-parent/backend-api/src/main/resources/application.properties index 8c83a2cef..c375b65ed 100644 --- a/clearing-parent/backend-api/src/main/resources/application.properties +++ b/clearing-parent/backend-api/src/main/resources/application.properties @@ -1,5 +1,9 @@ server.port=8080 server.servlet.context-path=/backend-api +server.ssl.key-store-type=PKCS12 +server.ssl.key-store=classpath:keystore/client.p12 +server.ssl.key-store-password=Aa123456 +server.ssl.enabled=true spring.main.web-application-type=servlet backend-api.example-setting=test @@ -8,14 +12,22 @@ backend-api.hazelcast.cluster-members=127.0.0.1:5701 backend-api.hazelcast.login=dev backend-api.hazelcast.password=dev-pass -backend-api.kafka.bootstrap-servers=localhost:9092 -backend-api.kafka.acks=all -backend-api.kafka.retries=0 -backend-api.kafka.batch-size=16384 -backend-api.kafka.linger-ms=1 -backend-api.kafka.buffer-memory=33554432 +backend-api.kafka-producer.bootstrap-servers=localhost:9092 +backend-api.kafka-producer.acks=all +backend-api.kafka-producer.retries=0 +backend-api.kafka-producer.batch-size=16384 +backend-api.kafka-producer.linger-ms=1 +backend-api.kafka-producer.buffer-memory=33554432 -backend-api.security.authorization-disabled=true +backend-api.kafka-consumer.bootstrap-servers=localhost:9092 +backend-api.kafka-consumer.group-id=dev-group-backend-api +backend-api.kafka-consumer.enable-auto-commit=true +backend-api.kafka-consumer.session-timeout-ms=30000 +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 ##keycloak diff --git a/clearing-parent/backend-api/src/main/resources/data.xml b/clearing-parent/backend-api/src/main/resources/data.xml deleted file mode 100644 index da29f9695..000000000 --- a/clearing-parent/backend-api/src/main/resources/data.xml +++ /dev/null @@ -1,237 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/resources/messages/error.properties b/clearing-parent/backend-api/src/main/resources/messages/error.properties index bd5831476..34ec50c2e 100644 --- a/clearing-parent/backend-api/src/main/resources/messages/error.properties +++ b/clearing-parent/backend-api/src/main/resources/messages/error.properties @@ -1,4 +1,7 @@ 1=This is error example 1. -3000=validation error field '%s' -3001=unrecognized json property '%s' -3002=failed to read http message \ No newline at end of file +9000=validation error field '%s' +9001=unrecognized json property '%s' +9002=failed to read http message +9003=Keycloak roles contain repeated elements +9004=couldn't find dictionary '%s' +9005=Not found %s \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/resources/messages/error_ru.properties b/clearing-parent/backend-api/src/main/resources/messages/error_ru.properties index 4e12eeded..feefe7634 100644 --- a/clearing-parent/backend-api/src/main/resources/messages/error_ru.properties +++ b/clearing-parent/backend-api/src/main/resources/messages/error_ru.properties @@ -1,2 +1 @@ -1=Пример ошибки с идентификатором 1. -3000=Ошибка валидации, поле: %s \ No newline at end of file +1=Пример ошибки с идентификатором 1. \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/resources/meta/data.xml b/clearing-parent/backend-api/src/main/resources/meta/data.xml new file mode 100644 index 000000000..be4ee5c59 --- /dev/null +++ b/clearing-parent/backend-api/src/main/resources/meta/data.xml @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.server.xslt b/clearing-parent/backend-api/src/main/resources/meta/meta.server.xslt new file mode 100644 index 000000000..a994995fc --- /dev/null +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.server.xslt @@ -0,0 +1,199 @@ + + + + + + + + + + { + "version": "", + + } + + + + "enums": { + + } + + + + + ,"objects": { + + } + + + + + ,"views": { + + } + + + + + + + + ,"types": [ + + ] + + + + + , + { + "": { + + "": "" + , + + }} + + + + + , + "": { + + "": "", + + "fields": [] + } + + + + + , + "": { + + "": "", + + "fields": [] + + ,"actions":[] + } + + + + + + + + + + + + , + {"": + { + + "": "", + + "fields": [] + }} + + + + + + + + , + "": { + + "": "", + + "sources": [] + ,"fields":[] + } + + + + + , + "" + + + + + , + + + + + + { + + , + "": + + { + + + , + + } + + + } + + + + + + + , + {"": + { + + + "": + "": + "": + "": + "": + "": + "": + "": + "": "" + + , + + }} + + + + , + {"": + { + + + "": + "": "" + "": "" + "": "" + + , + + }} + + + + + + "": + "": + "": + "": + "": + "": + "": + "": "" + + + diff --git a/clearing-parent/backend-api/src/main/resources/meta.xml b/clearing-parent/backend-api/src/main/resources/meta/meta.xml similarity index 78% rename from clearing-parent/backend-api/src/main/resources/meta.xml rename to clearing-parent/backend-api/src/main/resources/meta/meta.xml index d0ff64de3..2c066a2c6 100644 --- a/clearing-parent/backend-api/src/main/resources/meta.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.xml @@ -1,1479 +1,1678 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -