diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ContactValidationConfig.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ContactValidationConfig.java new file mode 100644 index 000000000..3cb98b376 --- /dev/null +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ContactValidationConfig.java @@ -0,0 +1,106 @@ +package ru.spcex.clearing.company.config.validation; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.profile.Contact; +import ru.clearing.platform.dictionary.ContactTypeDictionary; +import ru.spcex.clearing.company.error.CompanyErrors; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest; +import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule; +import ru.spcex.clearing.validation.common.rules.EnumPresentRule; +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.enumeration.ContactTypes; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +@Configuration +public class ContactValidationConfig { + + @Bean("contactNewRequestValidator") + public Function contactNewRequestValidator( + Map> imdgForValidation + ) { + return contactNewRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(contactNewRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_ContactTypeDictionary); + return new ValidatorImpl<>(context, + IdPresentRule.instance("companyId", + ContactNewRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + CompanyErrors.RequiredFieldEmpty, + CompanyErrors.CompanyNotFound), + EnumPresentRule.instance("contactType", + ContactNewRequest::getContactType, + ContactTypes.values(), + CompanyErrors.WrongFieldValue, + CompanyErrors.RequiredFieldEmpty), + DictionaryPresentRule.instance("contactType", + ContactNewRequest::getContactType, + IMDGDistributedNames.Map_ContactTypeDictionary, + ContactTypeDictionary.class, + CompanyErrors.RequiredFieldEmpty, + CompanyErrors.WrongFieldValue), + FieldRequiredRule.instance("contactValue", + ContactNewRequest::getContactValue, + CompanyErrors.RequiredFieldEmpty) + ); + }; + } + + @Bean("contactUpdateRequestValidator") + public Function contactUpdateRequestValidator( + Map> imdgForValidation + ) { + return contactUpdateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(contactUpdateRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Contact); + addImdg.accept(IMDGDistributedNames.Map_ContactTypeDictionary); + return new ValidatorImpl<>(context, + IdPresentRule.instance("id", + ContactUpdateRequest::getId, + IMDGDistributedNames.Map_Contact, + Contact.class, + CompanyErrors.RequiredFieldEmpty, + CompanyErrors.CompanyNotFound, + contact -> { + if (contactUpdateRequest.getContactType() == null) return null; + if (!contactUpdateRequest.getContactType().equalsIgnoreCase(contact.getContactType())) { + return CompanyErrors.EditContactType; + } + return null; + }), + EnumPresentRule.instance("contactType", + ContactUpdateRequest::getContactType, + ContactTypes.values(), + false, + CompanyErrors.WrongFieldValue, + CompanyErrors.RequiredFieldEmpty), + DictionaryPresentRule.instance("contactType", + ContactUpdateRequest::getContactType, + IMDGDistributedNames.Map_ContactTypeDictionary, + ContactTypeDictionary.class, + CompanyErrors.RequiredFieldEmpty, + CompanyErrors.WrongFieldValue, + false) + ); + }; + } + +} diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ValidationConfig.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ValidationConfig.java index 20ce51e01..06c9aadc6 100644 --- a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ValidationConfig.java +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/validation/ValidationConfig.java @@ -4,8 +4,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.clearing.classes.statics.data.profile.Contact; import ru.clearing.classes.statics.data.profile.ProfileDocument; import ru.clearing.platform.dictionary.ClearingCategoryDictionary; +import ru.clearing.platform.dictionary.ContactTypeDictionary; import ru.clearing.platform.dictionary.DocumentTypeDictionary; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.validation.common.ValidationHelper; @@ -31,6 +33,8 @@ public class ValidationConfig { addImdg.accept(IMDGDistributedNames.Map_ClearingCategoryDictionary, ClearingCategoryDictionary.class); addImdg.accept(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class); addImdg.accept(IMDGDistributedNames.Map_DocumentTypeDictionary, DocumentTypeDictionary.class); + addImdg.accept(IMDGDistributedNames.Map_ContactTypeDictionary, ContactTypeDictionary.class); + addImdg.accept(IMDGDistributedNames.Map_Contact, Contact.class); addImdg.accept(IMDGDistributedNames.Map_WorkflowStatusDictionary, DocumentTypeDictionary.class); addImdg.accept(IMDGDistributedNames.Map_CompanySymbolDictionary, DocumentTypeDictionary.class); diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ContactService.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ContactService.java index 44940401c..814902983 100644 --- a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ContactService.java +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ContactService.java @@ -6,44 +6,90 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.profile.Contact; 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.ContactNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.validation.IValidator; + +import java.util.function.Function; @Service public class ContactService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg contactMap; + private final ValidationHelper validationHelper; + private final Function contactNewRequestValidator; + private final Function contactUpdateRequestValidator; @Autowired - public ContactService(Consumer kafkaQueue, Producer kafkaProducer, - ImdgProvider imdgProvider) { + public ContactService(Consumer kafkaQueue, + Producer kafkaProducer, + ImdgProvider imdgProvider, + ValidationHelper validationHelper, + @Qualifier("contactNewRequestValidator") Function contactNewRequestValidator, + @Qualifier("contactUpdateRequestValidator") Function contactUpdateRequestValidator) { super(kafkaQueue, kafkaProducer); this.contactMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Contact, Contact.class); + this.validationHelper = validationHelper; + this.contactNewRequestValidator = contactNewRequestValidator; + this.contactUpdateRequestValidator = contactUpdateRequestValidator; } @Override public void afterPropertiesSet() { + callback(ContactNewRequest.class) + .setConsumer(this::contactNew) + .forDestination(Consts.DESTINATION_CONTACT_NEW, callbacks::put); callback(ContactUpdateRequest.class) .setConsumer(this::contactUpdate) .forDestination(Consts.DESTINATION_CONTACT_UPDATE, callbacks::put); init(); } - public void contactUpdate(BaseRequest userRequest) { - ContactUpdateRequest req = userRequest.getRequestPayload(); + public RequestInfoUpdate contactNew(BaseRequest userRequest) { + log.debug("ContactNewRequest received"); + + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError( + userRequest, contactNewRequestValidator + ); + if (requestInfoUpdate != null) return requestInfoUpdate; + + ContactNewRequest contactNewRequest = userRequest.getRequestPayload(); + Contact contact = new Contact(); + contact.setCompanyId(contactNewRequest.getCompanyId()); + contact.setContactType(contactNewRequest.getContactType()); + contact.setContactValue(contactNewRequest.getContactValue()); + Long id = contactMap.insert(contact); + + log.debug("successfully processed, id {}", id); + return null; + } + + public RequestInfoUpdate contactUpdate(BaseRequest userRequest) { log.debug("ContactUpdateRequest received"); + + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError( + userRequest, contactUpdateRequestValidator + ); + if (requestInfoUpdate != null) return requestInfoUpdate; + + // Тип контакта не меняем, при валидации кидаем ошибку. + ContactUpdateRequest req = userRequest.getRequestPayload(); Contact contact = contactMap.getSingleObjectByID(req.getId()); -// contact.setContactType(req.getContactType()); по ТЗ не должен менятся при обновлении contact.setContactValue(req.getContactValue()); contactMap.update(contact); log.debug("successfully processed, id {}", contact.getId()); + return null; } } \ No newline at end of file diff --git a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java index 25ae9344b..4d78b455d 100644 --- a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java +++ b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java @@ -67,7 +67,7 @@ class ClearingMemberCategoryServiceTest { @SpyBean private MockProducer mockProducer; - private final long COMPANY_ID = 777L; + private long COMPANY_ID; private Company TEST_COMPANY; private final String CLEARING_CATEGORY_DICT_CODE = ClearingCategory.B.getKey(); @@ -87,9 +87,8 @@ class ClearingMemberCategoryServiceTest { Imdg companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class); TEST_COMPANY = new Company(); - TEST_COMPANY.setId(COMPANY_ID); TEST_COMPANY.setWorkflowStatus(WorkflowStatus.Active.getKey()); - companyImdg.insert(TEST_COMPANY); + COMPANY_ID = companyImdg.insert(TEST_COMPANY); clearingCategoryDictionary = new ClearingCategoryDictionary(); clearingCategoryDictionary.setCode(CLEARING_CATEGORY_DICT_CODE); diff --git a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ContactServiceTest.java b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ContactServiceTest.java index fe81faca4..e361852d5 100644 --- a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ContactServiceTest.java +++ b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ContactServiceTest.java @@ -12,14 +12,22 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.profile.Contact; +import ru.clearing.platform.dictionary.ContactTypeDictionary; +import ru.spcex.clearing.company.config.BeanConfiguration; import ru.spcex.clearing.company.config.HazelcastServiceTestConfiguration; import ru.spcex.clearing.company.config.KafkaConfigTest; +import ru.spcex.clearing.company.config.validation.ContactValidationConfig; +import ru.spcex.clearing.company.config.validation.ValidationConfig; import ru.spcex.clearing.company.utils.MatcherFactory; 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.ContactNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest; +import ru.spcex.platform.enumeration.ContactTypes; +import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; @@ -30,6 +38,9 @@ import static ru.spcex.clearing.company.utils.TestUtils.*; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { + BeanConfiguration.class, + ValidationConfig.class, + ContactValidationConfig.class, ContactService.class, KafkaConfigTest.class, HazelcastServiceTestConfiguration.class}) @@ -38,6 +49,7 @@ class ContactServiceTest { public static final MatcherFactory.Matcher CONTACT_MATCHER = usingIgnoringFieldsComparator(); private static final int PARTITION = 0; private static final String TOPIC_CONTACT_UPDATE = Consts.DESTINATION_CONTACT_UPDATE; + private static final String TOPIC_CONTACT_NEW = Consts.DESTINATION_CONTACT_NEW; private static final Long ID = 0L; @Autowired @@ -53,10 +65,50 @@ class ContactServiceTest { @SpyBean private MockProducer mockProducer; + private Company TEST_COMPANY; + private Long COMPANY_ID; + @PostConstruct private void init() { hazelcastServiceTest.waitAvailable(); contactImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Contact, Contact.class); + + Imdg companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class); + TEST_COMPANY = new Company(); + TEST_COMPANY.setWorkflowStatus(WorkflowStatus.Active.getKey()); + COMPANY_ID = companyImdg.insert(TEST_COMPANY); + + ContactTypeDictionary contactTypeDictionary = new ContactTypeDictionary(); + contactTypeDictionary.setCode(ContactTypes.adrs.getKey()); + contactTypeDictionary.setName("name"); + Imdg contactTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ContactTypeDictionary, ContactTypeDictionary.class + ); + contactTypeDictionaryImdg.insert(contactTypeDictionary); + } + @Test + void contactNew() throws InterruptedException { + //ARRANGE + ContactNewRequest contactNewRequest = new ContactNewRequest(); + contactNewRequest.setCompanyId(COMPANY_ID); + contactNewRequest.setContactType(ContactTypes.adrs.getKey()); + contactNewRequest.setContactValue("value"); + + Contact predictableContact = new Contact(); + predictableContact.setCompanyId(COMPANY_ID); + predictableContact.setContactType(ContactTypes.adrs.getKey()); + predictableContact.setContactValue("value"); + + //ACT + String jsonString = getJsonStringForNew(contactNewRequest, ID); + addRecordToKafka((MockConsumer) contactService.getConsumer(), TOPIC_CONTACT_NEW, PARTITION, 0, jsonString); + + //ASSERT + waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord); + + Contact resultNew = contactImdg.getAllValues().iterator().next(); + predictableContact.setId(resultNew.getId()); + CONTACT_MATCHER.assertMatch(resultNew, predictableContact); } /** @@ -65,39 +117,38 @@ class ContactServiceTest { * Входной запрос {@link ContactUpdateRequest}:
* {@link ContactUpdateRequest#id} - Идентификатор записи
* {@link ContactUpdateRequest#companyId} - Идентификатор записи
- * {@link ContactUpdateRequest#contactType} - 1234
+ * {@link ContactUpdateRequest#contactType} - ADDR
* {@link ContactUpdateRequest#contactValue} - new ContactValue
*/ @Test void contactUpdate() throws InterruptedException { //ARRANGE + Long existContactID; Contact existsContact = new Contact(); - existsContact.setId(ID); - existsContact.setCompanyId(ID); - existsContact.setContactType("0000"); + existsContact.setCompanyId(COMPANY_ID); + existsContact.setContactType(ContactTypes.adrs.getKey()); existsContact.setContactValue("exists ContactValue"); - contactImdg.insert(existsContact); + existContactID = contactImdg.insert(existsContact); ContactUpdateRequest contactUpdateRequest = new ContactUpdateRequest(); - contactUpdateRequest.setId(ID); - contactUpdateRequest.setCompanyId(1L); - contactUpdateRequest.setContactType("1234"); + contactUpdateRequest.setId(existContactID); + contactUpdateRequest.setContactType(ContactTypes.adrs.getKey()); contactUpdateRequest.setContactValue("new ContactValue"); Contact predictableContact = new Contact(); - predictableContact.setId(ID); - predictableContact.setCompanyId(ID); - predictableContact.setContactType("0000"); + predictableContact.setId(existContactID); + predictableContact.setCompanyId(COMPANY_ID); + predictableContact.setContactType(ContactTypes.adrs.getKey()); predictableContact.setContactValue("new ContactValue"); //ACT - String jsonString = getJsonStringForUPDATE(contactUpdateRequest, ID); + String jsonString = getJsonStringForUPDATE(contactUpdateRequest, existContactID); addRecordToKafka((MockConsumer) contactService.getConsumer(), TOPIC_CONTACT_UPDATE, PARTITION, 0, jsonString); //ASSERT - waitingWhenAddedRecordAndCheckIt(ID, mockProducer, producerRecord); + waitingWhenAddedRecordAndCheckIt(existContactID, mockProducer, producerRecord); - Contact resultUpdating = contactImdg.getSingleObjectByID(ID); + Contact resultUpdating = contactImdg.getSingleObjectByID(existContactID); CONTACT_MATCHER.assertMatch(resultUpdating, predictableContact); } } \ No newline at end of file diff --git a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ProfileDocumentServiceTest.java b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ProfileDocumentServiceTest.java index c2ed53986..298d1483d 100644 --- a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ProfileDocumentServiceTest.java +++ b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ProfileDocumentServiceTest.java @@ -68,7 +68,7 @@ class ProfileDocumentServiceTest { @SpyBean private MockProducer mockProducer; - private final long COMPANY_ID = 777L; + private long COMPANY_ID; private Company TEST_COMPANY; private DocumentTypes TEST_DOCUMENT_TYPE = DocumentTypes.cio; @@ -86,9 +86,8 @@ class ProfileDocumentServiceTest { this.companyMap = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class); TEST_COMPANY = new Company(); - TEST_COMPANY.setId(COMPANY_ID); TEST_COMPANY.setWorkflowStatus(WorkflowStatus.Active.getKey()); - companyMap.insert(TEST_COMPANY); + COMPANY_ID = companyMap.insert(TEST_COMPANY); Imdg documentTypeDictionaryImdg = hazelcastServiceTest.getImdg( IMDGDistributedNames.Map_DocumentTypeDictionary,