You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2023/06/06 13:20:48 UTC

[fineract] branch develop updated: FINERACT-1926: Fineract Asset Externalization events - [x] Change events - [x] Create data enricher - [x] Core changes - [x] Remove AbstractBusinessEventSerializer - [x] BusinessEventSerializer.toAvroDto added and change the event serializers

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 99470c0cf FINERACT-1926: Fineract Asset Externalization events - [x] Change events - [x] Create data enricher - [x] Core changes - [x] Remove AbstractBusinessEventSerializer - [x] BusinessEventSerializer.toAvroDto added and change the event serializers
99470c0cf is described below

commit 99470c0cf85177c02aff040a5399d9d6db8d287d
Author: Janos Haber <ja...@finesolution.hu>
AuthorDate: Fri May 26 09:24:02 2023 +0200

    FINERACT-1926: Fineract Asset Externalization events
    - [x] Change events
    - [x] Create data enricher
    - [x] Core changes
    - [x] Remove AbstractBusinessEventSerializer
    - [x] BusinessEventSerializer.toAvroDto added and change the event serializers
---
 .../src/main/avro/loan/v1/LoanAccountDataV1.avsc   | 24 ++++++++++
 .../src/main/avro/loan/v1/LoanChargeDataV1.avsc    |  8 ++++
 .../main/avro/loan/v1/LoanTransactionDataV1.avsc   |  8 ++++
 fineract-core/dependencies.gradle                  |  1 +
 .../infrastructure/core/service/DataEnricher.java  | 14 ++----
 .../core/service/DataEnricherProcessor.java        | 29 ++++++++----
 .../mapper/support/AvroDateTimeMapper.java         |  0
 fineract-investor/dependencies.gradle              |  4 ++
 .../api/ExternalAssetOwnersApiResource.java        |  2 +
 .../ExternalAssetOwnerTransferRepository.java      |  6 +++
 .../enricher/LoanAccountDataV1Enricher.java        | 55 ++++++++++++++++++++++
 .../enricher/LoanChargeDataV1Enricher.java         | 45 ++++++++++++++++++
 .../config/AbstractFineractModuleProperties.java}  | 17 +++----
 .../core/config/FineractProperties.java            | 15 ++++++
 .../external/service/ExternalEventService.java     |  8 +++-
 .../service/message/BulkMessageItemFactory.java    |  7 ++-
 .../mapper/loan/LoanAccountDataMapper.java         |  6 ++-
 .../mapper/loan/LoanChargeDataMapper.java          |  2 +
 .../mapper/loan/LoanTransactionDataMapper.java     |  1 +
 .../AbstractBusinessEventSerializer.java           | 44 -----------------
 .../serializer/BusinessEventSerializer.java        |  7 +--
 .../client/ClientBusinessEventSerializer.java      |  6 +--
 ...FixedDepositAccountBusinessEventSerializer.java |  6 +--
 .../group/GroupsBusinessEventSerializer.java       |  6 +--
 ...ccountsStayedLockedBusinessEventSerializer.java |  6 +--
 ...anAdjustTransactionBusinessEventSerializer.java |  6 +--
 .../loan/LoanBusinessEventSerializer.java          |  6 +--
 .../loan/LoanChargeBusinessEventSerializer.java    |  6 +--
 .../LoanChargeDeletedBusinessEventSerializer.java  |  6 +--
 .../loan/LoanChargeOffBusinessEventSerializer.java |  2 +-
 ...inquencyRangeChangeBusinessEventSerializer.java |  6 +--
 .../loan/LoanProductBusinessEventSerializer.java   |  6 +--
 .../loan/LoanRepaymentBusinessEventSerializer.java |  6 +--
 .../LoanTransactionBusinessEventSerializer.java    |  6 +--
 ...rringDepositAccountBusinessEventSerializer.java |  6 +--
 .../SavingsAccountBusinessEventSerializer.java     |  6 +--
 ...sAccountTransactionBusinessEventSerializer.java |  6 +--
 .../share/ShareAccountBusinessEventSerializer.java |  6 +--
 ...ductDividentsCreateBusinessEventSerializer.java |  6 +--
 .../src/main/resources/application.properties      |  2 +
 .../external/service/ExternalEventServiceTest.java | 32 ++++++++++---
 .../LoanRepaymentBusinessEventSerializerTest.java  |  1 -
 42 files changed, 304 insertions(+), 138 deletions(-)

diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc
index 6365b974c..c56a9fc76 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc
@@ -27,6 +27,30 @@
                 "string"
             ]
         },
+        {
+            "default": null,
+            "name": "externalOwnerId",
+            "type": [
+                "null",
+                "string"
+            ]
+        },
+        {
+            "default": null,
+            "name": "settlementDate",
+            "type": [
+                "null",
+                "string"
+            ]
+        },
+        {
+            "default": null,
+            "name": "purchasePriceRatio",
+            "type": [
+                "null",
+                "string"
+            ]
+        },
         {
             "default": null,
             "name": "status",
diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanChargeDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanChargeDataV1.avsc
index 4c2143f6f..0987d32a5 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanChargeDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanChargeDataV1.avsc
@@ -241,6 +241,14 @@
                 "string"
             ]
         },
+        {
+            "default": null,
+            "name": "externalOwnerId",
+            "type": [
+                "null",
+                "string"
+            ]
+        },
         {
             "default": null,
             "name": "submittedOnDate",
diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanTransactionDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanTransactionDataV1.avsc
index fd8262f9b..9ee340aa3 100644
--- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanTransactionDataV1.avsc
+++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanTransactionDataV1.avsc
@@ -147,6 +147,14 @@
                 "string"
             ]
         },
