diff --git a/fineract-avro-schemas/src/main/avro/document/v1/DocumentDataV1.avsc b/fineract-avro-schemas/src/main/avro/document/v1/DocumentDataV1.avsc new file mode 100644 index 000000000..6c0987065 --- /dev/null +++ b/fineract-avro-schemas/src/main/avro/document/v1/DocumentDataV1.avsc @@ -0,0 +1,80 @@ +{ + "name": "DocumentDataV1", + "namespace": "org.apache.fineract.avro.document.v1", + "doc": "Metadata emitted by DocumentCreatedBusinessEvent when a file is stored in Fineract.", + "type": "record", + "fields": [ + { + "default": null, + "name": "id", + "type": [ + "null", + "long" + ] + }, + { + "default": null, + "name": "parentEntityType", + "type": [ + "null", + "string" + ] + }, + { + "default": null, + "name": "parentEntityId", + "type": [ + "null", + "long" + ] + }, + { + "default": null, + "name": "name", + "type": [ + "null", + "string" + ] + }, + { + "default": null, + "name": "fileName", + "type": [ + "null", + "string" + ] + }, + { + "default": null, + "name": "size", + "type": [ + "null", + "long" + ] + }, + { + "default": null, + "name": "type", + "type": [ + "null", + "string" + ] + }, + { + "default": null, + "name": "description", + "type": [ + "null", + "string" + ] + }, + { + "default": null, + "name": "storageType", + "type": [ + "null", + "int" + ] + } + ] +} diff --git a/fineract-document/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java b/fineract-document/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java index 869de535e..e87575d65 100644 --- a/fineract-document/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-document/src/main/java/org/apache/fineract/infrastructure/documentmanagement/service/DocumentWritePlatformServiceJpaRepositoryImpl.java @@ -31,6 +31,9 @@ import org.apache.fineract.infrastructure.documentmanagement.domain.StorageType; import org.apache.fineract.infrastructure.documentmanagement.exception.ContentManagementException; import org.apache.fineract.infrastructure.documentmanagement.exception.DocumentNotFoundException; import org.apache.fineract.infrastructure.documentmanagement.exception.InvalidEntityTypeForDocumentManagementException; +import org.apache.fineract.infrastructure.event.business.domain.document.DocumentCreatedBusinessEvent; +import org.apache.fineract.infrastructure.event.business.domain.document.DocumentDeletedBusinessEvent; +import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,13 +51,15 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr private final PlatformSecurityContext context; private final DocumentRepository documentRepository; private final ContentRepositoryFactory contentRepositoryFactory; + private final BusinessEventNotifierService businessEventNotifierService; @Autowired public DocumentWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final DocumentRepository documentRepository, - final ContentRepositoryFactory documentStoreFactory) { + final ContentRepositoryFactory documentStoreFactory, BusinessEventNotifierService businessEventNotifierService) { this.context = context; this.documentRepository = documentRepository; this.contentRepositoryFactory = documentStoreFactory; + this.businessEventNotifierService = businessEventNotifierService; } @Transactional @@ -78,6 +83,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr documentCommand.getDescription(), fileLocation, contentRepository.getStorageType()); this.documentRepository.saveAndFlush(document); + businessEventNotifierService.notifyPostBusinessEvent(new DocumentCreatedBusinessEvent(document)); return document.getId(); } catch (final JpaSystemException | DataIntegrityViolationException dve) { @@ -158,6 +164,7 @@ public class DocumentWritePlatformServiceJpaRepositoryImpl implements DocumentWr final ContentRepository contentRepository = this.contentRepositoryFactory.getRepository(document.storageType()); contentRepository.deleteFile(document.getLocation()); + businessEventNotifierService.notifyPostBusinessEvent(new DocumentDeletedBusinessEvent(document)); return CommandProcessingResult.resourceResult(document.getId()); } diff --git a/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentBusinessEvent.java b/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentBusinessEvent.java new file mode 100644 index 000000000..dc0aca7d4 --- /dev/null +++ b/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentBusinessEvent.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.business.domain.document; + +import org.apache.fineract.infrastructure.documentmanagement.domain.Document; +import org.apache.fineract.infrastructure.event.business.domain.AbstractBusinessEvent; + +public abstract class DocumentBusinessEvent extends AbstractBusinessEvent { + + private static final String CATEGORY = "Document"; + + protected DocumentBusinessEvent(Document value) { + super(value); + } + + @Override + public String getCategory() { + return CATEGORY; // e.g. will appear as “Document” + } + + @Override + public Long getAggregateRootId() { + return get().getId(); // primary-key of the uploaded doc + } +} diff --git a/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentCreatedBusinessEvent.java b/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentCreatedBusinessEvent.java new file mode 100644 index 000000000..b323857e7 --- /dev/null +++ b/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentCreatedBusinessEvent.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.business.domain.document; + +import org.apache.fineract.infrastructure.documentmanagement.domain.Document; + +public class DocumentCreatedBusinessEvent extends DocumentBusinessEvent { + + private static final String TYPE = "DocumentCreatedBusinessEvent"; + + public DocumentCreatedBusinessEvent(Document value) { + super(value); + } + + @Override + public String getType() { + return TYPE; + } +} diff --git a/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentDeletedBusinessEvent.java b/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentDeletedBusinessEvent.java new file mode 100644 index 000000000..14184b59e --- /dev/null +++ b/fineract-document/src/main/java/org/apache/fineract/infrastructure/event/business/domain/document/DocumentDeletedBusinessEvent.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.business.domain.document; + +import org.apache.fineract.infrastructure.documentmanagement.domain.Document; + +public class DocumentDeletedBusinessEvent extends DocumentBusinessEvent { + + private static final String TYPE = "DocumentDeletedBusinessEvent"; + + public DocumentDeletedBusinessEvent(Document value) { + super(value); + } + + @Override + public String getType() { + return TYPE; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/document/DocumentDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/document/DocumentDataMapper.java new file mode 100644 index 000000000..04a8093bd --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/document/DocumentDataMapper.java @@ -0,0 +1,30 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.external.service.serialization.mapper.document; + +import org.apache.fineract.avro.document.v1.DocumentDataV1; +import org.apache.fineract.infrastructure.documentmanagement.data.DocumentData; +import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroMapperConfig; +import org.mapstruct.Mapper; + +@Mapper(config = AvroMapperConfig.class) +public interface DocumentDataMapper { + + DocumentDataV1 map(DocumentData source); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/document/DocumentBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/document/DocumentBusinessEventSerializer.java new file mode 100644 index 000000000..a2b68d1cf --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/document/DocumentBusinessEventSerializer.java @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.infrastructure.event.external.service.serialization.serializer.document; + +import lombok.RequiredArgsConstructor; +import org.apache.avro.generic.GenericContainer; +import org.apache.fineract.avro.document.v1.DocumentDataV1; +import org.apache.fineract.avro.generator.ByteBufferSerializable; +import org.apache.fineract.infrastructure.documentmanagement.data.DocumentData; +import org.apache.fineract.infrastructure.documentmanagement.domain.Document; +import org.apache.fineract.infrastructure.documentmanagement.service.DocumentReadPlatformService; +import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent; +import org.apache.fineract.infrastructure.event.business.domain.document.DocumentBusinessEvent; +import org.apache.fineract.infrastructure.event.business.domain.document.DocumentCreatedBusinessEvent; +import org.apache.fineract.infrastructure.event.business.domain.document.DocumentDeletedBusinessEvent; +import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.document.DocumentDataMapper; +import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DocumentBusinessEventSerializer implements BusinessEventSerializer { + + private static final Logger log = LoggerFactory.getLogger(DocumentBusinessEventSerializer.class); + private final DocumentReadPlatformService service; + private final DocumentDataMapper mapper; + + @Override + public boolean canSerialize(BusinessEvent event) { + return event instanceof DocumentCreatedBusinessEvent || event instanceof DocumentDeletedBusinessEvent; + } + + @Override + public ByteBufferSerializable toAvroDTO(BusinessEvent rawEvent) { + + DocumentBusinessEvent event = (DocumentBusinessEvent) rawEvent; + Document entity = event.get(); // domain entity + + DocumentData dto = null; + if (rawEvent instanceof DocumentCreatedBusinessEvent) { + try { + dto = service.retrieveDocument(entity.getParentEntityType(), entity.getParentEntityId(), entity.getId()); + } catch (Exception ex) { + // log at DEBUG and fall back to entity mapping + log.debug("DocumentData not found, falling back to entity", ex); + } + } + + // If we have the DTO, let MapStruct do the work. Otherwise, build from the entity + + DocumentDataV1 avro; + if (dto != null) { + avro = mapper.map(dto); + } else { + avro = DocumentDataV1.newBuilder().setId(entity.getId()).setParentEntityType(entity.getParentEntityType()) + .setParentEntityId(entity.getParentEntityId()).setName(entity.getName()).setFileName(entity.getFileName()) + .setSize(entity.getSize()).setType(entity.getType()).setDescription(entity.getDescription()).build(); + } + + Integer storageTypeCode = (dto != null && dto.getStorageType() != null && dto.storageType() != null) ? dto.getStorageType() + : (entity.storageType() != null ? entity.storageType().getValue() : null); + avro.setStorageType(storageTypeCode); + + return avro; + } + + @Override + public Class getSupportedSchema() { + return DocumentDataV1.class; + } +} diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 50b68a01f..a66325bad 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -202,4 +202,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0184_add_document_event_configuration.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0184_add_document_event_configuration.xml new file mode 100644 index 000000000..096b40328 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0184_add_document_event_configuration.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventConfigurationValidationServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventConfigurationValidationServiceTest.java index 5d5e47edd..6e56c097f 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventConfigurationValidationServiceTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventConfigurationValidationServiceTest.java @@ -67,20 +67,20 @@ public class ExternalEventConfigurationValidationServiceTest { // given List configurations = Arrays.asList("CentersCreateBusinessEvent", "ClientActivateBusinessEvent", - "ClientCreateBusinessEvent", "ClientRejectBusinessEvent", "FixedDepositAccountCreateBusinessEvent", - "GroupsCreateBusinessEvent", "LoanAcceptTransferBusinessEvent", "LoanAddChargeBusinessEvent", - "LoanAdjustTransactionBusinessEvent", "LoanApplyOverdueChargeBusinessEvent", "LoanApprovedBusinessEvent", - "LoanBalanceChangedBusinessEvent", "LoanChargebackTransactionBusinessEvent", "LoanChargePaymentPostBusinessEvent", - "LoanChargePaymentPreBusinessEvent", "LoanChargeRefundBusinessEvent", "LoanCloseAsRescheduleBusinessEvent", - "LoanCloseBusinessEvent", "LoanCreatedBusinessEvent", "LoanCreditBalanceRefundPostBusinessEvent", - "LoanCreditBalanceRefundPreBusinessEvent", "LoanDeleteChargeBusinessEvent", "LoanDisbursalBusinessEvent", - "LoanDisbursalTransactionBusinessEvent", "LoanForeClosurePostBusinessEvent", "LoanForeClosurePreBusinessEvent", - "LoanInitiateTransferBusinessEvent", "LoanInterestRecalculationBusinessEvent", "LoanProductCreateBusinessEvent", - "LoanReassignOfficerBusinessEvent", "LoanRefundPostBusinessEvent", "LoanRefundPreBusinessEvent", - "LoanRejectedBusinessEvent", "LoanRejectTransferBusinessEvent", "LoanRemoveOfficerBusinessEvent", - "LoanRepaymentDueBusinessEvent", "LoanRepaymentOverdueBusinessEvent", "LoanRescheduledDueCalendarChangeBusinessEvent", - "LoanRescheduledDueHolidayBusinessEvent", "LoanScheduleVariationsAddedBusinessEvent", - "LoanScheduleVariationsDeletedBusinessEvent", "LoanStatusChangedBusinessEvent", + "ClientCreateBusinessEvent", "ClientRejectBusinessEvent", "DocumentCreatedBusinessEvent", "DocumentDeletedBusinessEvent", + "FixedDepositAccountCreateBusinessEvent", "GroupsCreateBusinessEvent", "LoanAcceptTransferBusinessEvent", + "LoanAddChargeBusinessEvent", "LoanAdjustTransactionBusinessEvent", "LoanApplyOverdueChargeBusinessEvent", + "LoanApprovedBusinessEvent", "LoanBalanceChangedBusinessEvent", "LoanChargebackTransactionBusinessEvent", + "LoanChargePaymentPostBusinessEvent", "LoanChargePaymentPreBusinessEvent", "LoanChargeRefundBusinessEvent", + "LoanCloseAsRescheduleBusinessEvent", "LoanCloseBusinessEvent", "LoanCreatedBusinessEvent", + "LoanCreditBalanceRefundPostBusinessEvent", "LoanCreditBalanceRefundPreBusinessEvent", "LoanDeleteChargeBusinessEvent", + "LoanDisbursalBusinessEvent", "LoanDisbursalTransactionBusinessEvent", "LoanForeClosurePostBusinessEvent", + "LoanForeClosurePreBusinessEvent", "LoanInitiateTransferBusinessEvent", "LoanInterestRecalculationBusinessEvent", + "LoanProductCreateBusinessEvent", "LoanReassignOfficerBusinessEvent", "LoanRefundPostBusinessEvent", + "LoanRefundPreBusinessEvent", "LoanRejectedBusinessEvent", "LoanRejectTransferBusinessEvent", + "LoanRemoveOfficerBusinessEvent", "LoanRepaymentDueBusinessEvent", "LoanRepaymentOverdueBusinessEvent", + "LoanRescheduledDueCalendarChangeBusinessEvent", "LoanRescheduledDueHolidayBusinessEvent", + "LoanScheduleVariationsAddedBusinessEvent", "LoanScheduleVariationsDeletedBusinessEvent", "LoanStatusChangedBusinessEvent", "LoanTransactionGoodwillCreditPostBusinessEvent", "LoanTransactionGoodwillCreditPreBusinessEvent", "LoanTransactionMakeRepaymentPostBusinessEvent", "LoanTransactionMakeRepaymentPreBusinessEvent", "LoanTransactionMerchantIssuedRefundPostBusinessEvent", "LoanTransactionMerchantIssuedRefundPreBusinessEvent", @@ -157,12 +157,12 @@ public class ExternalEventConfigurationValidationServiceTest { // given List configurationWithMissingCentersCreateBusinessEvent = Arrays.asList("MockBusinessEvent", "MockBusinessEvent", - "ClientActivateBusinessEvent", "ClientCreateBusinessEvent", "ClientRejectBusinessEvent", - "FixedDepositAccountCreateBusinessEvent", "GroupsCreateBusinessEvent", "LoanAcceptTransferBusinessEvent", - "LoanAddChargeBusinessEvent", "LoanAdjustTransactionBusinessEvent", "LoanApplyOverdueChargeBusinessEvent", - "LoanApprovedBusinessEvent", "LoanBalanceChangedBusinessEvent", "LoanChargebackTransactionBusinessEvent", - "LoanChargePaymentPostBusinessEvent", "LoanChargePaymentPreBusinessEvent", "LoanChargeRefundBusinessEvent", - "LoanCloseAsRescheduleBusinessEvent", "LoanCloseBusinessEvent", "LoanCreatedBusinessEvent", + "ClientActivateBusinessEvent", "ClientCreateBusinessEvent", "ClientRejectBusinessEvent", "DocumentCreatedBusinessEvent", + "DocumentDeletedBusinessEvent", "FixedDepositAccountCreateBusinessEvent", "GroupsCreateBusinessEvent", + "LoanAcceptTransferBusinessEvent", "LoanAddChargeBusinessEvent", "LoanAdjustTransactionBusinessEvent", + "LoanApplyOverdueChargeBusinessEvent", "LoanApprovedBusinessEvent", "LoanBalanceChangedBusinessEvent", + "LoanChargebackTransactionBusinessEvent", "LoanChargePaymentPostBusinessEvent", "LoanChargePaymentPreBusinessEvent", + "LoanChargeRefundBusinessEvent", "LoanCloseAsRescheduleBusinessEvent", "LoanCloseBusinessEvent", "LoanCreatedBusinessEvent", "LoanCreditBalanceRefundPostBusinessEvent", "LoanCreditBalanceRefundPreBusinessEvent", "LoanDeleteChargeBusinessEvent", "LoanDisbursalBusinessEvent", "LoanDisbursalTransactionBusinessEvent", "LoanForeClosurePostBusinessEvent", "LoanForeClosurePreBusinessEvent", "LoanInitiateTransferBusinessEvent", "LoanInterestRecalculationBusinessEvent", diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/document/DocumentBusinessEventSerializerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/document/DocumentBusinessEventSerializerTest.java new file mode 100644 index 000000000..8bf5bf31d --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/document/DocumentBusinessEventSerializerTest.java @@ -0,0 +1,100 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.infrastructure.event.external.service.serialization.serializer.document; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.fineract.avro.document.v1.DocumentDataV1; +import org.apache.fineract.avro.generator.ByteBufferSerializable; +import org.apache.fineract.infrastructure.documentmanagement.data.DocumentData; +import org.apache.fineract.infrastructure.documentmanagement.domain.Document; +import org.apache.fineract.infrastructure.documentmanagement.domain.StorageType; +import org.apache.fineract.infrastructure.documentmanagement.service.DocumentReadPlatformService; +import org.apache.fineract.infrastructure.event.business.domain.document.DocumentCreatedBusinessEvent; +import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.document.DocumentDataMapper; +import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@MockitoSettings(strictness = Strictness.LENIENT) +@ExtendWith(MockitoExtension.class) +class DocumentBusinessEventSerializerTest { + + @Mock + private DocumentReadPlatformService readService; + @Mock + private DocumentDataMapper mapper; + + private BusinessEventSerializer serializer; + + @BeforeEach + void setUp() { + serializer = new DocumentBusinessEventSerializer(readService, mapper); + } + + @Test + void documentStorageTypeIsPatchedIntoAvro() { + + long docId = 42L; + String parentEntity = "loans"; + long parentEntityId = 979L; + String name = "test_document"; + String fileName = "test_document.pdf"; + String fileType = "application/pdf"; + String description = "Test document description"; + Integer storageTypeInt = StorageType.FILE_SYSTEM.getValue(); + + Document document = mock(Document.class); + when(document.getId()).thenReturn(docId); + when(document.getParentEntityType()).thenReturn(parentEntity); + when(document.getParentEntityId()).thenReturn(parentEntityId); + when(document.getName()).thenReturn(name); + when(document.getFileName()).thenReturn(fileName); + when(document.getType()).thenReturn(fileType); + when(document.getDescription()).thenReturn(description); + when(document.storageType()).thenReturn(StorageType.fromInt(storageTypeInt)); + + DocumentCreatedBusinessEvent event = new DocumentCreatedBusinessEvent(document); + + DocumentData dtoFromReadService = mock(DocumentData.class); + when(readService.retrieveDocument(parentEntity, parentEntityId, docId)).thenReturn(dtoFromReadService); + + DocumentDataV1 avroFromMapper = DocumentDataV1.newBuilder().setId(docId).setParentEntityType(parentEntity) + .setParentEntityId(parentEntityId).setName(name).setFileName(fileName).setType(fileType).setDescription(description) + .build(); + when(mapper.map(any(DocumentData.class))).thenReturn(avroFromMapper); + + ByteBufferSerializable serialised = serializer.toAvroDTO(event); + assertNotNull(serialised); + + DocumentDataV1 avro = (DocumentDataV1) serialised; + + assertEquals(storageTypeInt, avro.getStorageType(), "Serializer must patch storageType taken from the domain entity"); + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalEventConfigurationHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalEventConfigurationHelper.java index acbadd414..5a993bbf7 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalEventConfigurationHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/ExternalEventConfigurationHelper.java @@ -73,6 +73,16 @@ public class ExternalEventConfigurationHelper { clientRejectBusinessEvent.put("enabled", false); defaults.add(clientRejectBusinessEvent); + Map documentCreatedBusinessEvent = new HashMap<>(); + documentCreatedBusinessEvent.put("type", "DocumentCreatedBusinessEvent"); + documentCreatedBusinessEvent.put("enabled", false); + defaults.add(documentCreatedBusinessEvent); + + Map documentDeletedBusinessEvent = new HashMap<>(); + documentDeletedBusinessEvent.put("type", "DocumentDeletedBusinessEvent"); + documentDeletedBusinessEvent.put("enabled", false); + defaults.add(documentDeletedBusinessEvent); + Map fixedDepositAccountCreateBusinessEvent = new HashMap<>(); fixedDepositAccountCreateBusinessEvent.put("type", "FixedDepositAccountCreateBusinessEvent"); fixedDepositAccountCreateBusinessEvent.put("enabled", false);