This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 159eff0ad4 FINERACT-2309: Emit external events on document upload and
delete
159eff0ad4 is described below
commit 159eff0ad4ff90d275a8d5c68a2d91bb7f94a2a3
Author: Abhinav Cillanki <[email protected]>
AuthorDate: Sat Jun 14 13:04:12 2025 +0530
FINERACT-2309: Emit external events on document upload and delete
---
.../src/main/avro/document/v1/DocumentDataV1.avsc | 80 +++++++++++++++++
...umentWritePlatformServiceJpaRepositoryImpl.java | 9 +-
.../domain/document/DocumentBusinessEvent.java | 41 +++++++++
.../document/DocumentCreatedBusinessEvent.java | 35 ++++++++
.../document/DocumentDeletedBusinessEvent.java | 35 ++++++++
.../mapper/document/DocumentDataMapper.java | 30 +++++++
.../document/DocumentBusinessEventSerializer.java | 89 ++++++++++++++++++
.../db/changelog/tenant/changelog-tenant.xml | 1 +
.../0184_add_document_event_configuration.xml | 35 ++++++++
...nalEventConfigurationValidationServiceTest.java | 40 ++++-----
.../DocumentBusinessEventSerializerTest.java | 100 +++++++++++++++++++++
.../common/ExternalEventConfigurationHelper.java | 10 +++
12 files changed, 484 insertions(+), 21 deletions(-)
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 0000000000..6c09870653
--- /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 869de535e3..e87575d658 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 0000000000..dc0aca7d43
--- /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<Document> {
+
+ 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 0000000000..b323857e7a
--- /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 0000000000..14184b59e2
--- /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 0000000000..04a8093bdc
--- /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 0000000000..a2b68d1cfb
--- /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 <T> boolean canSerialize(BusinessEvent<T> event) {
+ return event instanceof DocumentCreatedBusinessEvent || event
instanceof DocumentDeletedBusinessEvent;
+ }
+
+ @Override
+ public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> 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<? extends GenericContainer> 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 50b68a01f9..a66325bad0 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 @@
<include
file="parts/0181_add_capitalized_income_amortization_adjustment_transaction.xml"
relativeToChangelogFile="true" />
<include
file="parts/0182_transaction_summary_with_asset_owner_report_fix_charge_reason_and_add_buyback_intermediate.xml"
relativeToChangelogFile="true" />
<include
file="parts/0183_add_LoanCapitalizedIncomeTransactionCreatedBusinessEvent.xml"
relativeToChangelogFile="true" />
+ <include file="parts/0184_add_document_event_configuration.xml"
relativeToChangelogFile="true" />
</databaseChangeLog>
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 0000000000..096b403282
--- /dev/null
+++
b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0184_add_document_event_configuration.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
+ <changeSet id="1" author="fineract">
+ <insert tableName="m_external_event_configuration">
+ <column name="type" value="DocumentCreatedBusinessEvent"/>
+ <column name="enabled" valueBoolean="false"/>
+ </insert>
+ <insert tableName="m_external_event_configuration">
+ <column name="type" value="DocumentDeletedBusinessEvent"/>
+ <column name="enabled" valueBoolean="false"/>
+ </insert>
+ </changeSet>
+</databaseChangeLog>
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 5d5e47edde..6e56c097f1 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<String> 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<String> 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 0000000000..8bf5bf31d6
--- /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 acbadd414d..5a993bbf7f 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<String, Object> documentCreatedBusinessEvent = new HashMap<>();
+ documentCreatedBusinessEvent.put("type",
"DocumentCreatedBusinessEvent");
+ documentCreatedBusinessEvent.put("enabled", false);
+ defaults.add(documentCreatedBusinessEvent);
+
+ Map<String, Object> documentDeletedBusinessEvent = new HashMap<>();
+ documentDeletedBusinessEvent.put("type",
"DocumentDeletedBusinessEvent");
+ documentDeletedBusinessEvent.put("enabled", false);
+ defaults.add(documentDeletedBusinessEvent);
+
Map<String, Object> fixedDepositAccountCreateBusinessEvent = new
HashMap<>();
fixedDepositAccountCreateBusinessEvent.put("type",
"FixedDepositAccountCreateBusinessEvent");
fixedDepositAccountCreateBusinessEvent.put("enabled", false);