+        {
+            "default": null,
+            "name": "externalOwnerId",
+            "type": [
+                "null",
+                "string"
+            ]
+        },
         {
             "default": null,
             "name": "transfer",
diff --git a/fineract-core/dependencies.gradle b/fineract-core/dependencies.gradle
index 456ae23be..6e95a3628 100644
--- a/fineract-core/dependencies.gradle
+++ b/fineract-core/dependencies.gradle
@@ -23,6 +23,7 @@ dependencies {
     // Note that we never use 'api', because Fineract at least currently is a simple monolithic application ("WAR"), not a library.
     // We also (normally should have) no need to ever use 'compileOnly'.
 
+
     // implementation dependencies are directly used (compiled against) in src/main (and src/test)
     //
     implementation(
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DataEnricher.java
similarity index 62%
copy from fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
copy to fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DataEnricher.java
index ddb2ce9f6..9a373c0ae 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
+++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DataEnricher.java
@@ -16,17 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.infrastructure.event.external.service.serialization.serializer;
+package org.apache.fineract.infrastructure.core.service;
 
-import java.io.IOException;
-import org.apache.avro.generic.GenericContainer;
-import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
+public interface DataEnricher<T> {
 
-public interface BusinessEventSerializer {
+    boolean isDataTypeSupported(Class<T> dataType);
 
-    <T> boolean canSerialize(BusinessEvent<T> event);
-
-    <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException;
-
-    Class<? extends GenericContainer> getSupportedSchema();
+    void enrich(T data);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DataEnricherProcessor.java
similarity index 51%
copy from fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
copy to fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DataEnricherProcessor.java
index ddb2ce9f6..8022eef8f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
+++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DataEnricherProcessor.java
@@ -16,17 +16,30 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.infrastructure.event.external.service.serialization.serializer;
+package org.apache.fineract.infrastructure.core.service;
 
-import java.io.IOException;
-import org.apache.avro.generic.GenericContainer;
-import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
 
-public interface BusinessEventSerializer {
+@Component
+public class DataEnricherProcessor {
 
-    <T> boolean canSerialize(BusinessEvent<T> event);
+    private final List<DataEnricher<?>> enhancers;
 
-    <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException;
+    @Autowired
+    public DataEnricherProcessor(Optional<List<DataEnricher<?>>> enhancers) {
+        this.enhancers = enhancers.orElse(new ArrayList<>());
+    }
 
-    Class<? extends GenericContainer> getSupportedSchema();
+    public <T> T enrich(T source) {
+        for (DataEnricher enhancer : enhancers) {
+            if (enhancer.isDataTypeSupported(source.getClass())) {
+                enhancer.enrich(source);
+            }
+        }
+        return source;
+    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroDateTimeMapper.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroDateTimeMapper.java
similarity index 100%
rename from fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroDateTimeMapper.java
rename to fineract-core/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/support/AvroDateTimeMapper.java
diff --git a/fineract-investor/dependencies.gradle b/fineract-investor/dependencies.gradle
index e2eb8a6c3..26b040d9f 100644
--- a/fineract-investor/dependencies.gradle
+++ b/fineract-investor/dependencies.gradle
@@ -26,6 +26,10 @@ dependencies {
     //
     implementation(project(path: ':fineract-core'))
     implementation(project(path: ':fineract-loan'))
+    implementation('org.apache.avro:avro')
+    implementation(
+            project(path: ':fineract-avro-schemas')
+            )
 
     implementation(
             'org.springframework.boot:spring-boot-starter-web',
diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
index e1ae283d5..a495433ef 100644
--- a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
+++ b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
@@ -50,6 +50,7 @@ import org.apache.fineract.investor.data.ExternalTransferData;
 import org.apache.fineract.investor.data.ExternalTransferResponseData;
 import org.apache.fineract.investor.service.ExternalAssetOwnersReadService;
 import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformServiceCommon;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Component;
 
@@ -57,6 +58,7 @@ import org.springframework.stereotype.Component;
 @Component
 @Tag(name = "External Asset Owners", description = "External Asset Owners")
 @RequiredArgsConstructor
+@ConditionalOnProperty(value = "fineract.module.external-asset-owner.enabled", havingValue = "true")
 public class ExternalAssetOwnersApiResource {
 
     private final PlatformUserRightsContext platformUserRightsContext;
diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
index b4ad2e54c..a8dc5e8c4 100644
--- a/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
+++ b/fineract-investor/src/main/java/org/apache/fineract/investor/domain/ExternalAssetOwnerTransferRepository.java
@@ -41,6 +41,12 @@ public interface ExternalAssetOwnerTransferRepository
     @Query("select e from ExternalAssetOwnerTransfer e where e.loanId = :loanId and e.id = (select max(ex.id) from ExternalAssetOwnerTransfer ex where ex.loanId = :loanId)")
     Optional<ExternalAssetOwnerTransfer> findLatestByLoanId(@Param("loanId") Long loanId);
 
+    @Query("select m.ownerTransfer from ExternalAssetOwnerTransferLoanMapping m inner join fetch m.ownerTransfer o where m.loanId = :loanId")
+    Optional<ExternalAssetOwnerTransfer> findActiveByLoanId(@Param("loanId") Long loanId);
+
+    @Query("select m.ownerTransfer.owner from ExternalAssetOwnerTransferLoanMapping m where m.loanId = :loanId")
+    Optional<ExternalAssetOwner> findActiveOwnerByLoanId(@Param("loanId") Long loanId);
+
     @Query("SELECT t FROM ExternalAssetOwnerTransfer t WHERE t.loanId = :loanId AND t.effectiveDateTo > :effectiveDate")
     List<ExternalAssetOwnerTransfer> findEffectiveTransfers(@Param("loanId") Long loanId, @Param("effectiveDate") LocalDate effectiveDate);
 }
diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/enricher/LoanAccountDataV1Enricher.java b/fineract-investor/src/main/java/org/apache/fineract/investor/enricher/LoanAccountDataV1Enricher.java
new file mode 100644
index 000000000..ff3e0bb59
--- /dev/null
+++ b/fineract-investor/src/main/java/org/apache/fineract/investor/enricher/LoanAccountDataV1Enricher.java
@@ -0,0 +1,55 @@
+/**
+ * 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.investor.enricher;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
+import org.apache.fineract.infrastructure.core.domain.ExternalId;
+import org.apache.fineract.infrastructure.core.service.DataEnricher;
+import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper;
+import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.ExternalIdMapper;
+import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LoanAccountDataV1Enricher implements DataEnricher<LoanAccountDataV1> {
+
+    private final ExternalAssetOwnerTransferRepository externalAssetOwnerTransferRepository;
+    private final ExternalIdMapper externalIdMapper;
+    private final AvroDateTimeMapper avroDateTimeMapper;
+
+    @Override
+    public boolean isDataTypeSupported(Class<LoanAccountDataV1> dataType) {
+        return dataType.isAssignableFrom(LoanAccountDataV1.class);
+    }
+
+    @Override
+    public void enrich(LoanAccountDataV1 data) {
+        externalAssetOwnerTransferRepository.findActiveByLoanId(data.getId()).ifPresent(transfer -> {
+            ExternalId transferOwnerExternalId = transfer.getOwner().getExternalId();
+            data.setExternalOwnerId(externalIdMapper.mapExternalId(transferOwnerExternalId));
+            data.setSettlementDate(avroDateTimeMapper.mapLocalDate(transfer.getSettlementDate()));
+            data.setPurchasePriceRatio(transfer.getPurchasePriceRatio());
+            if (data.getCharges() != null) {
+                data.getCharges().forEach(charge -> charge.setExternalOwnerId(externalIdMapper.mapExternalId(transferOwnerExternalId)));
+            }
+        });
+    }
+}
diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/enricher/LoanChargeDataV1Enricher.java b/fineract-investor/src/main/java/org/apache/fineract/investor/enricher/LoanChargeDataV1Enricher.java
new file mode 100644
index 000000000..3413b0b47
--- /dev/null
+++ b/fineract-investor/src/main/java/org/apache/fineract/investor/enricher/LoanChargeDataV1Enricher.java
@@ -0,0 +1,45 @@
+/**
+ * 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.investor.enricher;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.avro.loan.v1.LoanChargeDataV1;
+import org.apache.fineract.infrastructure.core.service.DataEnricher;
+import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.ExternalIdMapper;
+import org.apache.fineract.investor.domain.ExternalAssetOwnerTransferRepository;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LoanChargeDataV1Enricher implements DataEnricher<LoanChargeDataV1> {
+
+    private final ExternalAssetOwnerTransferRepository externalAssetOwnerTransferRepository;
+    private final ExternalIdMapper externalIdMapper;
+
+    @Override
+    public boolean isDataTypeSupported(Class<LoanChargeDataV1> dataType) {
+        return dataType.isAssignableFrom(LoanChargeDataV1.class);
+    }
+
+    @Override
+    public void enrich(LoanChargeDataV1 data) {
+        externalAssetOwnerTransferRepository.findActiveOwnerByLoanId(data.getLoanId())
+                .ifPresent(owner -> data.setExternalOwnerId(externalIdMapper.mapExternalId(owner.getExternalId())));
+    }
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/AbstractFineractModuleProperties.java
similarity index 62%
copy from fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
copy to fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/AbstractFineractModuleProperties.java
index ddb2ce9f6..93329119f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/AbstractFineractModuleProperties.java
@@ -16,17 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.infrastructure.event.external.service.serialization.serializer;
+package org.apache.fineract.infrastructure.core.config;
 
-import java.io.IOException;
-import org.apache.avro.generic.GenericContainer;
-import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
+import lombok.Getter;
+import lombok.Setter;
 
-public interface BusinessEventSerializer {
+@Getter
+@Setter
+public class AbstractFineractModuleProperties {
 
-    <T> boolean canSerialize(BusinessEvent<T> event);
-
-    <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException;
-
-    Class<? extends GenericContainer> getSupportedSchema();
+    private boolean enabled;
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
index fecc18cba..2b0452665 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
@@ -65,6 +65,8 @@ public class FineractProperties {
 
     private FineractSamplingProperties sampling;
 
+    private FineractModulesProperties module;
+
     @Getter
     @Setter
     public static class FineractTenantProperties {
@@ -403,4 +405,17 @@ public class FineractProperties {
         private String sampledClasses;
         private int resetPeriodSec;
     }
+
+    @Getter
+    @Setter
+    public static class FineractModulesProperties {
+
+        private FineractExternalAssetOwnerModuleProperties externalAssetOwner;
+    }
+
+    @Getter
+    @Setter
+    public static class FineractExternalAssetOwnerModuleProperties extends AbstractFineractModuleProperties {
+
+    }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventService.java
index c67376102..0f1aa1715 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventService.java
@@ -21,12 +21,15 @@ package org.apache.fineract.infrastructure.event.external.service;
 import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.avro.BulkMessageItemV1;
 import org.apache.fineract.avro.BulkMessagePayloadV1;
+import org.apache.fineract.avro.generator.ByteBufferSerializable;
+import org.apache.fineract.infrastructure.core.service.DataEnricherProcessor;
 import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.external.repository.ExternalEventRepository;
@@ -50,6 +53,7 @@ public class ExternalEventService {
     private final BusinessEventSerializerFactory serializerFactory;
     private final ByteBufferConverter byteBufferConverter;
     private final BulkMessageItemFactory bulkMessageItemFactory;
+    private final DataEnricherProcessor dataEnricherProcessor;
 
     private EntityManager entityManager;
 
@@ -98,7 +102,9 @@ public class ExternalEventService {
         String idempotencyKey = idempotencyKeyGenerator.generate(event);
         BusinessEventSerializer serializer = serializerFactory.create(event);
         String schema = serializer.getSupportedSchema().getName();
-        byte[] data = serializer.serialize(event);
+        ByteBufferSerializable avroDto = dataEnricherProcessor.enrich(serializer.toAvroDTO(event));
+        ByteBuffer buffer = avroDto.toByteBuffer();
+        byte[] data = byteBufferConverter.convert(buffer);
         Long aggregateRootId = event.getAggregateRootId();
 
         return new ExternalEvent(eventType, eventCategory, schema, data, idempotencyKey, aggregateRootId);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/message/BulkMessageItemFactory.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/message/BulkMessageItemFactory.java
index a01baa18a..d94514f53 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/message/BulkMessageItemFactory.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/message/BulkMessageItemFactory.java
@@ -22,6 +22,8 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import lombok.RequiredArgsConstructor;
 import org.apache.fineract.avro.BulkMessageItemV1;
+import org.apache.fineract.avro.generator.ByteBufferSerializable;
+import org.apache.fineract.infrastructure.core.service.DataEnricherProcessor;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializerFactory;
@@ -34,10 +36,13 @@ public class BulkMessageItemFactory {
 
     private final BusinessEventSerializerFactory serializerFactory;
     private final ByteBufferConverter byteBufferConverter;
+    private final DataEnricherProcessor dataEnricherProcessor;
 
     public BulkMessageItemV1 createBulkMessageItem(int id, BusinessEvent<?> event) throws IOException {
         BusinessEventSerializer eventSerializer = serializerFactory.create(event);
-        byte[] serializedContent = eventSerializer.serialize(event);
+        ByteBufferSerializable avroDto = dataEnricherProcessor.enrich(eventSerializer.toAvroDTO(event));
+        ByteBuffer buffer = avroDto.toByteBuffer();
+        byte[] serializedContent = byteBufferConverter.convert(buffer);
         String type = event.getType();
         String category = "nocategory"; // TODO: switch this to the actual category when implemented
         String schema = eventSerializer.getSupportedSchema().getName();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java
index 1ada4f441..0db349fc8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanAccountDataMapper.java
@@ -24,7 +24,7 @@ import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 
-@Mapper(config = AvroMapperConfig.class, uses = { LoanTransactionDataMapper.class })
+@Mapper(config = AvroMapperConfig.class, uses = { LoanTransactionDataMapper.class, LoanChargeDataMapper.class })
 public interface LoanAccountDataMapper {
 
     // TODO: avoid prefix "is" in class attributes; I would recommend to fix this also in the Avro structures
@@ -32,5 +32,9 @@ public interface LoanAccountDataMapper {
     @Mapping(source = "floatingInterestRate", target = "isFloatingInterestRate")
     @Mapping(source = "topup", target = "isTopup")
     @Mapping(source = "interestRecalculationEnabled", target = "isInterestRecalculationEnabled")
+    @Mapping(target = "externalOwnerId", ignore = true)
+    @Mapping(target = "settlementDate", ignore = true)
+    @Mapping(target = "purchasePriceRatio", ignore = true)
     LoanAccountDataV1 map(LoanAccountData source);
+
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanChargeDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanChargeDataMapper.java
index 0a7ae2710..2e49121e7 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanChargeDataMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanChargeDataMapper.java
@@ -23,10 +23,12 @@ import org.apache.fineract.avro.loan.v1.LoanChargeDataV1;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroMapperConfig;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
 import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
 
 @Mapper(config = AvroMapperConfig.class)
 public interface LoanChargeDataMapper {
 
+    @Mapping(target = "externalOwnerId", ignore = true)
     LoanChargeDataV1 map(LoanChargeData source);
 
     LoanChargeDataRangeViewV1 mapRangeView(LoanChargeData source);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanTransactionDataMapper.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanTransactionDataMapper.java
index 671d091a6..412c96e04 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanTransactionDataMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/mapper/loan/LoanTransactionDataMapper.java
@@ -29,5 +29,6 @@ public interface LoanTransactionDataMapper {
 
     // unpaidCharges are calculated and set explicitly based on if needed (only for charge-off transaction yet)
     @Mapping(target = "unpaidCharges", ignore = true)
+    @Mapping(target = "externalOwnerId", ignore = true)
     LoanTransactionDataV1 map(LoanTransactionData source);
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/AbstractBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/AbstractBusinessEventSerializer.java
deleted file mode 100644
index bc2c9abab..000000000
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/AbstractBusinessEventSerializer.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import lombok.RequiredArgsConstructor;
-import lombok.Setter;
-import org.apache.fineract.avro.generator.ByteBufferSerializable;
-import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
-import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
-import org.springframework.beans.factory.annotation.Autowired;
-
-@RequiredArgsConstructor
-public abstract class AbstractBusinessEventSerializer implements BusinessEventSerializer {
-
-    @Setter(onMethod = @__({ @Autowired }))
-    private ByteBufferConverter byteBufferConverter;
-
-    @Override
-    public <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException {
-        ByteBufferSerializable avroDto = toAvroDTO(rawEvent);
-        ByteBuffer buffer = avroDto.toByteBuffer();
-        return byteBufferConverter.convert(buffer);
-    }
-
-    protected abstract <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent);
-}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
index ddb2ce9f6..416e223eb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/BusinessEventSerializer.java
@@ -18,15 +18,16 @@
  */
 package org.apache.fineract.infrastructure.event.external.service.serialization.serializer;
 
-import java.io.IOException;
 import org.apache.avro.generic.GenericContainer;
+import org.apache.fineract.avro.generator.ByteBufferSerializable;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 
 public interface BusinessEventSerializer {
 
     <T> boolean canSerialize(BusinessEvent<T> event);
 
-    <T> byte[] serialize(BusinessEvent<T> rawEvent) throws IOException;
-
     Class<? extends GenericContainer> getSupportedSchema();
+
+    <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent);
+
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/client/ClientBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/client/ClientBusinessEventSerializer.java
index 1b9a98b05..87ca3058e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/client/ClientBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/client/ClientBusinessEventSerializer.java
@@ -25,14 +25,14 @@ import org.apache.fineract.avro.generator.ByteBufferSerializable;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.client.ClientBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.client.ClientDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.client.data.ClientData;
 import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class ClientBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class ClientBusinessEventSerializer implements BusinessEventSerializer {
 
     private final ClientReadPlatformService service;
     private final ClientDataMapper mapper;
@@ -43,7 +43,7 @@ public class ClientBusinessEventSerializer extends AbstractBusinessEventSerializ
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         ClientBusinessEvent event = (ClientBusinessEvent) rawEvent;
         ClientData data = service.retrieveOne(event.get().getId());
         return mapper.map(data);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/fixeddeposit/FixedDepositAccountBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/fixeddeposit/FixedDepositAccountBusinessEventSerializer.java
index 04ec6c132..c1e0f8fb1 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/fixeddeposit/FixedDepositAccountBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/fixeddeposit/FixedDepositAccountBusinessEventSerializer.java
@@ -25,7 +25,7 @@ import org.apache.fineract.avro.generator.ByteBufferSerializable;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.deposit.FixedDepositAccountBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.fixeddeposit.FixedDepositAccountDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.savings.DepositAccountType;
 import org.apache.fineract.portfolio.savings.data.FixedDepositAccountData;
 import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService;
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class FixedDepositAccountBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class FixedDepositAccountBusinessEventSerializer implements BusinessEventSerializer {
 
     private final DepositAccountReadPlatformService service;
     private final FixedDepositAccountDataMapper mapper;
@@ -44,7 +44,7 @@ public class FixedDepositAccountBusinessEventSerializer extends AbstractBusiness
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         FixedDepositAccountBusinessEvent event = (FixedDepositAccountBusinessEvent) rawEvent;
         FixedDepositAccountData data = (FixedDepositAccountData) service.retrieveOne(DepositAccountType.FIXED_DEPOSIT, event.get().getId());
         return mapper.map(data);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/group/GroupsBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/group/GroupsBusinessEventSerializer.java
index a28c4407d..3d36fc3a8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/group/GroupsBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/group/GroupsBusinessEventSerializer.java
@@ -25,12 +25,12 @@ import org.apache.fineract.avro.generic.v1.CommandProcessingResultV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.group.GroupsBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.generic.CommandProcessingResultMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class GroupsBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class GroupsBusinessEventSerializer implements BusinessEventSerializer {
 
     private final CommandProcessingResultMapper mapper;
 
@@ -40,7 +40,7 @@ public class GroupsBusinessEventSerializer extends AbstractBusinessEventSerializ
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         GroupsBusinessEvent event = (GroupsBusinessEvent) rawEvent;
         return mapper.map(event.get());
     }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java
index 8ff06cbd5..b233504b5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountsStayedLockedBusinessEventSerializer.java
@@ -26,12 +26,12 @@ import org.apache.fineract.cob.data.LoanAccountsStayedLockedData;
 import org.apache.fineract.cob.loan.LoanAccountsStayedLockedBusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanAccountsStayedLockedDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanAccountsStayedLockedBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanAccountsStayedLockedBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanAccountsStayedLockedDataMapper mapper;
 
@@ -41,7 +41,7 @@ public class LoanAccountsStayedLockedBusinessEventSerializer extends AbstractBus
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanAccountsStayedLockedBusinessEvent event = (LoanAccountsStayedLockedBusinessEvent) rawEvent;
         LoanAccountsStayedLockedData loanAccounts = event.get();
         return mapper.map(loanAccounts);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAdjustTransactionBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAdjustTransactionBusinessEventSerializer.java
index 25052c0a4..5c3465eab 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAdjustTransactionBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAdjustTransactionBusinessEventSerializer.java
@@ -26,7 +26,7 @@ import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.LoanAdjustTransactionBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanTransactionDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import org.apache.fineract.portfolio.loanaccount.service.LoanChargePaidByReadPlatformService;
@@ -35,7 +35,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanAdjustTransactionBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanAdjustTransactionBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanReadPlatformService service;
     private final LoanTransactionDataMapper mapper;
@@ -47,7 +47,7 @@ public class LoanAdjustTransactionBusinessEventSerializer extends AbstractBusine
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanAdjustTransactionBusinessEvent event = (LoanAdjustTransactionBusinessEvent) rawEvent;
         LoanTransaction transactionToAdjust = event.get().getTransactionToAdjust();
         LoanTransactionData transactionToAdjustData = service.retrieveLoanTransaction(transactionToAdjust.getLoan().getId(),
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java
index 8e30978f4..25dbe7eb8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java
@@ -27,7 +27,7 @@ import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanAccountDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
 import org.apache.fineract.portfolio.loanaccount.data.CollectionData;
 import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData;
@@ -40,7 +40,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanReadPlatformService service;
     private final LoanAccountDataMapper mapper;
@@ -53,7 +53,7 @@ public class LoanBusinessEventSerializer extends AbstractBusinessEventSerializer
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanBusinessEvent event = (LoanBusinessEvent) rawEvent;
         Long loanId = event.get().getId();
         LoanAccountData data = service.retrieveOne(loanId);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeBusinessEventSerializer.java
index 065e056e1..7a80e872b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeBusinessEventSerializer.java
@@ -25,14 +25,14 @@ import org.apache.fineract.avro.loan.v1.LoanChargeDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanChargeBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanChargeDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.loanaccount.data.LoanChargeData;
 import org.apache.fineract.portfolio.loanaccount.service.LoanChargeReadPlatformService;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanChargeBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanChargeBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanChargeReadPlatformService service;
     private final LoanChargeDataMapper mapper;
@@ -43,7 +43,7 @@ public class LoanChargeBusinessEventSerializer extends AbstractBusinessEventSeri
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanChargeBusinessEvent event = (LoanChargeBusinessEvent) rawEvent;
         LoanChargeData data = service.retrieveLoanChargeDetails(event.get().getId(), event.get().getLoan().getId());
         return mapper.map(data);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeDeletedBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeDeletedBusinessEventSerializer.java
index 330d8b3fc..4ba8bc172 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeDeletedBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeDeletedBusinessEventSerializer.java
@@ -24,7 +24,7 @@ import org.apache.fineract.avro.generator.ByteBufferSerializable;
 import org.apache.fineract.avro.loan.v1.LoanChargeDeletedV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.charge.LoanDeleteChargeBusinessEvent;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
 import org.springframework.core.Ordered;
@@ -34,7 +34,7 @@ import org.springframework.stereotype.Component;
 @Component
 @RequiredArgsConstructor
 @Order(Ordered.LOWEST_PRECEDENCE - 1)
-public class LoanChargeDeletedBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanChargeDeletedBusinessEventSerializer implements BusinessEventSerializer {
 
     private final ByteBufferConverter byteBufferConverter;
 
@@ -44,7 +44,7 @@ public class LoanChargeDeletedBusinessEventSerializer extends AbstractBusinessEv
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanDeleteChargeBusinessEvent event = (LoanDeleteChargeBusinessEvent) rawEvent;
         LoanCharge loanCharge = event.get();
         Long id = loanCharge.getId();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeOffBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeOffBusinessEventSerializer.java
index 3c94d1bf1..84c2a2777 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeOffBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanChargeOffBusinessEventSerializer.java
@@ -56,7 +56,7 @@ public class LoanChargeOffBusinessEventSerializer extends LoanTransactionBusines
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanTransactionDataV1 transactionDataV1 = (LoanTransactionDataV1) super.toAvroDTO(rawEvent);
         LoanTransactionBusinessEvent event = (LoanTransactionBusinessEvent) rawEvent;
         List<UnpaidChargeData> unpaidChargeDataList = loanTransactionRepository.fetchTotalUnpaidChargesForLoan(event.get().getLoan());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
index e04156482..7fb24d9eb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
@@ -34,7 +34,7 @@ import org.apache.fineract.infrastructure.event.external.service.serialization.m
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanChargeDataMapper;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanDelinquencyRangeDataMapper;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
 import org.apache.fineract.portfolio.loanaccount.data.CollectionData;
@@ -50,7 +50,7 @@ import org.springframework.stereotype.Component;
 @Component
 @RequiredArgsConstructor
 @Order(Ordered.LOWEST_PRECEDENCE - 1)
-public class LoanDelinquencyRangeChangeBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanDelinquencyRangeChangeBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanReadPlatformService service;
 
@@ -66,7 +66,7 @@ public class LoanDelinquencyRangeChangeBusinessEventSerializer extends AbstractB
     private final AvroDateTimeMapper dataTimeMapper;
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanDelinquencyRangeChangeBusinessEvent event = (LoanDelinquencyRangeChangeBusinessEvent) rawEvent;
         LoanAccountData data = service.retrieveOne(event.get().getId());
         Long id = data.getId();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanProductBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanProductBusinessEventSerializer.java
index 70229d723..5a1345c8e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanProductBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanProductBusinessEventSerializer.java
@@ -25,14 +25,14 @@ import org.apache.fineract.avro.loan.v1.LoanProductDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.product.LoanProductBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanProductDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
 import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanProductBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanProductBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanProductReadPlatformService service;
     private final LoanProductDataMapper mapper;
@@ -43,7 +43,7 @@ public class LoanProductBusinessEventSerializer extends AbstractBusinessEventSer
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanProductBusinessEvent event = (LoanProductBusinessEvent) rawEvent;
         LoanProductData data = service.retrieveLoanProduct(event.get().getId());
         return mapper.map(data);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
index 384b0172f..84ad31b05 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializer.java
@@ -30,7 +30,7 @@ import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.repayment.LoanRepaymentBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanRepaymentPastDueDataMapper;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.portfolio.loanaccount.data.LoanRepaymentPastDueData;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -40,14 +40,14 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanRepaymentBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanRepaymentBusinessEventSerializer implements BusinessEventSerializer {
 
     private final AvroDateTimeMapper dataTimeMapper;
     private final LoanRepaymentPastDueDataMapper pastDueDataMapper;
     private final LoanCalculateRepaymentPastDueService pastDueService;
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
 
         LoanRepaymentBusinessEvent event = (LoanRepaymentBusinessEvent) rawEvent;
         LoanRepaymentScheduleInstallment repaymentInstallment = event.get();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanTransactionBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanTransactionBusinessEventSerializer.java
index ef5e26ab2..5c1ac8b2e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanTransactionBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanTransactionBusinessEventSerializer.java
@@ -25,7 +25,7 @@ import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.loan.transaction.LoanTransactionBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanTransactionDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTransactionData;
 import org.apache.fineract.portfolio.loanaccount.service.LoanChargePaidByReadPlatformService;
 import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class LoanTransactionBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class LoanTransactionBusinessEventSerializer implements BusinessEventSerializer {
 
     private final LoanReadPlatformService service;
     private final LoanTransactionDataMapper loanTransactionMapper;
@@ -45,7 +45,7 @@ public class LoanTransactionBusinessEventSerializer extends AbstractBusinessEven
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         LoanTransactionBusinessEvent event = (LoanTransactionBusinessEvent) rawEvent;
         Long loanId = event.get().getLoan().getId();
         Long loanTransactionId = event.get().getId();
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/recurringdeposit/RecurringDepositAccountBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/recurringdeposit/RecurringDepositAccountBusinessEventSerializer.java
index 3f291b45a..69ea5de45 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/recurringdeposit/RecurringDepositAccountBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/recurringdeposit/RecurringDepositAccountBusinessEventSerializer.java
@@ -25,7 +25,7 @@ import org.apache.fineract.avro.recurringdeposit.v1.RecurringDepositAccountDataV
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.deposit.RecurringDepositAccountBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.recurringdeposit.RecurringDepositAccountDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.savings.DepositAccountType;
 import org.apache.fineract.portfolio.savings.data.RecurringDepositAccountData;
 import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService;
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class RecurringDepositAccountBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class RecurringDepositAccountBusinessEventSerializer implements BusinessEventSerializer {
 
     private final DepositAccountReadPlatformService service;
     private final RecurringDepositAccountDataMapper mapper;
@@ -44,7 +44,7 @@ public class RecurringDepositAccountBusinessEventSerializer extends AbstractBusi
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         RecurringDepositAccountBusinessEvent event = (RecurringDepositAccountBusinessEvent) rawEvent;
         RecurringDepositAccountData data = (RecurringDepositAccountData) service.retrieveOne(DepositAccountType.RECURRING_DEPOSIT,
                 event.get().getId());
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountBusinessEventSerializer.java
index eba534061..2b349b36f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountBusinessEventSerializer.java
@@ -25,14 +25,14 @@ import org.apache.fineract.avro.savings.v1.SavingsAccountDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.savings.SavingsAccountBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.savings.SavingsAccountDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
 import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class SavingsAccountBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class SavingsAccountBusinessEventSerializer implements BusinessEventSerializer {
 
     private final SavingsAccountReadPlatformService service;
     private final SavingsAccountDataMapper mapper;
@@ -43,7 +43,7 @@ public class SavingsAccountBusinessEventSerializer extends AbstractBusinessEvent
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         SavingsAccountBusinessEvent event = (SavingsAccountBusinessEvent) rawEvent;
         SavingsAccountData data = service.retrieveOne(event.get().getId());
         return mapper.map(data);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountTransactionBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountTransactionBusinessEventSerializer.java
index e07d38f55..864f86c0e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountTransactionBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/savings/SavingsAccountTransactionBusinessEventSerializer.java
@@ -25,7 +25,7 @@ import org.apache.fineract.avro.savings.v1.SavingsAccountTransactionDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.savings.transaction.SavingsAccountTransactionBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.savings.SavingsAccountTransactionDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
 import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class SavingsAccountTransactionBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class SavingsAccountTransactionBusinessEventSerializer implements BusinessEventSerializer {
 
     private final SavingsAccountReadPlatformService service;
     private final SavingsAccountTransactionDataMapper mapper;
@@ -44,7 +44,7 @@ public class SavingsAccountTransactionBusinessEventSerializer extends AbstractBu
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         SavingsAccountTransactionBusinessEvent event = (SavingsAccountTransactionBusinessEvent) rawEvent;
         SavingsAccountTransaction tx = event.get();
         SavingsAccountTransactionData data = service.retrieveSavingsTransaction(tx.getSavingsAccount().getId(), tx.getId(),
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareAccountBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareAccountBusinessEventSerializer.java
index 138490131..61873f89e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareAccountBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareAccountBusinessEventSerializer.java
@@ -25,14 +25,14 @@ import org.apache.fineract.avro.share.v1.ShareAccountDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.share.ShareAccountBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.share.ShareAccountDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
 import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountReadPlatformService;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class ShareAccountBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class ShareAccountBusinessEventSerializer implements BusinessEventSerializer {
 
     private final ShareAccountReadPlatformService service;
     private final ShareAccountDataMapper mapper;
@@ -43,7 +43,7 @@ public class ShareAccountBusinessEventSerializer extends AbstractBusinessEventSe
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         ShareAccountBusinessEvent event = (ShareAccountBusinessEvent) rawEvent;
         ShareAccountData data = service.retrieveOne(event.get().getId(), false);
         return mapper.map(data);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareProductDividentsCreateBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareProductDividentsCreateBusinessEventSerializer.java
index 3370333b2..b8e154c1e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareProductDividentsCreateBusinessEventSerializer.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/share/ShareProductDividentsCreateBusinessEventSerializer.java
@@ -25,14 +25,14 @@ import org.apache.fineract.avro.share.v1.ShareProductDataV1;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.share.ShareProductDividentsCreateBusinessEvent;
 import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.share.ShareProductDataMapper;
-import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventSerializer;
+import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.portfolio.products.service.ShareProductReadPlatformService;
 import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-public class ShareProductDividentsCreateBusinessEventSerializer extends AbstractBusinessEventSerializer {
+public class ShareProductDividentsCreateBusinessEventSerializer implements BusinessEventSerializer {
 
     private final ShareProductReadPlatformService service;
     private final ShareProductDataMapper mapper;
@@ -43,7 +43,7 @@ public class ShareProductDividentsCreateBusinessEventSerializer extends Abstract
     }
 
     @Override
-    protected <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
+    public <T> ByteBufferSerializable toAvroDTO(BusinessEvent<T> rawEvent) {
         ShareProductDividentsCreateBusinessEvent event = (ShareProductDividentsCreateBusinessEvent) rawEvent;
         ShareProductData data = (ShareProductData) service.retrieveOne(event.get(), false);
         return mapper.map(data);
diff --git a/fineract-provider/src/main/resources/application.properties b/fineract-provider/src/main/resources/application.properties
index 963f8565c..d69d2f7f3 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -124,6 +124,8 @@ fineract.sampling.samplingRate=${FINERACT_SAMPLING_RATE:1000}
 fineract.sampling.sampledClasses=${FINERACT_SAMPLED_CLASSES:}
 fineract.sampling.resetPeriodSec=${FINERACT_SAMPLING_RESET_PERIOD_IN_SEC:60}
 
+fineract.module.external-asset-owner.enabled=${FINERACT_MODULE_EXTERNAL_ASSET_OWNER_ENABLED:true}
+
 # Logging pattern for the console
 logging.pattern.console=${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(%replace([%X{correlationId}]){'\\[\\]', ''}) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}}
 
diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventServiceTest.java
index 4360fc67d..5c529d0a6 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventServiceTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/ExternalEventServiceTest.java
@@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
@@ -31,13 +32,17 @@ import java.nio.ByteBuffer;
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import org.apache.fineract.avro.BulkMessageItemV1;
+import org.apache.fineract.avro.generator.ByteBufferSerializable;
 import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
+import org.apache.fineract.infrastructure.core.service.DataEnricherProcessor;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.event.business.domain.BulkBusinessEvent;
 import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
@@ -48,6 +53,7 @@ import org.apache.fineract.infrastructure.event.external.service.message.BulkMes
 import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializer;
 import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.BusinessEventSerializerFactory;
 import org.apache.fineract.infrastructure.event.external.service.support.ByteBufferConverter;
+import org.apache.fineract.investor.enricher.LoanAccountDataV1Enricher;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -59,6 +65,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
 @SuppressWarnings({ "rawtypes", "unchecked" })
 class ExternalEventServiceTest {
 
+    public static final String DUMMY_EXTERNAL_OWNER_ID = "dummy-external-owner-id";
+
+    public static final String DUMMY_SETTLEMENT_DATE = "2021-01-01";
     @Mock
     private ExternalEventRepository repository;
     @Mock
@@ -72,12 +81,17 @@ class ExternalEventServiceTest {
     @Mock
     private EntityManager entityManager;
 
+    @Mock
+    private LoanAccountDataV1Enricher loanAccountDataV1Enricher;
+
     private ExternalEventService underTest;
 
     @BeforeEach
     public void setUp() {
+        lenient().when(loanAccountDataV1Enricher.isDataTypeSupported(any())).thenReturn(true);
+        DataEnricherProcessor dataEnricherProcessor = new DataEnricherProcessor(Optional.of(Arrays.asList(loanAccountDataV1Enricher)));
         underTest = new ExternalEventService(repository, idempotencyKeyGenerator, serializerFactory, byteBufferConverter,
-                bulkMessageItemFactory);
+                bulkMessageItemFactory, dataEnricherProcessor);
         underTest.setEntityManager(entityManager);
         FineractPlatformTenant tenant = new FineractPlatformTenant(1L, "default", "Default Tenant", "Europe/Budapest", null);
         ThreadLocalContextUtil.setTenant(tenant);
@@ -101,7 +115,9 @@ class ExternalEventServiceTest {
         given(idempotencyKeyGenerator.generate(event)).willReturn("");
         given(serializerFactory.create(event)).willReturn(eventSerializer);
         given(eventSerializer.getSupportedSchema()).will(invocation -> LoanAccountDataV1.class);
-        given(eventSerializer.serialize(event)).willThrow(IOException.class);
+        ByteBufferSerializable byteBuffer = mock(LoanAccountDataV1.class);
+        given(eventSerializer.toAvroDTO(event)).willReturn(byteBuffer);
+        given(byteBuffer.toByteBuffer()).willThrow(new IOException(""));
         // when & then
         assertThatThrownBy(() -> underTest.postEvent(event)).isExactlyInstanceOf(RuntimeException.class);
     }
@@ -121,12 +137,16 @@ class ExternalEventServiceTest {
         given(event.getType()).willReturn(eventType);
         given(idempotencyKeyGenerator.generate(event)).willReturn(idempotencyKey);
         given(serializerFactory.create(event)).willReturn(eventSerializer);
+        LoanAccountDataV1 loanAccountData = new LoanAccountDataV1();
         given(eventSerializer.getSupportedSchema()).will(invocation -> LoanAccountDataV1.class);
-        given(eventSerializer.serialize(event)).willReturn(data);
+        given(eventSerializer.toAvroDTO(event)).willReturn(loanAccountData);
+        given(byteBufferConverter.convert(any(ByteBuffer.class))).willReturn(data);
         // when
         underTest.postEvent(event);
         // then
         verify(repository).save(externalEventArgumentCaptor.capture());
+        verify(loanAccountDataV1Enricher).isDataTypeSupported(LoanAccountDataV1.class);
+        verify(loanAccountDataV1Enricher).enrich(loanAccountData);
         ExternalEvent externalEvent = externalEventArgumentCaptor.getValue();
         assertThat(externalEvent.getIdempotencyKey()).isEqualTo(idempotencyKey);
         assertThat(externalEvent.getData()).isEqualTo(data);
@@ -171,14 +191,13 @@ class ExternalEventServiceTest {
         String idempotencyKey = "key";
         BusinessEvent event = mock(BusinessEvent.class);
         BusinessEventSerializer eventSerializer = mock(BusinessEventSerializer.class);
-        byte[] data = new byte[0];
 
         given(event.getType()).willReturn(eventType);
         given(event.getCategory()).willReturn(eventCategory);
         given(idempotencyKeyGenerator.generate(event)).willReturn(idempotencyKey);
         given(serializerFactory.create(event)).willReturn(eventSerializer);
         given(eventSerializer.getSupportedSchema()).will(invocation -> LoanAccountDataV1.class);
-        given(eventSerializer.serialize(event)).willReturn(data);
+        given(eventSerializer.toAvroDTO(event)).willReturn(new LoanAccountDataV1());
         // when
         underTest.postEvent(event);
         // then
@@ -198,14 +217,13 @@ class ExternalEventServiceTest {
         String idempotencyKey = "key";
         BusinessEvent event = mock(BusinessEvent.class);
         BusinessEventSerializer eventSerializer = mock(BusinessEventSerializer.class);
-        byte[] data = new byte[0];
 
         given(event.getType()).willReturn(eventType);
         given(event.getCategory()).willReturn(eventCategory);
         given(idempotencyKeyGenerator.generate(event)).willReturn(idempotencyKey);
         given(serializerFactory.create(event)).willReturn(eventSerializer);
         given(eventSerializer.getSupportedSchema()).will(invocation -> LoanAccountDataV1.class);
-        given(eventSerializer.serialize(event)).willReturn(data);
+        given(eventSerializer.toAvroDTO(event)).willReturn(new LoanAccountDataV1());
         // when
         underTest.postEvent(event);
         // then
diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
index 7293afd4a..6519ea604 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanRepaymentBusinessEventSerializerTest.java
@@ -103,7 +103,6 @@ public class LoanRepaymentBusinessEventSerializerTest {
         LocalDate loanInstallmentRepaymentDueDate = DateUtils.getBusinessLocalDate().plusDays(1);
 
         Loan loanForProcessing = Mockito.mock(Loan.class);
-        LoanProduct loanProduct = Mockito.mock(LoanProduct.class);
         LoanSummary loanSummary = Mockito.mock(LoanSummary.class);
         MonetaryCurrency loanCurrency = Mockito.mock(MonetaryCurrency.class);