From 7f46dc5b4f35e9699c722b6e6bc31625675b4c2e Mon Sep 17 00:00:00 2001 From: Aleksey Kulikov Date: Wed, 21 May 2025 12:25:17 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-851 --- .../DigitalCertificateSecurityService.java | 201 +++++++++++++ .../service/cud/GatewaySecurityService.java | 83 +++++- .../cud/UtilitarianDigitalRightService.java | 152 ++++++++++ .../validation/ValidationProvider.java | 267 +++++++++++++++++- .../service/AbstractServiceTest.java | 46 ++- ...DigitalCertificateSecurityServiceTest.java | 148 ++++++++++ .../UtilitarianDigitalRightServiceTest.java | 108 +++++++ .../platform/enumeration/InstrumentType.java | 3 +- .../platform/messaging/domain/Consts.java | 8 + ...italCertificateSecurityGatewayRequest.java | 24 ++ .../DigitalCertificateSecurityNewRequest.java | 205 ++++++++++++++ ...gitalCertificateSecurityUpdateRequest.java | 217 ++++++++++++++ .../UtilitarianDigitalRightNewRequest.java | 172 +++++++++++ .../UtilitarianDigitalRightUpdateRequest.java | 185 ++++++++++++ 14 files changed, 1793 insertions(+), 26 deletions(-) create mode 100644 clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/DigitalCertificateSecurityService.java create mode 100644 clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/UtilitarianDigitalRightService.java create mode 100644 clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/DigitalCertificateSecurityServiceTest.java create mode 100644 clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/UtilitarianDigitalRightServiceTest.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/company/DigitalCertificateSecurityGatewayRequest.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityNewRequest.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityUpdateRequest.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightNewRequest.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightUpdateRequest.java diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/DigitalCertificateSecurityService.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/DigitalCertificateSecurityService.java new file mode 100644 index 000000000..afcf2db5b --- /dev/null +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/DigitalCertificateSecurityService.java @@ -0,0 +1,201 @@ +package ru.spcex.clearing.securities.service.cud; + +import java.time.Instant; +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import ru.clearing.classes.statics.data.security.DigitalCertificateSecurity; +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.common.CommonDeleteRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.clearing.securities.validation.ValidationProvider; +import ru.spcex.clearing.util.security.UserRoleVerification; +import ru.spcex.clearing.util.services.RequestHelper; +import ru.spcex.clearing.validation.common.ValidationHelper; +import ru.spcex.platform.enumeration.UserRole; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; +import ru.spcex.platform.utils.error.ValidationException; + +@Service +public class DigitalCertificateSecurityService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg digitalCertificateSecurityImdg; + private final ImdgProvider imdgProvider; + private final ImdgId idGenerator; + private final ValidationProvider validation; + private final UserRoleVerification userRoleVerification; + private final ValidationHelper validationHelper; + private final RequestHelper requestHelper; + + @Autowired + public DigitalCertificateSecurityService(Consumer kafkaQueue, + Producer kafkaProducer, + ImdgProvider imdgProvider, + UserRoleVerification userRoleVerification, + ValidationProvider validation, + ValidationHelper validationHelper, + RequestHelper requestHelper) { + super(kafkaQueue, kafkaProducer); + this.validation = validation; + this.digitalCertificateSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class); + this.imdgProvider = imdgProvider; + this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.userRoleVerification = userRoleVerification.setRoleForVerification(UserRole.Admin); + this.validationHelper = validationHelper; + this.requestHelper = requestHelper; + } + + @Override + public void afterPropertiesSet() { + callback(DigitalCertificateSecurityNewRequest.class) + .setFunction(this::newDigitalCertificate) + .forDestination(Consts.DESTINATION_DIGITAL_CERTIFICATE_SECURITY_NEW, callbacks::put); + callback(DigitalCertificateSecurityUpdateRequest.class) + .setFunction(this::updateDigitalCertificate) + .forDestination(Consts.DESTINATION_DIGITAL_CERTIFICATE_SECURITY_UPDATE, callbacks::put); + callback(CommonDeleteRequest.class) + .setFunction(this::deleteDigitalCertificate) + .forDestination(Consts.DESTINATION_DIGITAL_CERTIFICATE_SECURITY_DELETE, callbacks::put); + imdgProvider.waitAvailable(); + init(); + } + + protected RequestInfoUpdate newDigitalCertificate(BaseRequest userRequest) { + log.debug("DigitalCertificateSecurityNewRequest received, id={}", userRequest.getId()); + try { + userRoleVerification.validateRoleAndThrow(userRequest); + DigitalCertificateSecurity digitalCertificateSecurity = newDigitalCertificate0(userRequest.getRequestPayload()); + log.debug("successfully processed, request id {}, new object id {}", userRequest.getId(), digitalCertificateSecurity.getId()); + return null; + } catch (ValidationException e) { + return requestHelper.makeErrorResponse(userRequest, e.getEnumMsg()); + } + } + + protected synchronized DigitalCertificateSecurity newDigitalCertificate0(DigitalCertificateSecurityNewRequest req) throws ValidationException { + validationHelper.validateTillFirstErrorAndThrow(req, validation.digitalCertificateNewValidator()); + + log.debug("DigitalCertificateSecurityNewRequest received"); + DigitalCertificateSecurity digitalCertificate = new DigitalCertificateSecurity(); + digitalCertificate.setId(idGenerator.nextId()); + digitalCertificate.setSecuritySymbol(StringUtils.hasText(req.getSecuritySymbol()) ? req.getSecuritySymbol().trim() : null); + digitalCertificate.setShortName(req.getShortName()); + digitalCertificate.setFullName(req.getFullName()); + digitalCertificate.setIssuerId(req.getIssuerId()); + digitalCertificate.setShortNameEng(req.getShortNameEng()); + digitalCertificate.setFullNameEng(req.getFullNameEng()); + if (req.getWorkflowStatus() == null) { + digitalCertificate.setWorkflowStatus(WorkflowStatus.Active.getKey()); + } else { + digitalCertificate.setWorkflowStatus(req.getWorkflowStatus()); + } + digitalCertificate.setInstrumentType(req.getInstrumentType()); + digitalCertificate.setSecurityId(digitalCertificate.getId()); + digitalCertificate.setCreated(Instant.now()); + digitalCertificate.setUpdated(digitalCertificate.getCreated()); + digitalCertificate.setBaseCode(req.getBaseCode()); + digitalCertificate.setBaseUnitSize(req.getBaseUnitSize()); + digitalCertificate.setPriceVarianceLimit(req.getPriceVarianceLimit()); + digitalCertificate.setNominalTypeCode(req.getNominalTypeCode()); + digitalCertificate.setNominalValue(req.getNominalValue()); + digitalCertificate.setNominalIndexationDate(req.getNominalIndexationDate()); + digitalCertificate.setNominalIndexationSign(req.getNominalIndexationSign()); + digitalCertificate.setSettlementHouse(req.getSettlementHouse()); + digitalCertificate.setDepository(req.getDepository()); + ImdgTransaction transaction = imdgProvider.newTransaction(); + try { + transaction.beginTransaction(); + Imdg digitalCertificateImdg = transaction.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class); + digitalCertificateImdg.insert(digitalCertificate); + transaction.commitTransaction(); + } catch (Throwable e) { + transaction.rollbackTransaction(); + } + return digitalCertificate; + } + + protected RequestInfoUpdate updateDigitalCertificate(BaseRequest userRequest) { + log.debug("DigitalCertificateSecurityUpdateRequest received, id={}", userRequest.getId()); + try { + userRoleVerification.validateRoleAndThrow(userRequest); + DigitalCertificateSecurity digitalCertificateSecurity = updateDigitalCertificate0(userRequest.getRequestPayload()); + log.debug("successfully processed, request id {}, updated object id {}", userRequest.getId(), digitalCertificateSecurity.getId()); + return null; + } catch (ValidationException e) { + return requestHelper.makeErrorResponse(userRequest, e.getEnumMsg()); + } + } + + protected synchronized DigitalCertificateSecurity updateDigitalCertificate0(DigitalCertificateSecurityUpdateRequest req) throws ValidationException { + validationHelper.validateTillFirstErrorAndThrow(req, validation.digitalCertificateUpdateValidator()); + + DigitalCertificateSecurity digitalCertificate = digitalCertificateSecurityImdg.getSingleObjectByID(req.getId()); + Instant updateTime = Instant.now(); + digitalCertificate.setUpdated(updateTime); + digitalCertificate.setSecuritySymbol(StringUtils.hasText(req.getSecuritySymbol()) ? req.getSecuritySymbol().trim() : null); + digitalCertificate.setShortName(req.getShortName()); + digitalCertificate.setFullName(req.getFullName()); + digitalCertificate.setIssuerId(req.getIssuerId()); + digitalCertificate.setShortNameEng(req.getShortNameEng()); + digitalCertificate.setFullNameEng(req.getFullNameEng()); + if (req.getWorkflowStatus() != null) { + digitalCertificate.setWorkflowStatus(req.getWorkflowStatus()); + } + digitalCertificate.setInstrumentType(req.getInstrumentType()); + digitalCertificate.setBaseCode(req.getBaseCode()); + digitalCertificate.setBaseUnitSize(req.getBaseUnitSize()); + digitalCertificate.setPriceVarianceLimit(req.getPriceVarianceLimit()); + digitalCertificate.setNominalTypeCode(req.getNominalTypeCode()); + digitalCertificate.setNominalValue(req.getNominalValue()); + digitalCertificate.setNominalIndexationDate(req.getNominalIndexationDate()); + digitalCertificate.setNominalIndexationSign(req.getNominalIndexationSign()); + digitalCertificate.setSettlementHouse(req.getSettlementHouse()); + digitalCertificate.setDepository(req.getDepository()); + if (req.getWorkflowStatus() != null) { + digitalCertificate.setWorkflowStatus(req.getWorkflowStatus()); + } + digitalCertificate.setInstrumentType(req.getInstrumentType()); + + digitalCertificateSecurityImdg.update(digitalCertificate); + return digitalCertificate; + } + + private RequestInfoUpdate deleteDigitalCertificate(BaseRequest userRequest) { + log.debug("CommonDeleteRequest received id = {}", userRequest.getId()); + try { + userRoleVerification.validateRoleAndThrow(userRequest); + Long digitalCertificateId = deleteDigitalCertificate0(userRequest.getRequestPayload()); + log.debug("successfully processed, request id {}, delete object id {}", userRequest.getId(), digitalCertificateId); + return null; + } catch (ValidationException e) { + return requestHelper.makeErrorResponse(userRequest, e.getEnumMsg()); + } + } + + protected synchronized Long deleteDigitalCertificate0(CommonDeleteRequest req) throws ValidationException { + validationHelper.validateTillFirstErrorAndThrow(req, validation.digitalCertificateDeleteValidator()); + + Instant updateTime = Instant.now(); + DigitalCertificateSecurity digitalCertificate = digitalCertificateSecurityImdg.getSingleObjectByID(req.getId()); + digitalCertificate.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey()); + digitalCertificate.setUpdated(updateTime); + digitalCertificateSecurityImdg.update(digitalCertificate); + + return digitalCertificate.getId(); + } + +} diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/GatewaySecurityService.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/GatewaySecurityService.java index e43786e2d..3532b4efb 100644 --- a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/GatewaySecurityService.java +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/GatewaySecurityService.java @@ -1,7 +1,11 @@ package ru.spcex.clearing.securities.service.cud; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.producer.Producer; import org.slf4j.Logger; @@ -23,10 +27,25 @@ import ru.clearing.platform.dictionary.CurrencyPairDictionary; 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.company.DigitalCertificateSecurityGatewayRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.EquitySecurityGatewayRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.FixedIncomeGatewayRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.SecurityFondGatewayRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.securitites.*; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CouponPeriodNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CouponPeriodUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.EquitySecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.EquitySecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeCashFlowNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeCashFlowUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeSecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewGatewayRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewGatewayRequest; import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityUpdateRequest; @@ -36,7 +55,11 @@ import ru.spcex.clearing.securities.validation.ValidationProvider; import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.util.services.RequestHelper; import ru.spcex.clearing.validation.common.ValidationHelper; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.CompanySymbol; +import ru.spcex.platform.enumeration.CurrencyCode; +import ru.spcex.platform.enumeration.InstrumentType; +import ru.spcex.platform.enumeration.UserRole; +import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -44,8 +67,6 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.error.ValidationException; -import java.util.*; - @Service public class GatewaySecurityService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -70,6 +91,7 @@ public class GatewaySecurityService extends QueueConsumer implements Initializin private final ListingService listingService; private final CouponPeriodService couponPeriodService; private final FixedIncomeCashFlowService fixedIncomeCashFlowService; + private final DigitalCertificateSecurityService digitalCertificateSecurityService; private final ValidationProvider validation; private final UserRoleVerification userRoleVerification; @@ -93,7 +115,8 @@ public class GatewaySecurityService extends QueueConsumer implements Initializin CurrencyPairSecurityService currencyPairSecurityService, ListingService listingService, CouponPeriodService couponPeriodService, - FixedIncomeCashFlowService fixedIncomeCashFlowService) { + FixedIncomeCashFlowService fixedIncomeCashFlowService, + DigitalCertificateSecurityService digitalCertificateSecurityService) { super(kafkaQueue, kafkaProducer); this.validation = validation; this.fixedIncomeSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class); @@ -120,6 +143,7 @@ public class GatewaySecurityService extends QueueConsumer implements Initializin this.listingService = listingService; this.couponPeriodService = couponPeriodService; this.fixedIncomeCashFlowService = fixedIncomeCashFlowService; + this.digitalCertificateSecurityService = digitalCertificateSecurityService; } @Override @@ -130,6 +154,9 @@ public class GatewaySecurityService extends QueueConsumer implements Initializin callback(EquitySecurityGatewayRequest.class) .setFunction(this::newSecurities) .forDestination(Consts.DESTINATION_SECURITY_EQTY_GATEWAY, callbacks::put); + callback(EquitySecurityGatewayRequest.class) + .setFunction(this::newSecurities) + .forDestination(Consts.DESTINATION_SECURITY_DGCT_GATEWAY, callbacks::put); callback(MoneyMarketSecurityNewGatewayRequest.class) .setFunction(this::newMoneyMarketSecurity) .forDestination(Consts.DESTINATION_GATEWAY_MONEY_MARKET_SECURITY, callbacks::put); @@ -331,6 +358,26 @@ public class GatewaySecurityService extends QueueConsumer implements Initializin security = equitySecurityService.updateEquity0(updateRequest); } } + if (InstrumentType.DGCT.equalsByKey(req.getSecurityType())) { + DigitalCertificateSecurityGatewayRequest digitalCertificateSecurityGatewayRequest = (DigitalCertificateSecurityGatewayRequest) req; + DigitalCertificateSecurityNewRequest newRequest = digitalCertificateSecurityGatewayRequest.getSecurity(); + if (StringUtils.isEmpty(newRequest.getSecuritySymbol())) { + log.warn("Skip creating digitalCertificateSecurity without securityId: uuid: {}", req.getUuid()); + return null; + } + log.debug("Processed request with securitySymbol: {}", newRequest.getSecuritySymbol()); + newRequest.setIssuerId(companyId); + log.trace("EquitySecurityNewRequest - FOND"); + String securitySymbol = newRequest.getSecuritySymbol(); + security = findSecurityBySecuritySymbol(equitySecurityImdg, securitySymbol); + + if (security == null) { + security = digitalCertificateSecurityService.newDigitalCertificate0(newRequest); + } else { + DigitalCertificateSecurityUpdateRequest updateRequest = toUpdateRequest(security, newRequest); + security = digitalCertificateSecurityService.updateDigitalCertificate0(updateRequest); + } + } if (InstrumentType.CRNC.equalsByKey(req.getSecurityType())) { throw new IllegalStateException("CRNC support in other function"); // см. другой метод. } @@ -632,4 +679,28 @@ public class GatewaySecurityService extends QueueConsumer implements Initializin updateRequest.setClearingOrganization(newRequest.getClearingOrganization()); return updateRequest; } + + DigitalCertificateSecurityUpdateRequest toUpdateRequest(Security digitalCertificateSecurity, DigitalCertificateSecurityNewRequest newRequest) { + var updateRequest = new DigitalCertificateSecurityUpdateRequest(); + updateRequest.setId(digitalCertificateSecurity.getId()); + updateRequest.setSecuritySymbol(newRequest.getSecuritySymbol()); + updateRequest.setInstrumentType(newRequest.getInstrumentType()); + updateRequest.setBaseCode(newRequest.getBaseCode()); + updateRequest.setShortName(newRequest.getShortName()); + updateRequest.setFullName(newRequest.getFullName()); + updateRequest.setIssuerId(newRequest.getIssuerId()); + updateRequest.setShortNameEng(newRequest.getShortNameEng()); + updateRequest.setFullNameEng(newRequest.getFullNameEng()); + updateRequest.setWorkflowStatus(newRequest.getWorkflowStatus()); + updateRequest.setBaseUnitSize(newRequest.getBaseUnitSize()); + updateRequest.setPriceVarianceLimit(newRequest.getPriceVarianceLimit()); + updateRequest.setNominalTypeCode(newRequest.getNominalTypeCode()); + updateRequest.setNominalValue(newRequest.getNominalValue()); + updateRequest.setNominalIndexationDate(newRequest.getNominalIndexationDate()); + updateRequest.setNominalIndexationSign(newRequest.getNominalIndexationSign()); + updateRequest.setSettlementHouse(newRequest.getSettlementHouse()); + updateRequest.setDepository(newRequest.getDepository()); + + return updateRequest; + } } diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/UtilitarianDigitalRightService.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/UtilitarianDigitalRightService.java new file mode 100644 index 000000000..6aa917b4c --- /dev/null +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/UtilitarianDigitalRightService.java @@ -0,0 +1,152 @@ +package ru.spcex.clearing.securities.service.cud; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.security.UtilitarianDigitalRight; +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.securitites.UtilitarianDigitalRightNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.UtilitarianDigitalRightUpdateRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.clearing.securities.validation.ValidationProvider; +import ru.spcex.clearing.util.security.UserRoleVerification; +import ru.spcex.clearing.util.services.RequestHelper; +import ru.spcex.clearing.validation.common.ValidationHelper; +import ru.spcex.platform.enumeration.UserRole; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; +import ru.spcex.platform.utils.error.ValidationException; + +@Service +public class UtilitarianDigitalRightService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg utilitarianDigitalRightImdg; + private final ImdgProvider imdgProvider; + private final ImdgId idGenerator; + private final ValidationProvider validation; + private final UserRoleVerification userRoleVerification; + private final ValidationHelper validationHelper; + private final RequestHelper requestHelper; + + @Autowired + public UtilitarianDigitalRightService(Consumer kafkaQueue, + Producer kafkaProducer, + ImdgProvider imdgProvider, + UserRoleVerification userRoleVerification, + ValidationProvider validation, + ValidationHelper validationHelper, + RequestHelper requestHelper) { + super(kafkaQueue, kafkaProducer); + this.validation = validation; + this.utilitarianDigitalRightImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UtilitarianDigitalRight, UtilitarianDigitalRight.class); + this.imdgProvider = imdgProvider; + this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.userRoleVerification = userRoleVerification.setRoleForVerification(UserRole.Admin); + this.validationHelper = validationHelper; + this.requestHelper = requestHelper; + } + + @Override + public void afterPropertiesSet() { + callback(UtilitarianDigitalRightNewRequest.class) + .setFunction(this::newUtilitarianDigitalRight) + .forDestination(Consts.DESTINATION_UTILITARIAN_DIGITAL_RIGHT_NEW, callbacks::put); + callback(UtilitarianDigitalRightUpdateRequest.class) + .setFunction(this::updateUtilitarianDigitalRight) + .forDestination(Consts.DESTINATION_UTILITARIAN_DIGITAL_RIGHT_UPDATE, callbacks::put); + imdgProvider.waitAvailable(); + init(); + } + + protected RequestInfoUpdate newUtilitarianDigitalRight(BaseRequest userRequest) { + log.debug("UtilitarianDigitalRightNewRequest received, id={}", userRequest.getId()); + try { + userRoleVerification.validateRoleAndThrow(userRequest); + UtilitarianDigitalRight utilitarianDigitalRight = newUtilitarianDigitalRight0(userRequest.getRequestPayload()); + log.debug("successfully processed, request id {}, new object id {}", userRequest.getId(), utilitarianDigitalRight.getId()); + return null; + } catch (ValidationException e) { + return requestHelper.makeErrorResponse(userRequest, e.getEnumMsg()); + } + } + + protected synchronized UtilitarianDigitalRight newUtilitarianDigitalRight0(UtilitarianDigitalRightNewRequest req) throws ValidationException { + validationHelper.validateTillFirstErrorAndThrow(req, validation.utilitarianDigitalRightNewValidator()); + + log.debug("UtilitarianDigitalRightNewRequest received"); + UtilitarianDigitalRight utilitarianDigitalRight = new UtilitarianDigitalRight(); + utilitarianDigitalRight.setId(idGenerator.nextId()); + utilitarianDigitalRight.setSecurityId(req.getSecurityId()); + utilitarianDigitalRight.setInvestmentAttractingCompany(req.getInvestmentAttractingCompany()); + utilitarianDigitalRight.setInvestmentAttractingInn(req.getInvestmentAttractingInn()); + utilitarianDigitalRight.setIssueAmount(req.getIssueAmount()); + utilitarianDigitalRight.setIssuePrice(req.getIssuePrice()); + utilitarianDigitalRight.setIssueSize(req.getIssueSize()); + utilitarianDigitalRight.setNominalIndexation(req.getNominalIndexation()); + utilitarianDigitalRight.setPlatformOperator(req.getPlatformOperator()); + utilitarianDigitalRight.setPlatformOperatorCode(req.getPlatformOperatorCode()); + utilitarianDigitalRight.setPlatformOperatorInn(req.getPlatformOperatorInn()); + utilitarianDigitalRight.setPlatformOperatorWeb(req.getPlatformOperatorWeb()); + utilitarianDigitalRight.setPlatformProposalWeb(req.getPlatformProposalWeb()); + utilitarianDigitalRight.setRightEssence(req.getRightEssence()); + utilitarianDigitalRight.setRightUnit(req.getRightUnit()); + utilitarianDigitalRight.setRightUnitMeasurement(req.getRightUnitMeasurement()); + + ImdgTransaction transaction = imdgProvider.newTransaction(); + try { + transaction.beginTransaction(); + Imdg utilitarianDigitalRightImdg = transaction.getImdg(IMDGDistributedNames.Map_UtilitarianDigitalRight, UtilitarianDigitalRight.class); + utilitarianDigitalRightImdg.insert(utilitarianDigitalRight); + transaction.commitTransaction(); + } catch (Throwable e) { + transaction.rollbackTransaction(); + } + return utilitarianDigitalRight; + } + + protected RequestInfoUpdate updateUtilitarianDigitalRight(BaseRequest userRequest) { + log.debug("UtilitarianDigitalRightUpdateRequest received, id={}", userRequest.getId()); + try { + userRoleVerification.validateRoleAndThrow(userRequest); + UtilitarianDigitalRight utilitarianDigitalRight = updateUtilitarianDigitalRight0(userRequest.getRequestPayload()); + log.debug("successfully processed, request id {}, updated object id {}", userRequest.getId(), utilitarianDigitalRight.getId()); + return null; + } catch (ValidationException e) { + return requestHelper.makeErrorResponse(userRequest, e.getEnumMsg()); + } + } + + protected synchronized UtilitarianDigitalRight updateUtilitarianDigitalRight0(UtilitarianDigitalRightUpdateRequest req) throws ValidationException { + validationHelper.validateTillFirstErrorAndThrow(req, validation.utilitarianDigitalRightUpdateValidator()); + + UtilitarianDigitalRight utilitarianDigitalRight = utilitarianDigitalRightImdg.getSingleObjectByID(req.getId()); + + utilitarianDigitalRight.setInvestmentAttractingCompany(req.getInvestmentAttractingCompany()); + utilitarianDigitalRight.setInvestmentAttractingInn(req.getInvestmentAttractingInn()); + utilitarianDigitalRight.setIssueAmount(req.getIssueAmount()); + utilitarianDigitalRight.setIssuePrice(req.getIssuePrice()); + utilitarianDigitalRight.setIssueSize(req.getIssueSize()); + utilitarianDigitalRight.setNominalIndexation(req.getNominalIndexation()); + utilitarianDigitalRight.setPlatformOperator(req.getPlatformOperator()); + utilitarianDigitalRight.setPlatformOperatorCode(req.getPlatformOperatorCode()); + utilitarianDigitalRight.setPlatformOperatorInn(req.getPlatformOperatorInn()); + utilitarianDigitalRight.setPlatformOperatorWeb(req.getPlatformOperatorWeb()); + utilitarianDigitalRight.setPlatformProposalWeb(req.getPlatformProposalWeb()); + utilitarianDigitalRight.setRightEssence(req.getRightEssence()); + utilitarianDigitalRight.setRightUnit(req.getRightUnit()); + utilitarianDigitalRight.setRightUnitMeasurement(req.getRightUnitMeasurement()); + + utilitarianDigitalRightImdg.update(utilitarianDigitalRight); + return utilitarianDigitalRight; + } + +} diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/ValidationProvider.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/ValidationProvider.java index 60dd117cf..7e745f3b7 100644 --- a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/ValidationProvider.java +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/ValidationProvider.java @@ -1,40 +1,73 @@ package ru.spcex.clearing.securities.validation; +import java.util.Collection; +import java.util.function.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity; -import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeCashFlow; import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity; import ru.clearing.classes.statics.data.misc.Market; import ru.clearing.classes.statics.data.security.CurrencyPairSecurity; +import ru.clearing.classes.statics.data.security.DigitalCertificateSecurity; import ru.clearing.classes.statics.data.security.MoneyMarketSecurity; +import ru.clearing.classes.statics.data.security.UtilitarianDigitalRight; import ru.clearing.platform.dictionary.InstrumentTypeDictionary; +import ru.clearing.platform.dictionary.NominalTypeCodeDictionary; +import ru.clearing.platform.dictionary.UnitMeasurementDictionary; +import ru.clearing.platform.dictionary.WorkflowStatusDictionary; import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountSymbolsNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.securitites.*; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CouponPeriodNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CouponPeriodUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CurrencyNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CurrencyUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.EquitySecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.EquitySecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.FixedIncomeSecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.UtilitarianDigitalRightNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.UtilitarianDigitalRightUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.security.CurrencyPairSecurityUpdateRequest; import ru.spcex.clearing.securities.errors.SecuritiesError; -import ru.spcex.clearing.securities.validation.rule.*; -import ru.spcex.clearing.validation.common.rules.*; +import ru.spcex.clearing.securities.validation.rule.CouponPeriodNewValidationRule; +import ru.spcex.clearing.securities.validation.rule.CouponPeriodUpdateValidationRule; +import ru.spcex.clearing.securities.validation.rule.CurrencyNewValidationRule; +import ru.spcex.clearing.securities.validation.rule.CurrencyUpdateValidationRule; +import ru.spcex.clearing.securities.validation.rule.EquityNewValidationRule; +import ru.spcex.clearing.securities.validation.rule.FixedIncomeNewValidationRule; +import ru.spcex.clearing.securities.validation.rule.HaveValidCodeByDictionary; +import ru.spcex.clearing.securities.validation.rule.HaveValidCompanyId; +import ru.spcex.clearing.securities.validation.rule.IsValidInstrumentTypeById; +import ru.spcex.clearing.securities.validation.rule.IsValidInstrumentTypeFromRequest; +import ru.spcex.clearing.securities.validation.rule.MmsNewValidationRule; +import ru.spcex.clearing.securities.validation.rule.NotPresentBySecuritySymbol; +import ru.spcex.clearing.securities.validation.rule.WorkflowStatusActv; +import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule; +import ru.spcex.clearing.validation.common.rules.EndDtAfterStartDtRule; +import ru.spcex.clearing.validation.common.rules.FieldNotBlankRequiredRule; +import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; +import ru.spcex.clearing.validation.common.rules.IdPresentRule; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.interfaces.WithInstrumentType; -import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.enumeration.InstrumentType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.rule.PresentById; import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.ValidatorImpl; -import java.util.Collection; -import java.util.HashMap; -import java.util.function.Function; - @Component public class ValidationProvider { + private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg mmsMap; private final Imdg equityMap; private final Imdg fixedIncomeMap; @@ -49,6 +82,11 @@ public class ValidationProvider { private final Imdg currencyImdg; private final Imdg couponPeriodImdg; private final Imdg currencyPairSecurityMap; + private final Imdg digitalCertificateMap; + private final Imdg nominalTypeCodeDictionaryMap; + private final Imdg utilitarianDigitalRightMap; + private final Imdg unitMeasurementDictionaryImdg; + public ValidationProvider(ImdgProvider imdgProvider) { @@ -66,6 +104,10 @@ public class ValidationProvider { this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, SpcexObjectBase.class); this.couponPeriodImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CouponPeriod, SpcexObjectBase.class); this.currencyPairSecurityMap = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class); + this.digitalCertificateMap = imdgProvider.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class); + this.nominalTypeCodeDictionaryMap = imdgProvider.getImdg(IMDGDistributedNames.Map_NominalTypeCodeDictionary, NominalTypeCodeDictionary.class); + this.utilitarianDigitalRightMap = imdgProvider.getImdg(IMDGDistributedNames.Map_UtilitarianDigitalRight, UtilitarianDigitalRight.class); + this.unitMeasurementDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UnitMeasurementDictionary, UnitMeasurementDictionary.class); } public Function mmsNewValidator() { @@ -465,4 +507,207 @@ public class ValidationProvider { ); }; } + + public Function digitalCertificateNewValidator() { + return digitalCertificateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(digitalCertificateRequest); + context.addImdg(IMDGDistributedNames.Map_Company, companyImdg); + context.addImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, digitalCertificateMap); + context.addImdg(IMDGDistributedNames.Map_InstrumentTypeDictionary, instrumentTypeDictionaryImdg); + context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg); + context.addImdg(IMDGDistributedNames.Map_NominalTypeCodeDictionary, nominalTypeCodeDictionaryMap); + return new ValidatorImpl<>(context, + new NotPresentBySecuritySymbol<>( + IMDGDistributedNames.Map_DigitalCertificateSecurity, + SecuritiesError.InstrumentAlreadyExists, + DigitalCertificateSecurity.class + ), + IdPresentRule.instance( + "issuerId", + DigitalCertificateSecurityNewRequest::getIssuerId, + IMDGDistributedNames.Map_Company, + Company.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.WrongFieldValue, + false + ), + DictionaryPresentRule.instance( + "instrumentType", + WithInstrumentType::getInstrumentType, + IMDGDistributedNames.Map_InstrumentTypeDictionary, + InstrumentTypeDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.DictionaryNotFound, + instrument -> !InstrumentType.DGCT.getKey().equalsIgnoreCase(instrument.getCode()) ? SecuritiesError.WrongFieldValue : null + ), + DictionaryPresentRule.instance( + "workflowStatus", + DigitalCertificateSecurityNewRequest::getWorkflowStatus, + IMDGDistributedNames.Map_WorkflowStatusDictionary, + WorkflowStatusDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.DictionaryNotFound, + false + ), + DictionaryPresentRule.instance( + "nominalType", + DigitalCertificateSecurityNewRequest::getNominalTypeCode, + IMDGDistributedNames.Map_NominalTypeCodeDictionary, + NominalTypeCodeDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.DictionaryNotFound, + false + ) + ); + }; + } + + public Function digitalCertificateUpdateValidator() { + return digitalCertificateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(digitalCertificateRequest); + context.addImdg(IMDGDistributedNames.Map_Company, companyImdg); + context.addImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, digitalCertificateMap); + context.addImdg(IMDGDistributedNames.Map_InstrumentTypeDictionary, instrumentTypeDictionaryImdg); + context.addImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, workflowStatusDictionaryImdg); + context.addImdg(IMDGDistributedNames.Map_NominalTypeCodeDictionary, nominalTypeCodeDictionaryMap); + return new ValidatorImpl<>(context, + IdPresentRule.instance( + "id", + DigitalCertificateSecurityUpdateRequest::getId, + IMDGDistributedNames.Map_DigitalCertificateSecurity, + DigitalCertificateSecurity.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.InstrumentNotFound + ), + IdPresentRule.instance( + "issuerId", + DigitalCertificateSecurityUpdateRequest::getIssuerId, + IMDGDistributedNames.Map_Company, + Company.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.WrongFieldValue, + false + ), + DictionaryPresentRule.instance( + "instrumentType", + WithInstrumentType::getInstrumentType, + IMDGDistributedNames.Map_InstrumentTypeDictionary, + InstrumentTypeDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.DictionaryNotFound, + instrument -> !InstrumentType.DGCT.getKey().equalsIgnoreCase(instrument.getCode()) ? SecuritiesError.WrongFieldValue : null + ), + DictionaryPresentRule.instance( + "workflowStatus", + DigitalCertificateSecurityUpdateRequest::getWorkflowStatus, + IMDGDistributedNames.Map_WorkflowStatusDictionary, + WorkflowStatusDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.DictionaryNotFound, + false + ), + DictionaryPresentRule.instance( + "nominalType", + DigitalCertificateSecurityUpdateRequest::getNominalTypeCode, + IMDGDistributedNames.Map_NominalTypeCodeDictionary, + NominalTypeCodeDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.DictionaryNotFound, + false + ) + ); + }; + } + + public Function digitalCertificateDeleteValidator() { + return digitalCertificateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(digitalCertificateRequest); + context.addImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, digitalCertificateMap); + return new ValidatorImpl<>(context, + new PresentById(IMDGDistributedNames.Map_DigitalCertificateSecurity, SecuritiesError.InstrumentNotFound, true), + new IsValidInstrumentTypeById(SecuritiesError.InstrumentNotFound, InstrumentType.DGCT.getKey()), + new WorkflowStatusActv() + ); + }; + } + + public Function utilitarianDigitalRightNewValidator() { + return utilitarianDigitalRightRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(utilitarianDigitalRightRequest); + context.addImdg(IMDGDistributedNames.Map_UtilitarianDigitalRight, utilitarianDigitalRightMap); + context.addImdg(IMDGDistributedNames.Map_UnitMeasurementDictionary, unitMeasurementDictionaryImdg); + return new ValidatorImpl<>(context, + FieldRequiredRule.instance( + "securityId", + UtilitarianDigitalRightNewRequest::getSecurityId, + SecuritiesError.RequiredFieldIsEmpty, + true, + (securityId) -> { + Imdg utilitarianDigitalRightImdg = context.obtainMap( + IMDGDistributedNames.Map_UtilitarianDigitalRight, UtilitarianDigitalRight.class + ); + ImdgPredicateBuilder pb = utilitarianDigitalRightImdg.predicateBuilder(); + Collection rights = utilitarianDigitalRightImdg.getCollectionObjectsByPredicate( + pb.equals("securityId", securityId) + ); + if (rights.isEmpty()) return null; + return SecuritiesError.CouponPeriodAlreadyExists; + } + ), + DictionaryPresentRule.instance( + "rightUnitMeasurement", + UtilitarianDigitalRightNewRequest::getRightUnitMeasurement, + IMDGDistributedNames.Map_UnitMeasurementDictionary, + UnitMeasurementDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.WrongFieldValue, + false + ) + ); + }; + } + + public Function utilitarianDigitalRightUpdateValidator() { + return utilitarianDigitalRightRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(utilitarianDigitalRightRequest); + context.addImdg(IMDGDistributedNames.Map_UtilitarianDigitalRight, utilitarianDigitalRightMap); + context.addImdg(IMDGDistributedNames.Map_UnitMeasurementDictionary, unitMeasurementDictionaryImdg); + return new ValidatorImpl<>(context, + FieldRequiredRule.instance( + "securityId", + UtilitarianDigitalRightUpdateRequest::getSecurityId, + SecuritiesError.RequiredFieldIsEmpty, + true, + (securityId) -> { + Imdg utilitarianDigitalRightImdg = context.obtainMap( + IMDGDistributedNames.Map_UtilitarianDigitalRight, UtilitarianDigitalRight.class + ); + ImdgPredicateBuilder pb = utilitarianDigitalRightImdg.predicateBuilder(); + Collection rights = utilitarianDigitalRightImdg.getCollectionObjectsByPredicate( + pb.equals("securityId", securityId) + ); + if (!rights.isEmpty()) { + if (rights.size() > 1) log.warn("Found >1 utilitarian digital right for securityId {}", securityId); + return null; + } + return SecuritiesError.CouponPeriodNotFound; + } + ), + DictionaryPresentRule.instance( + "rightUnitMeasurement", + UtilitarianDigitalRightUpdateRequest::getRightUnitMeasurement, + IMDGDistributedNames.Map_UnitMeasurementDictionary, + UnitMeasurementDictionary.class, + SecuritiesError.RequiredFieldIsEmpty, + SecuritiesError.WrongFieldValue, + false + ) + ); + }; + } } diff --git a/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/AbstractServiceTest.java b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/AbstractServiceTest.java index aca650384..2a178a7c4 100644 --- a/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/AbstractServiceTest.java +++ b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/AbstractServiceTest.java @@ -1,5 +1,6 @@ package ru.spcex.clearing.securities.service; +import java.util.concurrent.atomic.AtomicLong; import org.apache.kafka.clients.producer.Producer; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -12,34 +13,49 @@ import ru.clearing.classes.statics.data.instrument.issue.EquitySecurity; import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity; import ru.clearing.classes.statics.data.misc.Currency; import ru.clearing.classes.statics.data.misc.Listing; +import ru.clearing.classes.statics.data.security.DigitalCertificateSecurity; import ru.clearing.classes.statics.data.security.MoneyMarketSecurity; -import ru.clearing.platform.dictionary.*; +import ru.clearing.classes.statics.data.security.UtilitarianDigitalRight; +import ru.clearing.platform.dictionary.BondTypeDictionary; +import ru.clearing.platform.dictionary.CurrencyCodeDictionary; +import ru.clearing.platform.dictionary.InstrumentTypeDictionary; +import ru.clearing.platform.dictionary.ShareTypeDictionary; +import ru.clearing.platform.dictionary.TermTypeDictionary; +import ru.clearing.platform.dictionary.UnitMeasurementDictionary; +import ru.clearing.platform.dictionary.WorkflowStatusDictionary; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.securities.config.ErrorResolverConfig; import ru.spcex.clearing.securities.config.SecuritySelectorConfig; import ru.spcex.clearing.securities.config.ValidationConfig; -import ru.spcex.clearing.securities.service.cud.*; +import ru.spcex.clearing.securities.service.cud.CouponPeriodService; +import ru.spcex.clearing.securities.service.cud.CurrencyService; +import ru.spcex.clearing.securities.service.cud.DigitalCertificateSecurityService; +import ru.spcex.clearing.securities.service.cud.EquitySecurityService; +import ru.spcex.clearing.securities.service.cud.FixedIncomeSecurityService; +import ru.spcex.clearing.securities.service.cud.ListingService; +import ru.spcex.clearing.securities.service.cud.MoneyMarketSecurityService; +import ru.spcex.clearing.securities.service.cud.UtilitarianDigitalRightService; import ru.spcex.clearing.securities.validation.ListingValidationProvider; import ru.spcex.clearing.securities.validation.ValidationProvider; import ru.spcex.clearing.test.MatcherFactory; +import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator; import ru.spcex.clearing.test.config.ImdgTestConfig; +import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProviderAndAddAdminWithDefaultId; import ru.spcex.clearing.test.config.KafkaTestConfig; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; -import java.util.concurrent.atomic.AtomicLong; - -import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator; -import static ru.spcex.clearing.test.config.ImdgTestConfig.waitAvailableImdgProviderAndAddAdminWithDefaultId; - @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { CouponPeriodService.class, + UtilitarianDigitalRightService.class, CurrencyService.class, EquitySecurityService.class, + DigitalCertificateSecurityService.class, FixedIncomeSecurityService.class, MoneyMarketSecurityService.class, - ListingService.class, ListingValidationProvider.class, + ListingService.class, + ListingValidationProvider.class, SecuritySelectorConfig.class, ImdgTestConfig.class, KafkaTestConfig.class, @@ -52,9 +68,11 @@ public abstract class AbstractServiceTest { protected Imdg moneyMarketSecurityMap; protected Imdg listingImdg; protected Imdg equitySecurityImdg; + protected Imdg digitalCertificateSecurityImdg; protected Imdg fixedIncomeSecurityImdg; protected Imdg instrumentTypeDictionaryImdg; protected Imdg workflowStatusDictionaryImdg; + protected Imdg unitMeasurementDictionaryImdg; protected Imdg termTypeDictionaryImdg; protected Imdg currencyCodeDictionaryImdg; protected Imdg shareTypeDictionaryImdg; @@ -62,15 +80,18 @@ public abstract class AbstractServiceTest { protected Imdg companyImdg; protected Imdg currencyImdg; protected Imdg couponPeriodImdg; + protected Imdg utilitarianDigitalRightImdg; public static String RATE = "RATE"; protected String EQTY = "EQTY"; protected String BOND = "BOND"; + protected String DGCT = "DGCT"; protected String shareType = "shareType"; protected String bondType = "bondType"; public static Long issuerId = 13243L; public static String termType = "TermType"; public static String currencyCode = "RUB"; + public static String measurementUnit = "KG"; @Autowired @Qualifier("mockProducer") @@ -84,9 +105,11 @@ public abstract class AbstractServiceTest { this.moneyMarketSecurityMap = imdgProvider.getImdg(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class); this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class); this.equitySecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class); + this.digitalCertificateSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class); this.fixedIncomeSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeSecurity, FixedIncomeSecurity.class); this.instrumentTypeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_InstrumentTypeDictionary, InstrumentTypeDictionary.class); this.workflowStatusDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_WorkflowStatusDictionary, WorkflowStatusDictionary.class); + this.unitMeasurementDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UnitMeasurementDictionary, UnitMeasurementDictionary.class); this.termTypeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TermTypeDictionary, TermTypeDictionary.class); this.currencyCodeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class); this.shareTypeDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ShareTypeDictionary, ShareTypeDictionary.class); @@ -94,6 +117,7 @@ public abstract class AbstractServiceTest { this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class); this.couponPeriodImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CouponPeriod, CouponPeriod.class); + this.utilitarianDigitalRightImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UtilitarianDigitalRight, UtilitarianDigitalRight.class); InstrumentTypeDictionary instrumentTypeDictionary = new InstrumentTypeDictionary(); instrumentTypeDictionary.setId(1L); @@ -105,6 +129,9 @@ public abstract class AbstractServiceTest { instrumentTypeDictionary.setId(3L); instrumentTypeDictionary.setCode(BOND); instrumentTypeDictionaryImdg.insert(instrumentTypeDictionary); + instrumentTypeDictionary.setId(4L); + instrumentTypeDictionary.setCode(DGCT); + instrumentTypeDictionaryImdg.insert(instrumentTypeDictionary); WorkflowStatusDictionary workflowStatusDictionary = new WorkflowStatusDictionary(); workflowStatusDictionary.setCode(ru.spcex.platform.enumeration.Status.Active.getKey()); workflowStatusDictionaryImdg.insert(workflowStatusDictionary); @@ -120,6 +147,9 @@ public abstract class AbstractServiceTest { BondTypeDictionary bondTypeDictionary = new BondTypeDictionary(); bondTypeDictionary.setCode(bondType); bondTypeDictionaryImdg.insert(bondTypeDictionary); + UnitMeasurementDictionary unitMeasurementDictionary = new UnitMeasurementDictionary(); + unitMeasurementDictionary.setCode(measurementUnit); + unitMeasurementDictionaryImdg.insert(unitMeasurementDictionary); Company company = new Company(); company.setId(issuerId); companyImdg.insert(company); diff --git a/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/DigitalCertificateSecurityServiceTest.java b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/DigitalCertificateSecurityServiceTest.java new file mode 100644 index 000000000..c553e8355 --- /dev/null +++ b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/DigitalCertificateSecurityServiceTest.java @@ -0,0 +1,148 @@ +package ru.spcex.clearing.securities.service; + +import javax.annotation.PostConstruct; +import org.apache.kafka.clients.consumer.MockConsumer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import ru.clearing.classes.statics.data.security.DigitalCertificateSecurity; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityUpdateRequest; +import ru.spcex.clearing.securities.service.cud.DigitalCertificateSecurityService; +import ru.spcex.clearing.test.MatcherFactory; +import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator; +import static ru.spcex.clearing.test.TestUtils.*; + +public class DigitalCertificateSecurityServiceTest extends AbstractServiceTest { + private static final MatcherFactory.Matcher DIGITAL_CERTIFICATE_SECURITY_MATCHER = usingIgnoringFieldsComparator("created", "updated"); + private final long ID = currentId.getAndIncrement(); + private final int PARTITION = 0; + @Autowired + private DigitalCertificateSecurityService digitalCertificateSecurityService; + + @PostConstruct + protected void init() { + super.init(); + } + + @Test + public void testNewDigitalCertificate() { + clearAllInImdg(digitalCertificateSecurityImdg); + final String TOPIC = Consts.DESTINATION_DIGITAL_CERTIFICATE_SECURITY_NEW; + + final DigitalCertificateSecurity digitalCertificatePrediction = getDigitalCertificateSecurity(); + final DigitalCertificateSecurityNewRequest request = getDigitalCertificateSecurityNewRequest(digitalCertificatePrediction); + + //ACT + String jsonString = getJsonStringForNew(request, ID); + + addRecordToKafka((MockConsumer) digitalCertificateSecurityService.getConsumer(), TOPIC, PARTITION, 0, jsonString); + + //ASSERT + waitingSendAndCheckRecord(ID, mockProducer); + + DigitalCertificateSecurity digitalCertificateSecurity = digitalCertificateSecurityImdg.getFirstObjectBySQL( + String.format("fullName = %s", digitalCertificatePrediction.getFullName()) + ); + digitalCertificatePrediction.setId(digitalCertificateSecurity.getId()); + digitalCertificatePrediction.setSecurityId(digitalCertificateSecurity.getSecurityId()); + DIGITAL_CERTIFICATE_SECURITY_MATCHER.assertMatch(digitalCertificateSecurity, digitalCertificatePrediction); + } + + @Test + public void testUpdateDigitalCertificate() { + clearAllInImdg(digitalCertificateSecurityImdg); + final String TOPIC = Consts.DESTINATION_DIGITAL_CERTIFICATE_SECURITY_UPDATE; + String fullName = "FullNameUpdate"; + + final DigitalCertificateSecurity digitalCertificateSecurity = getDigitalCertificateSecurity(); + digitalCertificateSecurityImdg.insert(digitalCertificateSecurity); + digitalCertificateSecurity.setFullName(fullName); + final DigitalCertificateSecurityUpdateRequest request = getDigitalCertificateSecurityUpdateRequest(digitalCertificateSecurity); + + //ACT + String jsonString = getJsonStringForUpdate(request, ID); + + addRecordToKafka((MockConsumer) digitalCertificateSecurityService.getConsumer(), TOPIC, PARTITION, 0, jsonString); + + //ASSERT + waitingSendAndCheckRecord(ID, mockProducer); + + DigitalCertificateSecurity result = digitalCertificateSecurityImdg.getFirstObjectBySQL( + String.format("fullName = %s", digitalCertificateSecurity.getFullName()) + ); + digitalCertificateSecurity.setId(result.getId()); + digitalCertificateSecurity.setSecurityId(result.getSecurityId()); + DIGITAL_CERTIFICATE_SECURITY_MATCHER.assertMatch(result, digitalCertificateSecurity); + } + + @Test + public void testDeleteDigitalCertificate() { + clearAllInImdg(digitalCertificateSecurityImdg); + final String TOPIC = Consts.DESTINATION_DIGITAL_CERTIFICATE_SECURITY_DELETE; + + final DigitalCertificateSecurity digitalCertificateSecurity = getDigitalCertificateSecurity(); + digitalCertificateSecurityImdg.insert(digitalCertificateSecurity); + digitalCertificateSecurity.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey()); + + CommonDeleteRequest commonDeleteRequest = new CommonDeleteRequest(); + commonDeleteRequest.setId(ID); + + //ACT + String jsonString = getJsonStringForDelete(commonDeleteRequest, ID); + + addRecordToKafka((MockConsumer) digitalCertificateSecurityService.getConsumer(), TOPIC, PARTITION, 0, jsonString); + + //ASSERT + waitingSendAndCheckRecord(ID, mockProducer); + + DigitalCertificateSecurity result = digitalCertificateSecurityImdg.getFirstObjectBySQL( + String.format("fullName = %s", digitalCertificateSecurity.getFullName()) + ); + digitalCertificateSecurity.setId(result.getId()); + digitalCertificateSecurity.setSecurityId(result.getSecurityId()); + DIGITAL_CERTIFICATE_SECURITY_MATCHER.assertMatch(result, digitalCertificateSecurity); + } + + private DigitalCertificateSecurity getDigitalCertificateSecurity() { + DigitalCertificateSecurity digitalCertificateSecurity = new DigitalCertificateSecurity(); + digitalCertificateSecurity.setId(ID); + digitalCertificateSecurity.setSecuritySymbol("SecuritySymbol"); + digitalCertificateSecurity.setShortName("ShortNameNewEquity"); + digitalCertificateSecurity.setFullName("FullNameNewEquity"); + digitalCertificateSecurity.setIssuerId(issuerId); + digitalCertificateSecurity.setShortNameEng("ShortNameNewEquity"); + digitalCertificateSecurity.setFullNameEng("FullNameNewEquity"); + digitalCertificateSecurity.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Active.getKey()); + digitalCertificateSecurity.setInstrumentType(DGCT); + return digitalCertificateSecurity; + } + + private DigitalCertificateSecurityNewRequest getDigitalCertificateSecurityNewRequest(DigitalCertificateSecurity digitalCertificateSecurity) { + DigitalCertificateSecurityNewRequest digitalCertificateSecurityNewRequest = new DigitalCertificateSecurityNewRequest(); + digitalCertificateSecurityNewRequest.setSecuritySymbol(digitalCertificateSecurity.getSecuritySymbol()); + digitalCertificateSecurityNewRequest.setShortName(digitalCertificateSecurity.getShortName()); + digitalCertificateSecurityNewRequest.setFullName(digitalCertificateSecurity.getFullName()); + digitalCertificateSecurityNewRequest.setIssuerId(digitalCertificateSecurity.getIssuerId()); + digitalCertificateSecurityNewRequest.setShortNameEng(digitalCertificateSecurity.getShortNameEng()); + digitalCertificateSecurityNewRequest.setFullNameEng(digitalCertificateSecurity.getFullNameEng()); + digitalCertificateSecurityNewRequest.setWorkflowStatus(digitalCertificateSecurity.getWorkflowStatus()); + digitalCertificateSecurityNewRequest.setInstrumentType(digitalCertificateSecurity.getInstrumentType()); + return digitalCertificateSecurityNewRequest; + } + + private DigitalCertificateSecurityUpdateRequest getDigitalCertificateSecurityUpdateRequest(DigitalCertificateSecurity digitalCertificateSecurity) { + DigitalCertificateSecurityUpdateRequest digitalCertificateSecurityUpdateRequest = new DigitalCertificateSecurityUpdateRequest(); + digitalCertificateSecurityUpdateRequest.setId(digitalCertificateSecurity.getId()); + digitalCertificateSecurityUpdateRequest.setSecuritySymbol(digitalCertificateSecurity.getSecuritySymbol()); + digitalCertificateSecurityUpdateRequest.setShortName(digitalCertificateSecurity.getShortName()); + digitalCertificateSecurityUpdateRequest.setFullName(digitalCertificateSecurity.getFullName()); + digitalCertificateSecurityUpdateRequest.setIssuerId(digitalCertificateSecurity.getIssuerId()); + digitalCertificateSecurityUpdateRequest.setShortNameEng(digitalCertificateSecurity.getShortNameEng()); + digitalCertificateSecurityUpdateRequest.setFullNameEng(digitalCertificateSecurity.getFullNameEng()); + digitalCertificateSecurityUpdateRequest.setWorkflowStatus(digitalCertificateSecurity.getWorkflowStatus()); + digitalCertificateSecurityUpdateRequest.setInstrumentType(digitalCertificateSecurity.getInstrumentType()); + return digitalCertificateSecurityUpdateRequest; + } +} diff --git a/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/UtilitarianDigitalRightServiceTest.java b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/UtilitarianDigitalRightServiceTest.java new file mode 100644 index 000000000..7aa2ef4a7 --- /dev/null +++ b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/UtilitarianDigitalRightServiceTest.java @@ -0,0 +1,108 @@ +package ru.spcex.clearing.securities.service; + +import java.math.BigDecimal; +import javax.annotation.PostConstruct; +import org.apache.kafka.clients.consumer.MockConsumer; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import ru.clearing.classes.statics.data.instrument.issue.CouponPeriod; +import ru.clearing.classes.statics.data.security.UtilitarianDigitalRight; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CouponPeriodNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.CouponPeriodUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.UtilitarianDigitalRightNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.UtilitarianDigitalRightUpdateRequest; +import ru.spcex.clearing.securities.service.cud.CouponPeriodService; +import ru.spcex.clearing.securities.service.cud.UtilitarianDigitalRightService; +import ru.spcex.clearing.test.MatcherFactory; +import static ru.spcex.clearing.test.MatcherFactory.usingIgnoringFieldsComparator; +import static ru.spcex.clearing.test.TestUtils.*; + +public class UtilitarianDigitalRightServiceTest extends AbstractServiceTest { + private static final MatcherFactory.Matcher UTILITARIAN_DIGITAL_RIGHT_MATCHER = usingIgnoringFieldsComparator(); + private final long ID = currentId.getAndIncrement(); + private final long securityId = 3123L; + private final long number = 30200L; + private final int PARTITION = 0; + private final String countryCode = "countryCode"; + private final String currencyCode = "currencyCode"; + @Autowired + private UtilitarianDigitalRightService utilitarianDigitalRightService; + + @PostConstruct + protected void init() { + super.init(); + } + + /** + * {@link CouponPeriodService#newCouponPeriod(BaseRequest)}
+ * Тест проверяет генерацию сущности {@link CouponPeriod} в Hazelcast при передаче из Apache Kafka.
+ * Входной запрос {@link CouponPeriodNewRequest}:
+ */ + @Test + public void testNewUtilitarianDigitalRight() { + clearAllInImdg(utilitarianDigitalRightImdg); + final String TOPIC = Consts.DESTINATION_UTILITARIAN_DIGITAL_RIGHT_NEW; + + final UtilitarianDigitalRight utilitarianDigitalRight = new UtilitarianDigitalRight(); + utilitarianDigitalRight.setSecurityId(securityId); + utilitarianDigitalRight.setRightUnitMeasurement(measurementUnit); + final UtilitarianDigitalRightNewRequest request = new UtilitarianDigitalRightNewRequest(); + request.setSecurityId(securityId); + request.setRightUnitMeasurement(measurementUnit); + + //ACT + String jsonString = getJsonStringForNew(request, ID); + + addRecordToKafka((MockConsumer) utilitarianDigitalRightService.getConsumer(), TOPIC, PARTITION, 0, jsonString); + + //ASSERT + waitingSendAndCheckRecord(ID, mockProducer); + + UtilitarianDigitalRight result = utilitarianDigitalRightImdg.getFirstObjectBySQL(String.format("securityId = %s", utilitarianDigitalRight.getSecurityId())); + utilitarianDigitalRight.setId(result.getId()); + UTILITARIAN_DIGITAL_RIGHT_MATCHER.assertMatch(result, utilitarianDigitalRight); + } + + /** + * {@link CouponPeriodService#updateCouponPeriod(BaseRequest)} + * Тест проверяет обновление сущности {@link CouponPeriod} в Hazelcast при передаче из Apache Kafka.
+ * Входной запрос {@link CouponPeriodUpdateRequest}:
+ */ + @Test + public void testUpdateUtilitarianDigitalRights() { + clearAllInImdg(utilitarianDigitalRightImdg); + final String TOPIC = Consts.DESTINATION_UTILITARIAN_DIGITAL_RIGHT_UPDATE; + final UtilitarianDigitalRight utilitarianDigitalRight = new UtilitarianDigitalRight(); + utilitarianDigitalRight.setSecurityId(securityId); + utilitarianDigitalRight.setRightUnitMeasurement(measurementUnit); + utilitarianDigitalRight.setIssueAmount(BigDecimal.ONE); + Long id = utilitarianDigitalRightImdg.insert(utilitarianDigitalRight); + + final UtilitarianDigitalRight predictableDigitalRight = new UtilitarianDigitalRight(); + predictableDigitalRight.setSecurityId(securityId); + predictableDigitalRight.setRightUnitMeasurement(measurementUnit); + predictableDigitalRight.setIssueAmount(BigDecimal.TEN); + + final UtilitarianDigitalRightUpdateRequest request = new UtilitarianDigitalRightUpdateRequest(); + request.setId(id); + request.setSecurityId(securityId); + request.setIssueAmount(BigDecimal.TEN); + request.setRightUnitMeasurement(measurementUnit); + + //ACT + String jsonString = getJsonStringForUpdate(request, id); + + addRecordToKafka((MockConsumer) utilitarianDigitalRightService.getConsumer(), TOPIC, PARTITION, 0, jsonString); + + //ASSERT + waitingSendAndCheckRecord(id, mockProducer); + + UtilitarianDigitalRight result = utilitarianDigitalRightImdg.getFirstObjectBySQL( + String.format("securityId = %s", predictableDigitalRight.getSecurityId()) + ); + predictableDigitalRight.setId(result.getId()); + UTILITARIAN_DIGITAL_RIGHT_MATCHER.assertMatch(result, predictableDigitalRight); + } +} diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java index 11e95d1db..af590ec67 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InstrumentType.java @@ -8,7 +8,8 @@ public enum InstrumentType implements IEnumKey { RATE("RATE"), // Инструмент Денежного рынка CRNC("CRNC"), // Валюта MFND("MFND"), - CURR("CURR") + CURR("CURR"), + DGCT("DGCT"), // Цифровые свидетельства ; private final String key; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java index f8ce20419..b7dbde28a 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java @@ -14,8 +14,16 @@ public interface Consts { String DESTINATION_FIXED_INCOME_SECURITY_UPDATE = "fixed-income-security-update"; String DESTINATION_FIXED_INCOME_SECURITY_DELETE = "fixed-income-security-delete"; + String DESTINATION_DIGITAL_CERTIFICATE_SECURITY_NEW = "digital-certificate-new"; + String DESTINATION_DIGITAL_CERTIFICATE_SECURITY_UPDATE = "digital-certificate-update"; + String DESTINATION_DIGITAL_CERTIFICATE_SECURITY_DELETE = "digital-certificate-delete"; + + String DESTINATION_UTILITARIAN_DIGITAL_RIGHT_NEW = "utilitarian-digital-right-new"; + String DESTINATION_UTILITARIAN_DIGITAL_RIGHT_UPDATE = "utilitarian-digital-right-update"; + String DESTINATION_SECURITY_BOND_GATEWAY = "security-bond-gateway-request-new"; String DESTINATION_SECURITY_EQTY_GATEWAY = "security-eqty-gateway-request-new"; + String DESTINATION_SECURITY_DGCT_GATEWAY = "security-dgct-gateway-request-new"; String DESTINATION_GATEWAY_CURRENCY_PAIR_SECURITY = "currency-pair-securities-gateway-new"; // "security-currency-pair-gateway-request-new" String DESTINATION_FIXED_INCOME_CASH_FLOW_NEW = "fixed-income-cash-flow-new"; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/company/DigitalCertificateSecurityGatewayRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/company/DigitalCertificateSecurityGatewayRequest.java new file mode 100644 index 000000000..e882cb1da --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/company/DigitalCertificateSecurityGatewayRequest.java @@ -0,0 +1,24 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.company; + +import com.fasterxml.jackson.annotation.JsonProperty; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.DigitalCertificateSecurityNewRequest; + +public class DigitalCertificateSecurityGatewayRequest extends SecurityFondGatewayRequest { + @JsonProperty + private DigitalCertificateSecurityNewRequest security; + + public DigitalCertificateSecurityGatewayRequest() { + } + + public DigitalCertificateSecurityGatewayRequest(DigitalCertificateSecurityNewRequest security) { + this.security = security; + } + + public DigitalCertificateSecurityNewRequest getSecurity() { + return security; + } + + public void setSecurity(DigitalCertificateSecurityNewRequest security) { + this.security = security; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityNewRequest.java new file mode 100644 index 000000000..0ec23da60 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityNewRequest.java @@ -0,0 +1,205 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import java.math.BigDecimal; +import java.time.LocalDate; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; +import ru.spcex.platform.classes.base.interfaces.WithInstrumentType; +import ru.spcex.platform.classes.base.interfaces.WithSecuritySymbol; + +public class DigitalCertificateSecurityNewRequest implements WithSecuritySymbol, WithInstrumentType { + @JsonProperty + private String securitySymbol; + + @JsonProperty + private String instrumentType; + + @JsonProperty + private String baseCode; + + @JsonProperty + private String shortName; + + @JsonProperty + private String fullName; + + @JsonProperty + private Long issuerId; + + @JsonProperty + private String shortNameEng; + + @JsonProperty + private String fullNameEng; + + @JsonProperty + private String workflowStatus; + + @JsonProperty + private Long baseUnitSize; + + @JsonProperty + private BigDecimal priceVarianceLimit; + + @JsonProperty + private String nominalTypeCode; + + @JsonProperty + private BigDecimal nominalValue; + + @JsonProperty + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + private LocalDate nominalIndexationDate; + + @JsonProperty + private String nominalIndexationSign; + + @JsonProperty + private String settlementHouse; + + @JsonProperty + private String depository; + + + @Override + public String getSecuritySymbol() { + return securitySymbol; + } + + public void setSecuritySymbol(String securitySymbol) { + this.securitySymbol = securitySymbol; + } + + @Override + public String getInstrumentType() { + return instrumentType; + } + + public void setInstrumentType(String instrumentType) { + this.instrumentType = instrumentType; + } + + public String getBaseCode() { + return baseCode; + } + + public void setBaseCode(String baseCode) { + this.baseCode = baseCode; + } + + 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 Long getIssuerId() { + return issuerId; + } + + public void setIssuerId(Long issuerId) { + this.issuerId = issuerId; + } + + 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 getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } + + public Long getBaseUnitSize() { + return baseUnitSize; + } + + public void setBaseUnitSize(Long baseUnitSize) { + this.baseUnitSize = baseUnitSize; + } + + public BigDecimal getPriceVarianceLimit() { + return priceVarianceLimit; + } + + public void setPriceVarianceLimit(BigDecimal priceVarianceLimit) { + this.priceVarianceLimit = priceVarianceLimit; + } + + public String getNominalTypeCode() { + return nominalTypeCode; + } + + public void setNominalTypeCode(String nominalTypeCode) { + this.nominalTypeCode = nominalTypeCode; + } + + public BigDecimal getNominalValue() { + return nominalValue; + } + + public void setNominalValue(BigDecimal nominalValue) { + this.nominalValue = nominalValue; + } + + public LocalDate getNominalIndexationDate() { + return nominalIndexationDate; + } + + public void setNominalIndexationDate(LocalDate nominalIndexationDate) { + this.nominalIndexationDate = nominalIndexationDate; + } + + public String getNominalIndexationSign() { + return nominalIndexationSign; + } + + public void setNominalIndexationSign(String nominalIndexationSign) { + this.nominalIndexationSign = nominalIndexationSign; + } + + public String getSettlementHouse() { + return settlementHouse; + } + + public void setSettlementHouse(String settlementHouse) { + this.settlementHouse = settlementHouse; + } + + public String getDepository() { + return depository; + } + + public void setDepository(String depository) { + this.depository = depository; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityUpdateRequest.java new file mode 100644 index 000000000..9a7d7cab8 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/DigitalCertificateSecurityUpdateRequest.java @@ -0,0 +1,217 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import java.math.BigDecimal; +import java.time.LocalDate; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import ru.spcex.clearing.platform.messaging.domain.json.deserialize.LocalDateDeserializer; +import ru.spcex.clearing.platform.messaging.domain.json.serialize.LocalDateSerializer; +import ru.spcex.platform.classes.base.interfaces.WithId; +import ru.spcex.platform.classes.base.interfaces.WithInstrumentType; +import ru.spcex.platform.classes.base.interfaces.WithSecuritySymbol; + +public class DigitalCertificateSecurityUpdateRequest implements WithId, WithSecuritySymbol, WithInstrumentType { + @JsonProperty + private Long id; + + @JsonProperty + private String securitySymbol; + + @JsonProperty + private String instrumentType; + + @JsonProperty + private String baseCode; + + @JsonProperty + private String shortName; + + @JsonProperty + private String fullName; + + @JsonProperty + private Long issuerId; + + @JsonProperty + private String shortNameEng; + + @JsonProperty + private String fullNameEng; + + @JsonProperty + private String workflowStatus; + + @JsonProperty + private Long baseUnitSize; + + @JsonProperty + private BigDecimal priceVarianceLimit; + + @JsonProperty + private String nominalTypeCode; + + @JsonProperty + private BigDecimal nominalValue; + + @JsonProperty + @JsonSerialize(using = LocalDateSerializer.class) + @JsonDeserialize(using = LocalDateDeserializer.class) + private LocalDate nominalIndexationDate; + + @JsonProperty + private String nominalIndexationSign; + + @JsonProperty + private String settlementHouse; + + @JsonProperty + private String depository; + + + @Override + public String getSecuritySymbol() { + return securitySymbol; + } + + public void setSecuritySymbol(String securitySymbol) { + this.securitySymbol = securitySymbol; + } + + @Override + public String getInstrumentType() { + return instrumentType; + } + + public void setInstrumentType(String instrumentType) { + this.instrumentType = instrumentType; + } + + public String getBaseCode() { + return baseCode; + } + + public void setBaseCode(String baseCode) { + this.baseCode = baseCode; + } + + 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 Long getIssuerId() { + return issuerId; + } + + public void setIssuerId(Long issuerId) { + this.issuerId = issuerId; + } + + 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 getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } + + public Long getBaseUnitSize() { + return baseUnitSize; + } + + public void setBaseUnitSize(Long baseUnitSize) { + this.baseUnitSize = baseUnitSize; + } + + public BigDecimal getPriceVarianceLimit() { + return priceVarianceLimit; + } + + public void setPriceVarianceLimit(BigDecimal priceVarianceLimit) { + this.priceVarianceLimit = priceVarianceLimit; + } + + public String getNominalTypeCode() { + return nominalTypeCode; + } + + public void setNominalTypeCode(String nominalTypeCode) { + this.nominalTypeCode = nominalTypeCode; + } + + public BigDecimal getNominalValue() { + return nominalValue; + } + + public void setNominalValue(BigDecimal nominalValue) { + this.nominalValue = nominalValue; + } + + public LocalDate getNominalIndexationDate() { + return nominalIndexationDate; + } + + public void setNominalIndexationDate(LocalDate nominalIndexationDate) { + this.nominalIndexationDate = nominalIndexationDate; + } + + public String getNominalIndexationSign() { + return nominalIndexationSign; + } + + public void setNominalIndexationSign(String nominalIndexationSign) { + this.nominalIndexationSign = nominalIndexationSign; + } + + public String getSettlementHouse() { + return settlementHouse; + } + + public void setSettlementHouse(String settlementHouse) { + this.settlementHouse = settlementHouse; + } + + public String getDepository() { + return depository; + } + + public void setDepository(String depository) { + this.depository = depository; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightNewRequest.java new file mode 100644 index 000000000..58bc4e437 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightNewRequest.java @@ -0,0 +1,172 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import java.math.BigDecimal; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UtilitarianDigitalRightNewRequest { + @JsonProperty + private Long securityId; + + @JsonProperty + private String investmentAttractingCompany; + + @JsonProperty + private String investmentAttractingInn; + + @JsonProperty + private BigDecimal issueAmount; + + @JsonProperty + private BigDecimal issuePrice; + + @JsonProperty + private Long issueSize; + + @JsonProperty + private String nominalIndexation; + + @JsonProperty + private String platformOperator; + + @JsonProperty + private String platformOperatorCode; + + @JsonProperty + private String platformOperatorInn; + + @JsonProperty + private String platformOperatorWeb; + + @JsonProperty + private String platformProposalWeb; + + @JsonProperty + private String rightEssence; + + @JsonProperty + private String rightUnit; + + @JsonProperty + private String rightUnitMeasurement; + + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public String getInvestmentAttractingCompany() { + return investmentAttractingCompany; + } + + public void setInvestmentAttractingCompany(String investmentAttractingCompany) { + this.investmentAttractingCompany = investmentAttractingCompany; + } + + public String getInvestmentAttractingInn() { + return investmentAttractingInn; + } + + public void setInvestmentAttractingInn(String investmentAttractingInn) { + this.investmentAttractingInn = investmentAttractingInn; + } + + public BigDecimal getIssueAmount() { + return issueAmount; + } + + public void setIssueAmount(BigDecimal issueAmount) { + this.issueAmount = issueAmount; + } + + public BigDecimal getIssuePrice() { + return issuePrice; + } + + public void setIssuePrice(BigDecimal issuePrice) { + this.issuePrice = issuePrice; + } + + public Long getIssueSize() { + return issueSize; + } + + public void setIssueSize(Long issueSize) { + this.issueSize = issueSize; + } + + public String getNominalIndexation() { + return nominalIndexation; + } + + public void setNominalIndexation(String nominalIndexation) { + this.nominalIndexation = nominalIndexation; + } + + public String getPlatformOperator() { + return platformOperator; + } + + public void setPlatformOperator(String platformOperator) { + this.platformOperator = platformOperator; + } + + public String getPlatformOperatorCode() { + return platformOperatorCode; + } + + public void setPlatformOperatorCode(String platformOperatorCode) { + this.platformOperatorCode = platformOperatorCode; + } + + public String getPlatformOperatorInn() { + return platformOperatorInn; + } + + public void setPlatformOperatorInn(String platformOperatorInn) { + this.platformOperatorInn = platformOperatorInn; + } + + public String getPlatformOperatorWeb() { + return platformOperatorWeb; + } + + public void setPlatformOperatorWeb(String platformOperatorWeb) { + this.platformOperatorWeb = platformOperatorWeb; + } + + public String getPlatformProposalWeb() { + return platformProposalWeb; + } + + public void setPlatformProposalWeb(String platformProposalWeb) { + this.platformProposalWeb = platformProposalWeb; + } + + public String getRightEssence() { + return rightEssence; + } + + public void setRightEssence(String rightEssence) { + this.rightEssence = rightEssence; + } + + public String getRightUnit() { + return rightUnit; + } + + public void setRightUnit(String rightUnit) { + this.rightUnit = rightUnit; + } + + public String getRightUnitMeasurement() { + return rightUnitMeasurement; + } + + public void setRightUnitMeasurement(String rightUnitMeasurement) { + this.rightUnitMeasurement = rightUnitMeasurement; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightUpdateRequest.java new file mode 100644 index 000000000..a326c5352 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/UtilitarianDigitalRightUpdateRequest.java @@ -0,0 +1,185 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import java.math.BigDecimal; +import com.fasterxml.jackson.annotation.JsonProperty; +import ru.spcex.platform.classes.base.interfaces.WithId; + +public class UtilitarianDigitalRightUpdateRequest implements WithId { + @JsonProperty + private Long id; + + @JsonProperty + private Long securityId; + + @JsonProperty + private String investmentAttractingCompany; + + @JsonProperty + private String investmentAttractingInn; + + @JsonProperty + private BigDecimal issueAmount; + + @JsonProperty + private BigDecimal issuePrice; + + @JsonProperty + private Long issueSize; + + @JsonProperty + private String nominalIndexation; + + @JsonProperty + private String platformOperator; + + @JsonProperty + private String platformOperatorCode; + + @JsonProperty + private String platformOperatorInn; + + @JsonProperty + private String platformOperatorWeb; + + @JsonProperty + private String platformProposalWeb; + + @JsonProperty + private String rightEssence; + + @JsonProperty + private String rightUnit; + + @JsonProperty + private String rightUnitMeasurement; + + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public String getInvestmentAttractingCompany() { + return investmentAttractingCompany; + } + + public void setInvestmentAttractingCompany(String investmentAttractingCompany) { + this.investmentAttractingCompany = investmentAttractingCompany; + } + + public String getInvestmentAttractingInn() { + return investmentAttractingInn; + } + + public void setInvestmentAttractingInn(String investmentAttractingInn) { + this.investmentAttractingInn = investmentAttractingInn; + } + + public BigDecimal getIssueAmount() { + return issueAmount; + } + + public void setIssueAmount(BigDecimal issueAmount) { + this.issueAmount = issueAmount; + } + + public BigDecimal getIssuePrice() { + return issuePrice; + } + + public void setIssuePrice(BigDecimal issuePrice) { + this.issuePrice = issuePrice; + } + + public Long getIssueSize() { + return issueSize; + } + + public void setIssueSize(Long issueSize) { + this.issueSize = issueSize; + } + + public String getNominalIndexation() { + return nominalIndexation; + } + + public void setNominalIndexation(String nominalIndexation) { + this.nominalIndexation = nominalIndexation; + } + + public String getPlatformOperator() { + return platformOperator; + } + + public void setPlatformOperator(String platformOperator) { + this.platformOperator = platformOperator; + } + + public String getPlatformOperatorCode() { + return platformOperatorCode; + } + + public void setPlatformOperatorCode(String platformOperatorCode) { + this.platformOperatorCode = platformOperatorCode; + } + + public String getPlatformOperatorInn() { + return platformOperatorInn; + } + + public void setPlatformOperatorInn(String platformOperatorInn) { + this.platformOperatorInn = platformOperatorInn; + } + + public String getPlatformOperatorWeb() { + return platformOperatorWeb; + } + + public void setPlatformOperatorWeb(String platformOperatorWeb) { + this.platformOperatorWeb = platformOperatorWeb; + } + + public String getPlatformProposalWeb() { + return platformProposalWeb; + } + + public void setPlatformProposalWeb(String platformProposalWeb) { + this.platformProposalWeb = platformProposalWeb; + } + + public String getRightEssence() { + return rightEssence; + } + + public void setRightEssence(String rightEssence) { + this.rightEssence = rightEssence; + } + + public String getRightUnit() { + return rightUnit; + } + + public void setRightUnit(String rightUnit) { + this.rightUnit = rightUnit; + } + + public String getRightUnitMeasurement() { + return rightUnitMeasurement; + } + + public void setRightUnitMeasurement(String rightUnitMeasurement) { + this.rightUnitMeasurement = rightUnitMeasurement; + } + + @Override + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +}