From 6a65bc6592c4223e75fb62e1bfc805577a99e418 Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Mon, 14 Apr 2025 22:32:07 -0500 Subject: [PATCH] FINERACT-2181: Add customData field to LoanAccountDelinquencyRangeBusinessEvent --- .../v1/LoanAccountDelinquencyRangeDataV1.avsc | 11 ++++ ...ncyRangeChangeBusinessEventSerializer.java | 15 ++++- ...ntDelinquencyRangeEventSerializerTest.java | 59 ++++++++++++++++++- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDelinquencyRangeDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDelinquencyRangeDataV1.avsc index 53fca4268..37d358005 100644 --- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDelinquencyRangeDataV1.avsc +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDelinquencyRangeDataV1.avsc @@ -61,6 +61,17 @@ "items": "org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1" } ] + }, + { + "default": null, + "name": "customData", + "type": [ + "null", + { + "values": "bytes", + "type": "map" + } + ] } ] } 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 8c0214873..def36a44e 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 @@ -36,7 +36,8 @@ 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.BusinessEventSerializer; +import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.AbstractBusinessEventWithCustomDataSerializer; +import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.ExternalEventCustomDataSerializer; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService; import org.apache.fineract.portfolio.loanaccount.data.CollectionData; @@ -52,7 +53,8 @@ import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor @Order(Ordered.LOWEST_PRECEDENCE - 1) -public class LoanDelinquencyRangeChangeBusinessEventSerializer implements BusinessEventSerializer { +public class LoanDelinquencyRangeChangeBusinessEventSerializer + extends AbstractBusinessEventWithCustomDataSerializer { private final LoanReadPlatformService service; @@ -67,6 +69,7 @@ public class LoanDelinquencyRangeChangeBusinessEventSerializer implements Busine private final CurrencyDataMapper currencyMapper; private final AvroDateTimeMapper dataTimeMapper; private final LoanInstallmentLevelDelinquencyEventProducer installmentLevelDelinquencyEventProducer; + private final List> externalEventCustomDataSerializers; @Override public ByteBufferSerializable toAvroDTO(BusinessEvent rawEvent) { @@ -111,7 +114,8 @@ public class LoanDelinquencyRangeChangeBusinessEventSerializer implements Busine .setAmount(amount)// .setCurrency(currencyMapper.map(data.getCurrency()))// .setDelinquentDate(delinquentDate)// - .setInstallmentDelinquencyBuckets(installmentsDelinquencyData).build(); + .setInstallmentDelinquencyBuckets(installmentsDelinquencyData)// + .setCustomData(collectCustomData(event)).build(); } private BigDecimal calculateDataSummary(Loan loan, BiFunction mapper) { @@ -129,4 +133,9 @@ public class LoanDelinquencyRangeChangeBusinessEventSerializer implements Busine public Class getSupportedSchema() { return LoanAccountDelinquencyRangeDataV1.class; } + + @Override + protected List> getExternalEventCustomDataSerializers() { + return externalEventCustomDataSerializers; + } } diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java index 4e17fc342..a8d1be5da 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java @@ -18,7 +18,9 @@ */ package org.apache.fineract.infrastructure.event.external.service.serialization.serializer.loan; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; @@ -31,6 +33,7 @@ import java.io.IOException; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import java.nio.ByteBuffer; import java.time.LocalDate; import java.time.ZoneId; import java.util.ArrayList; @@ -55,6 +58,7 @@ import org.apache.fineract.infrastructure.event.external.service.serialization.m import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanChargeDataMapperImpl; import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.loan.LoanDelinquencyRangeDataMapperImpl; import org.apache.fineract.infrastructure.event.external.service.serialization.mapper.support.AvroDateTimeMapper; +import org.apache.fineract.infrastructure.event.external.service.serialization.serializer.ExternalEventCustomDataSerializer; import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency; import org.apache.fineract.organisation.monetary.domain.Money; @@ -119,6 +123,8 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { private MockedStatic moneyHelper = Mockito.mockStatic(MoneyHelper.class); + private static final String CUSTOM_DATA_PREFIX = "test_data_loan_delinquency_range_business_event"; + @BeforeEach public void setUp() { moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP)); @@ -141,7 +147,8 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { LoanDelinquencyRangeChangeBusinessEventSerializer serializer = new LoanDelinquencyRangeChangeBusinessEventSerializer( loanReadPlatformService, new LoanDelinquencyRangeDataMapperImpl(), loanChargeReadPlatformService, delinquencyReadPlatformService, new LoanChargeDataMapperImpl(null, null, null), new CurrencyDataMapperImpl(), mapper, - new LoanInstallmentLevelDelinquencyEventProducer(delinquencyReadPlatformService, new CurrencyDataMapperImpl())); + new LoanInstallmentLevelDelinquencyEventProducer(delinquencyReadPlatformService, new CurrencyDataMapperImpl()), + createCustomDataForEvents()); Loan loanForProcessing = Mockito.mock(Loan.class); LoanAccountData loanAccountData = mock(LoanAccountData.class); @@ -193,6 +200,11 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { assertEquals(0, data.getAmount().getFeeAmount().compareTo(new BigDecimal("5.0"))); assertEquals(0, data.getAmount().getPenaltyAmount().compareTo(new BigDecimal("50.0"))); assertEquals(delinquentDateAsStr, data.getDelinquentDate()); + + assertNotNull(data.getCustomData()); + final Map customData = data.getCustomData(); + assertEquals(CUSTOM_DATA_PREFIX + "_1", new String(customData.get("test_key_1").array(), UTF_8)); + assertEquals(CUSTOM_DATA_PREFIX + "_2", new String(customData.get("test_key_2").array(), UTF_8)); } @Test @@ -201,7 +213,8 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { LoanDelinquencyRangeChangeBusinessEventSerializer serializer = new LoanDelinquencyRangeChangeBusinessEventSerializer( loanReadPlatformService, new LoanDelinquencyRangeDataMapperImpl(), loanChargeReadPlatformService, delinquencyReadPlatformService, new LoanChargeDataMapperImpl(null, null, null), new CurrencyDataMapperImpl(), mapper, - new LoanInstallmentLevelDelinquencyEventProducer(delinquencyReadPlatformService, new CurrencyDataMapperImpl())); + new LoanInstallmentLevelDelinquencyEventProducer(delinquencyReadPlatformService, new CurrencyDataMapperImpl()), + createCustomDataForEvents()); Loan loanForProcessing = Mockito.mock(Loan.class); LoanAccountData loanAccountData = mock(LoanAccountData.class); @@ -284,6 +297,11 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { assertEquals(0, data.getAmount().getPenaltyAmount().compareTo(new BigDecimal("20.0"))); assertEquals(delinquentDateAsStr, data.getDelinquentDate()); + assertNotNull(data.getCustomData()); + final Map customData = data.getCustomData(); + assertEquals(CUSTOM_DATA_PREFIX + "_1", new String(customData.get("test_key_1").array(), UTF_8)); + assertEquals(CUSTOM_DATA_PREFIX + "_2", new String(customData.get("test_key_2").array(), UTF_8)); + // check installment delinquency data assertEquals(2, data.getInstallmentDelinquencyBuckets().size()); @@ -414,4 +432,41 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { ReflectionTestUtils.setField(loanCharge, "id", 1L); return loanCharge; } + + private List> createCustomDataForEvents() { + return List.of(new ExternalEventCustomDataSerializer<>() { + + @Override + public ByteBuffer serialize(final LoanDelinquencyRangeChangeBusinessEvent event) { + return ByteBuffer.wrap(CUSTOM_DATA_PREFIX.getBytes(UTF_8)); + } + + @Override + public String key() { + return "test_key_1"; + } + }, new ExternalEventCustomDataSerializer<>() { + + @Override + public ByteBuffer serialize(final LoanDelinquencyRangeChangeBusinessEvent event) { + return ByteBuffer.wrap((CUSTOM_DATA_PREFIX + "_1").getBytes(UTF_8)); + } + + @Override + public String key() { + return "test_key_1"; + } + }, new ExternalEventCustomDataSerializer<>() { + + @Override + public ByteBuffer serialize(final LoanDelinquencyRangeChangeBusinessEvent event) { + return ByteBuffer.wrap((CUSTOM_DATA_PREFIX + "_2").getBytes(UTF_8)); + } + + @Override + public String key() { + return "test_key_2"; + } + }); + } }