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 2024/10/22 16:45:34 UTC

(fineract) branch develop updated: FINERACT-1981: Remove hardcoded MoneyHelper dependency during progressive loan

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 a9ecdf97a FINERACT-1981: Remove hardcoded MoneyHelper dependency during progressive loan
a9ecdf97a is described below

commit a9ecdf97a4ccb94ae50bad6dc7623f3d06ba0f0e
Author: Andrii Kulminskyi <ku...@gmail.com>
AuthorDate: Mon Oct 21 13:48:03 2024 +0300

    FINERACT-1981: Remove hardcoded MoneyHelper dependency during progressive loan
---
 .../infrastructure/core/service/MathUtil.java      |  17 ++
 .../organisation/monetary/domain/Money.java        | 177 +++++++++++++++++----
 .../organisation/monetary/domain/MoneyHelper.java  |   1 +
 fineract-loan/dependencies.gradle                  |   5 +
 .../loanschedule/data/LoanScheduleParams.java      |  72 +++++----
 .../AbstractCumulativeLoanScheduleGenerator.java   |  26 +--
 .../domain/DefaultScheduledDateGenerator.java      |  61 +++----
 .../loanschedule/domain/LoanApplicationTerms.java  |  41 +++--
 .../domain/LoanScheduleModelRepaymentPeriod.java   |  24 +--
 .../domain/ScheduledDateGenerator.java             |   5 +-
 ...argeRepaymentScheduleProcessingWrapperTest.java |   7 +-
 ...dvancedPaymentScheduleTransactionProcessor.java |   2 +-
 .../loanschedule/data/InterestPeriod.java          |  25 +--
 .../data/ProgressiveLoanInterestScheduleModel.java |  20 ++-
 .../loanschedule/data/RepaymentPeriod.java         |  55 ++++---
 .../domain/ProgressiveLoanScheduleGenerator.java   |  34 ++--
 .../portfolio/loanproduct/calc/EMICalculator.java  |   5 +-
 .../loanproduct/calc/ProgressiveEMICalculator.java | 156 +++++++++---------
 ...cedPaymentScheduleTransactionProcessorTest.java |   4 +-
 .../domain/LoanScheduleGeneratorTest.java          |  63 ++------
 .../calc/ProgressiveEMICalculatorTest.java         |  43 ++---
 .../CheckLoanRepaymentOverdueBusinessStepTest.java |   2 +
 ...AccountDelinquencyRangeEventSerializerTest.java |  15 +-
 .../LoanRepaymentBusinessEventSerializerTest.java  |   4 +-
 .../LoanDelinquencyDomainServiceTest.java          |   4 +-
 .../DefaultLoanLifecycleStateMachineTest.java      |   4 +-
 ...nRepaymentScheduleTransactionProcessorTest.java |   2 +
 ...nRepaymentScheduleTransactionProcessorTest.java |   2 +
 .../domain/DefaultScheduledDateGeneratorTest.java  |   7 +-
 .../LoanCalculateRepaymentPastDueServiceTest.java  |   4 +-
 .../LoanDownPaymentHandlerServiceImplTest.java     |   4 +-
 31 files changed, 536 insertions(+), 355 deletions(-)

diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
index 406f16c08..2e0779ef9 100644
--- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
+++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
@@ -359,6 +359,11 @@ public final class MathUtil {
         return value == null || isGreaterThanZero(value) ? value : Money.zero(value.getCurrency());
     }
 
+    /** @return parameter value or ZERO if it is negative */
+    public static Money negativeToZero(Money value, MathContext mc) {
+        return value == null || isGreaterThanZero(value, mc) ? value : Money.zero(value.getCurrency(), mc);
+    }
+
     public static boolean isEmpty(Money value) {
         return value == null || value.isZero();
     }
@@ -367,6 +372,10 @@ public final class MathUtil {
         return value != null && value.isGreaterThanZero();
     }
 
+    public static boolean isGreaterThanZero(Money value, MathContext mc) {
+        return value != null && value.isGreaterThanZero(mc);
+    }
+
     public static boolean isLessThanZero(Money value) {
         return value != null && value.isLessThanZero();
     }
@@ -387,10 +396,18 @@ public final class MathUtil {
         return first == null ? second : second == null ? first : first.plus(second);
     }
 
+    public static Money plus(Money first, Money second, MathContext mc) {
+        return first == null ? second : second == null ? first : first.plus(second, mc);
+    }
+
     public static Money plus(Money first, Money second, Money third) {
         return plus(plus(first, second), third);
     }
 
+    public static Money plus(Money first, Money second, Money third, MathContext mc) {
+        return plus(plus(first, second), third, mc);
+    }
+
     public static Money plus(Money first, Money second, Money third, Money fourth) {
         return plus(plus(plus(first, second), third), fourth);
     }
diff --git a/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/Money.java b/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/Money.java
index 9e2d51af9..8ec1a84fc 100644
--- a/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/Money.java
+++ b/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/Money.java
@@ -21,11 +21,14 @@ package org.apache.fineract.organisation.monetary.domain;
 import jakarta.persistence.Column;
 import jakarta.persistence.Embeddable;
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.util.Iterator;
+import lombok.Getter;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 
 @Embeddable
+@Getter
 public class Money implements Comparable<Money> {
 
     @Column(name = "currency_code", length = 3)
@@ -40,6 +43,16 @@ public class Money implements Comparable<Money> {
     @Column(name = "amount", scale = 6, precision = 19)
     private BigDecimal amount;
 
+    private final transient MathContext mc;
+
+    protected Money() {
+        this.currencyCode = null;
+        this.currencyDigitsAfterDecimal = 0;
+        this.inMultiplesOf = 0;
+        this.amount = null;
+        this.mc = getMc();
+    }
+
     public static Money total(final Money... monies) {
         if (monies.length == 0) {
             throw new IllegalArgumentException("Money array must not be empty");
@@ -53,7 +66,7 @@ public class Money implements Comparable<Money> {
 
     public static Money total(final Iterable<? extends Money> monies) {
         final Iterator<? extends Money> it = monies.iterator();
-        if (it.hasNext() == false) {
+        if (!it.hasNext()) {
             throw new IllegalArgumentException("Money iterator must not be empty");
         }
         Money total = it.next();
@@ -63,34 +76,47 @@ public class Money implements Comparable<Money> {
         return total;
     }
 
+    public static Money of(final MonetaryCurrency currency, final BigDecimal newAmount, final MathContext mc) {
+        return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), defaultToZeroIfNull(newAmount),
+                currency.getCurrencyInMultiplesOf(), mc);
+    }
+
     public static Money of(final MonetaryCurrency currency, final BigDecimal newAmount) {
         return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), defaultToZeroIfNull(newAmount),
-                currency.getCurrencyInMultiplesOf());
+                currency.getCurrencyInMultiplesOf(), null);
     }
 
     public static Money of(final CurrencyData currency, final BigDecimal newAmount) {
-        return new Money(currency.getCode(), currency.getDecimalPlaces(), defaultToZeroIfNull(newAmount), currency.getInMultiplesOf());
+        return new Money(currency.getCode(), currency.getDecimalPlaces(), defaultToZeroIfNull(newAmount), currency.getInMultiplesOf(),
+                null);
+    }
+
+    public static Money of(final CurrencyData currency, final BigDecimal newAmount, final MathContext mc) {
+        return new Money(currency.getCode(), currency.getDecimalPlaces(), defaultToZeroIfNull(newAmount), currency.getInMultiplesOf(), mc);
     }
 
     public static Money zero(final MonetaryCurrency currency) {
-        return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO, currency.getCurrencyInMultiplesOf());
+        return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO, currency.getCurrencyInMultiplesOf(), null);
     }
 
-    public static Money zero(final CurrencyData currency) {
-        return new Money(currency.getCode(), currency.getDecimalPlaces(), BigDecimal.ZERO, currency.getInMultiplesOf());
+    public static Money zero(final MonetaryCurrency currency, MathContext mc) {
+        return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO, currency.getCurrencyInMultiplesOf(), mc);
     }
 
-    protected Money() {
-        this.currencyCode = null;
-        this.currencyDigitsAfterDecimal = 0;
-        this.inMultiplesOf = 0;
-        this.amount = null;
+    public static Money zero(final CurrencyData currency, MathContext mc) {
+        return new Money(currency.getCode(), currency.getDecimalPlaces(), BigDecimal.ZERO, currency.getInMultiplesOf(), mc);
+    }
+
+    public static Money zero(final CurrencyData currency) {
+        return new Money(currency.getCode(), currency.getDecimalPlaces(), BigDecimal.ZERO, currency.getInMultiplesOf(), null);
     }
 
-    private Money(final String currencyCode, final int digitsAfterDecimal, final BigDecimal amount, final Integer inMultiplesOf) {
+    private Money(final String currencyCode, final int digitsAfterDecimal, final BigDecimal amount, final Integer inMultiplesOf,
+            final MathContext mc) {
         this.currencyCode = currencyCode;
         this.currencyDigitsAfterDecimal = digitsAfterDecimal;
         this.inMultiplesOf = inMultiplesOf;
+        this.mc = mc;
 
         final BigDecimal amountZeroed = defaultToZeroIfNull(amount);
         final BigDecimal amountStripped = amountZeroed.stripTrailingZeros();
@@ -101,7 +127,7 @@ public class Money implements Comparable<Money> {
             final double existingVal = amountScaled.doubleValue();
             amountScaled = BigDecimal.valueOf(roundToMultiplesOf(existingVal, inMultiplesOf));
         }
-        this.amount = amountScaled.setScale(this.currencyDigitsAfterDecimal, MoneyHelper.getRoundingMode());
+        this.amount = amountScaled.setScale(this.currencyDigitsAfterDecimal, getMc().getRoundingMode());
     }
 
     public static double roundToMultiplesOf(final double existingVal, final Integer inMultiplesOf) {
@@ -130,10 +156,14 @@ public class Money implements Comparable<Money> {
     }
 
     public static Money roundToMultiplesOf(final Money existingVal, final Integer inMultiplesOf) {
+        return roundToMultiplesOf(existingVal, inMultiplesOf, MoneyHelper.getMathContext());
+    }
+
+    public static Money roundToMultiplesOf(final Money existingVal, final Integer inMultiplesOf, final MathContext mc) {
         BigDecimal amountScaled = existingVal.getAmount();
         BigDecimal inMultiplesOfValue = BigDecimal.valueOf(inMultiplesOf.intValue());
         if (inMultiplesOfValue.compareTo(BigDecimal.ZERO) > 0) {
-            amountScaled = amountScaled.divide(inMultiplesOfValue, 0, MoneyHelper.getRoundingMode()).multiply(inMultiplesOfValue);
+            amountScaled = amountScaled.divide(inMultiplesOfValue, 0, mc.getRoundingMode()).multiply(inMultiplesOfValue);
         }
         return Money.of(existingVal.getCurrency(), amountScaled);
     }
@@ -171,7 +201,7 @@ public class Money implements Comparable<Money> {
     }
 
     public Money copy() {
-        return new Money(this.currencyCode, this.currencyDigitsAfterDecimal, this.amount.stripTrailingZeros(), this.inMultiplesOf);
+        return new Money(this.currencyCode, this.currencyDigitsAfterDecimal, this.amount.stripTrailingZeros(), this.inMultiplesOf, this.mc);
     }
 
     public Money plus(final Iterable<? extends Money> moniesToAdd) {
@@ -188,6 +218,11 @@ public class Money implements Comparable<Money> {
         return this.plus(toAdd.getAmount());
     }
 
+    public Money plus(final Money moneyToAdd, final MathContext mc) {
+        final Money toAdd = checkCurrencyEqual(moneyToAdd);
+        return this.plus(toAdd.getAmount(), mc);
+    }
+
     public Money plus(final BigDecimal amountToAdd) {
         if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
             return this;
@@ -196,6 +231,14 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money plus(final BigDecimal amountToAdd, MathContext mc) {
+        if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.add(amountToAdd);
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     public Money plus(final double amountToAdd) {
         if (amountToAdd == 0) {
             return this;
@@ -209,11 +252,21 @@ public class Money implements Comparable<Money> {
         return this.minus(toSubtract.getAmount());
     }
 
+    public Money minus(final Money moneyToSubtract, final MathContext mc) {
+        final Money toSubtract = checkCurrencyEqual(moneyToSubtract);
+        return this.minus(toSubtract.getAmount(), mc);
+    }
+
     public Money add(final Money moneyToAdd) {
         final Money toAdd = checkCurrencyEqual(moneyToAdd);
         return this.add(toAdd.getAmount());
     }
 
+    public Money add(final Money moneyToAdd, final MathContext mc) {
+        final Money toAdd = checkCurrencyEqual(moneyToAdd);
+        return this.add(toAdd.getAmount(), mc);
+    }
+
     public Money add(final BigDecimal amountToAdd) {
         if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
             return this;
@@ -222,6 +275,14 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money add(final BigDecimal amountToAdd, final MathContext mc) {
+        if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) == 0) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.add(amountToAdd);
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     public Money minus(final BigDecimal amountToSubtract) {
         if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) == 0) {
             return this;
@@ -230,8 +291,16 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money minus(final BigDecimal amountToSubtract, final MathContext mc) {
+        if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) == 0) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.subtract(amountToSubtract);
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     private Money checkCurrencyEqual(final Money money) {
-        if (isSameCurrency(money) == false) {
+        if (!isSameCurrency(money)) {
             throw new UnsupportedOperationException("currencies are different.");
         }
         return money;
@@ -249,6 +318,14 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money dividedBy(final BigDecimal valueToDivideBy, final RoundingMode roundingMode, final MathContext mc) {
+        if (valueToDivideBy.compareTo(BigDecimal.ONE) == 0) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.divide(valueToDivideBy, roundingMode);
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     public Money dividedBy(final double valueToDivideBy, final RoundingMode roundingMode) {
         if (valueToDivideBy == 1) {
             return this;
@@ -265,6 +342,14 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money dividedBy(final long valueToDivideBy, final RoundingMode roundingMode, final MathContext mc) {
+        if (valueToDivideBy == 1) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.divide(BigDecimal.valueOf(valueToDivideBy), roundingMode);
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     public Money multipliedBy(final BigDecimal valueToMultiplyBy) {
         if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) {
             return this;
@@ -273,6 +358,14 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money multipliedBy(final BigDecimal valueToMultiplyBy, final MathContext mc) {
+        if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.multiply(valueToMultiplyBy);
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     public Money multipliedBy(final double valueToMultiplyBy) {
         if (valueToMultiplyBy == 1) {
             return this;
@@ -289,6 +382,14 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), newAmount);
     }
 
+    public Money multipliedBy(final long valueToMultiplyBy, final MathContext mc) {
+        if (valueToMultiplyBy == 1) {
+            return this;
+        }
+        final BigDecimal newAmount = this.amount.multiply(BigDecimal.valueOf(valueToMultiplyBy));
+        return Money.of(monetaryCurrency(), newAmount, mc);
+    }
+
     public Money multiplyRetainScale(final BigDecimal valueToMultiplyBy, final RoundingMode roundingMode) {
         if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) {
             return this;
@@ -309,17 +410,20 @@ public class Money implements Comparable<Money> {
 
     @Override
     public int compareTo(final Money other) {
-        final Money otherMoney = other;
-        if (this.currencyCode.equals(otherMoney.currencyCode) == false) {
+        if (!this.currencyCode.equals(other.currencyCode)) {
             throw new UnsupportedOperationException("currencies arent different");
         }
-        return this.amount.compareTo(otherMoney.amount);
+        return this.amount.compareTo(other.amount);
     }
 
     public boolean isZero() {
         return isEqualTo(Money.zero(getCurrency()));
     }
 
+    public boolean isZero(final MathContext mc) {
+        return isEqualTo(Money.zero(getCurrency(), mc));
+    }
+
     public boolean isEqualTo(final Money other) {
         return compareTo(other) == 0;
     }
@@ -340,6 +444,10 @@ public class Money implements Comparable<Money> {
         return isGreaterThan(Money.zero(getCurrency()));
     }
 
+    public boolean isGreaterThanZero(MathContext mc) {
+        return isGreaterThan(Money.zero(getCurrency(), mc));
+    }
+
     public boolean isLessThan(final Money other) {
         return compareTo(other) < 0;
     }
@@ -348,22 +456,14 @@ public class Money implements Comparable<Money> {
         return isLessThan(Money.zero(getCurrency()));
     }
 
-    public String getCurrencyCode() {
-        return this.currencyCode;
-    }
-
-    public int getCurrencyDigitsAfterDecimal() {
-        return this.currencyDigitsAfterDecimal;
+    public boolean isLessThanZero(final MathContext mc) {
+        return isLessThan(Money.zero(getCurrency(), mc));
     }
 
     public Integer getCurrencyInMultiplesOf() {
         return this.inMultiplesOf;
     }
 
-    public BigDecimal getAmount() {
-        return this.amount;
-    }
-
     public BigDecimal getAmountDefaultedToNullIfZero() {
         return defaultToNullIfZero(this.amount);
     }
@@ -388,10 +488,21 @@ public class Money implements Comparable<Money> {
         return Money.of(monetaryCurrency(), this.amount.negate());
     }
 
+    public Money negated(final MathContext mc) {
+        if (isZero(mc)) {
+            return this;
+        }
+        return Money.of(monetaryCurrency(), this.amount.negate(), mc);
+    }
+
     public Money abs() {
         return isLessThanZero() ? negated() : this;
     }
 
+    public Money abs(MathContext mc) {
+        return isLessThanZero(mc) ? negated(mc) : this;
+    }
+
     public MonetaryCurrency getCurrency() {
         return monetaryCurrency();
     }
@@ -403,4 +514,12 @@ public class Money implements Comparable<Money> {
     public Money zero() {
         return Money.zero(getCurrency());
     }
+
+    public Money zero(MathContext mc) {
+        return Money.zero(getCurrency(), mc);
+    }
+
+    public MathContext getMc() {
+        return mc != null ? mc : MoneyHelper.getMathContext();
+    }
 }
diff --git a/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java b/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java
index d3cefb27d..1a99e7311 100644
--- a/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java
+++ b/fineract-core/src/main/java/org/apache/fineract/organisation/monetary/domain/MoneyHelper.java
@@ -65,6 +65,7 @@ public class MoneyHelper {
     public static void fetchRoundingModeFromGlobalConfig() {
         roundingMode = RoundingMode.valueOf(staticConfigurationDomainService.getRoundingMode());
         log.info("Fetch Rounding Mode from Global Config {}", roundingMode.name());
+        mathContext = null;
     }
 
 }
diff --git a/fineract-loan/dependencies.gradle b/fineract-loan/dependencies.gradle
index 2122febb5..5d439e708 100644
--- a/fineract-loan/dependencies.gradle
+++ b/fineract-loan/dependencies.gradle
@@ -59,6 +59,11 @@ dependencies {
             'org.apache.commons:commons-collections4'
 
             )
+    implementation ('org.mnode.ical4j:ical4j') {
+        exclude group: 'commons-logging'
+        exclude group: 'javax.activation'
+        exclude group: 'com.sun.mail', module: 'javax.mail'
+    }
     compileOnly 'org.projectlombok:lombok'
     annotationProcessor 'org.projectlombok:lombok'
     annotationProcessor 'org.mapstruct:mapstruct-processor'
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
index f73f67b19..635b62bd7 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.portfolio.loanaccount.loanschedule.data;
 
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -98,6 +99,7 @@ public final class LoanScheduleParams {
     private int loanTermInDays;
     private final MonetaryCurrency currency;
     private final boolean applyInterestRecalculation;
+    private final MathContext mc;
 
     private LoanScheduleParams(final int periodNumber, final int instalmentNumber, int loanTermInDays, LocalDate periodStartDate,
             final LocalDate actualRepaymentDate, final Money totalCumulativePrincipal, final Money totalCumulativeInterest,
@@ -108,7 +110,7 @@ public final class LoanScheduleParams {
             final Money outstandingBalanceAsPerRest, final List<LoanRepaymentScheduleInstallment> installments,
             final Collection<RecalculationDetail> recalculationDetails,
             final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final LocalDate scheduleTillDate,
-            final boolean partialUpdate, final MonetaryCurrency currency, final boolean applyInterestRecalculation) {
+            final boolean partialUpdate, final MonetaryCurrency currency, final boolean applyInterestRecalculation, final MathContext mc) {
         this.periodNumber = periodNumber;
         this.instalmentNumber = instalmentNumber;
         this.loanTermInDays = loanTermInDays;
@@ -136,8 +138,9 @@ public final class LoanScheduleParams {
         this.partialUpdate = partialUpdate;
         this.currency = currency;
         this.applyInterestRecalculation = applyInterestRecalculation;
+        this.mc = mc;
         if (this.currency != null) {
-            this.compoundedInLastInstallment = Money.zero(this.currency);
+            this.compoundedInLastInstallment = Money.zero(this.currency, mc);
         }
     }
 
@@ -150,19 +153,19 @@ public final class LoanScheduleParams {
             final Money principalToBeScheduled, final Money outstandingBalance, final Money outstandingBalanceAsPerRest,
             final List<LoanRepaymentScheduleInstallment> installments, final Collection<RecalculationDetail> recalculationDetails,
             final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final LocalDate scheduleTillDate,
-            final MonetaryCurrency currency, final boolean applyInterestRecalculation) {
+            final MonetaryCurrency currency, final boolean applyInterestRecalculation, final MathContext mc) {
         final boolean partialUpdate = true;
         return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
                 totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
                 totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
                 compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
                 outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
-                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
+                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation, mc);
     }
 
     public static LoanScheduleParams createLoanScheduleParamsForCompleteUpdate(final Collection<RecalculationDetail> recalculationDetails,
             final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor, final LocalDate scheduleTillDate,
-            final boolean applyInterestRecalculation) {
+            final boolean applyInterestRecalculation, MathContext mc) {
         final int periodNumber = 1;
         final int instalmentNumber = 1;
         final LocalDate periodStartDate = null;
@@ -191,22 +194,22 @@ public final class LoanScheduleParams {
                 totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
                 compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
                 outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
-                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
+                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation, mc);
     }
 
     public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency currency, final Money chargesDueAtTimeOfDisbursement,
-            final LocalDate periodStartDate, final Money principalToBeScheduled) {
+            final LocalDate periodStartDate, final Money principalToBeScheduled, final MathContext mc) {
         final int loanTermInDays = 0;
         final int periodNumber = 1;
         final int instalmentNumber = 1;
-        final Money totalCumulativePrincipal = Money.zero(currency);
-        final Money totalCumulativeInterest = Money.zero(currency);
-        final Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency);
+        final Money totalCumulativePrincipal = Money.zero(currency, mc);
+        final Money totalCumulativeInterest = Money.zero(currency, mc);
+        final Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency, mc);
         final LocalDate actualRepaymentDate = periodStartDate;
         final Money totalFeeChargesCharged = chargesDueAtTimeOfDisbursement;
-        final Money totalPenaltyChargesCharged = Money.zero(currency);
+        final Money totalPenaltyChargesCharged = Money.zero(currency, mc);
         final Money totalRepaymentExpected = chargesDueAtTimeOfDisbursement;
-        final Money reducePrincipal = Money.zero(currency);
+        final Money reducePrincipal = Money.zero(currency, mc);
         final Map<LocalDate, Money> principalPortionMap = new HashMap<>();
         final Map<LocalDate, Money> latePaymentMap = new HashMap<>();
         final Map<LocalDate, Money> compoundingMap = new TreeMap<>();
@@ -218,27 +221,28 @@ public final class LoanScheduleParams {
         final Collection<RecalculationDetail> recalculationDetails = null;
         final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = null;
         final LocalDate scheduleTillDate = null;
-        final Money unCompoundedAmount = Money.zero(currency);
+        final Money unCompoundedAmount = Money.zero(currency, mc);
         final boolean applyInterestRecalculation = false;
         return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
                 totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
                 totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
                 compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
                 outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
-                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
+                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation, mc);
     }
 
     public static LoanScheduleParams createLoanScheduleParams(final MonetaryCurrency currency, final Money chargesDueAtTimeOfDisbursement,
-            final LocalDate periodStartDate, final Money principalToBeScheduled, final LoanScheduleParams loanScheduleParams) {
+            final LocalDate periodStartDate, final Money principalToBeScheduled, final LoanScheduleParams loanScheduleParams,
+            MathContext mc) {
         final int loanTermInDays = 0;
         final int periodNumber = 1;
         final int instalmentNumber = 1;
-        final Money totalCumulativePrincipal = Money.zero(currency);
-        final Money totalCumulativeInterest = Money.zero(currency);
-        final Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency);
+        final Money totalCumulativePrincipal = Money.zero(currency, mc);
+        final Money totalCumulativeInterest = Money.zero(currency, mc);
+        final Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency, mc);
         final LocalDate actualRepaymentDate = periodStartDate;
         final Money totalFeeChargesCharged = chargesDueAtTimeOfDisbursement;
-        final Money totalPenaltyChargesCharged = Money.zero(currency);
+        final Money totalPenaltyChargesCharged = Money.zero(currency, mc);
         final Money totalRepaymentExpected = chargesDueAtTimeOfDisbursement;
         final Money reducePrincipal = Money.zero(currency);
         final Map<LocalDate, Money> principalPortionMap = new HashMap<>();
@@ -253,13 +257,13 @@ public final class LoanScheduleParams {
         final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loanScheduleParams.loanRepaymentScheduleTransactionProcessor;
         final LocalDate scheduleTillDate = loanScheduleParams.scheduleTillDate;
         final boolean applyInterestRecalculation = loanScheduleParams.applyInterestRecalculation;
-        final Money unCompoundedAmount = Money.zero(currency);
+        final Money unCompoundedAmount = Money.zero(currency, mc);
         return new LoanScheduleParams(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate,
                 totalCumulativePrincipal, totalCumulativeInterest, totalFeeChargesCharged, totalPenaltyChargesCharged,
                 totalRepaymentExpected, totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap,
                 compoundingMap, unCompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance,
                 outstandingBalanceAsPerRest, installments, recalculationDetails, loanRepaymentScheduleTransactionProcessor,
-                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation);
+                scheduleTillDate, partialUpdate, currency, applyInterestRecalculation, mc);
     }
 
     public int getPeriodNumber() {
@@ -288,7 +292,7 @@ public final class LoanScheduleParams {
 
     public void addTotalCumulativePrincipal(final Money totalCumulativePrincipal) {
         if (this.totalCumulativePrincipal != null) {
-            this.totalCumulativePrincipal = this.totalCumulativePrincipal.plus(totalCumulativePrincipal);
+            this.totalCumulativePrincipal = this.totalCumulativePrincipal.plus(totalCumulativePrincipal, mc);
         } else {
             this.totalCumulativePrincipal = totalCumulativePrincipal;
         }
@@ -300,7 +304,7 @@ public final class LoanScheduleParams {
 
     public void addTotalCumulativeInterest(final Money totalCumulativeInterest) {
         if (this.totalCumulativeInterest != null) {
-            this.totalCumulativeInterest = this.totalCumulativeInterest.plus(totalCumulativeInterest);
+            this.totalCumulativeInterest = this.totalCumulativeInterest.plus(totalCumulativeInterest, mc);
         } else {
             this.totalCumulativeInterest = totalCumulativeInterest;
         }
@@ -312,7 +316,7 @@ public final class LoanScheduleParams {
 
     public void addTotalFeeChargesCharged(final Money totalFeeChargesCharged) {
         if (this.totalFeeChargesCharged != null) {
-            this.totalFeeChargesCharged = this.totalFeeChargesCharged.plus(totalFeeChargesCharged);
+            this.totalFeeChargesCharged = this.totalFeeChargesCharged.plus(totalFeeChargesCharged, mc);
         } else {
             this.totalFeeChargesCharged = totalFeeChargesCharged;
         }
@@ -324,7 +328,7 @@ public final class LoanScheduleParams {
 
     public void addTotalPenaltyChargesCharged(final Money totalPenaltyChargesCharged) {
         if (this.totalPenaltyChargesCharged != null) {
-            this.totalPenaltyChargesCharged = this.totalPenaltyChargesCharged.plus(totalPenaltyChargesCharged);
+            this.totalPenaltyChargesCharged = this.totalPenaltyChargesCharged.plus(totalPenaltyChargesCharged, mc);
         } else {
             this.totalPenaltyChargesCharged = totalPenaltyChargesCharged;
         }
@@ -336,7 +340,7 @@ public final class LoanScheduleParams {
 
     public void addTotalRepaymentExpected(final Money totalRepaymentExpected) {
         if (this.totalRepaymentExpected != null) {
-            this.totalRepaymentExpected = this.totalRepaymentExpected.plus(totalRepaymentExpected);
+            this.totalRepaymentExpected = this.totalRepaymentExpected.plus(totalRepaymentExpected, mc);
         } else {
             this.totalRepaymentExpected = totalRepaymentExpected;
         }
@@ -428,7 +432,7 @@ public final class LoanScheduleParams {
 
     public void addReducePrincipal(Money reducePrincipal) {
         if (this.reducePrincipal != null) {
-            this.reducePrincipal = this.reducePrincipal.plus(reducePrincipal);
+            this.reducePrincipal = this.reducePrincipal.plus(reducePrincipal, mc);
         } else {
             this.reducePrincipal = reducePrincipal;
         }
@@ -436,13 +440,13 @@ public final class LoanScheduleParams {
 
     public void reduceReducePrincipal(Money reducePrincipal) {
         if (this.reducePrincipal != null) {
-            this.reducePrincipal = this.reducePrincipal.minus(reducePrincipal);
+            this.reducePrincipal = this.reducePrincipal.minus(reducePrincipal, mc);
         }
     }
 
     public void addPrincipalToBeScheduled(Money principalToBeScheduled) {
         if (this.principalToBeScheduled != null) {
-            this.principalToBeScheduled = this.principalToBeScheduled.plus(principalToBeScheduled);
+            this.principalToBeScheduled = this.principalToBeScheduled.plus(principalToBeScheduled, mc);
         } else {
             this.principalToBeScheduled = principalToBeScheduled;
         }
@@ -450,7 +454,7 @@ public final class LoanScheduleParams {
 
     public void addOutstandingBalance(Money outstandingBalance) {
         if (this.outstandingBalance != null) {
-            this.outstandingBalance = this.outstandingBalance.plus(outstandingBalance);
+            this.outstandingBalance = this.outstandingBalance.plus(outstandingBalance, mc);
         } else {
             this.outstandingBalance = outstandingBalance;
         }
@@ -458,13 +462,13 @@ public final class LoanScheduleParams {
 
     public void reduceOutstandingBalance(Money outstandingBalance) {
         if (this.outstandingBalance != null) {
-            this.outstandingBalance = this.outstandingBalance.minus(outstandingBalance);
+            this.outstandingBalance = this.outstandingBalance.minus(outstandingBalance, mc);
         }
     }
 
     public void addOutstandingBalanceAsPerRest(Money outstandingBalanceAsPerRest) {
         if (this.outstandingBalanceAsPerRest != null) {
-            this.outstandingBalanceAsPerRest = this.outstandingBalanceAsPerRest.plus(outstandingBalanceAsPerRest);
+            this.outstandingBalanceAsPerRest = this.outstandingBalanceAsPerRest.plus(outstandingBalanceAsPerRest, mc);
         } else {
             this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
         }
@@ -472,7 +476,7 @@ public final class LoanScheduleParams {
 
     public void reduceOutstandingBalanceAsPerRest(Money outstandingBalanceAsPerRest) {
         if (this.outstandingBalanceAsPerRest != null) {
-            this.outstandingBalanceAsPerRest = this.outstandingBalanceAsPerRest.minus(outstandingBalanceAsPerRest);
+            this.outstandingBalanceAsPerRest = this.outstandingBalanceAsPerRest.minus(outstandingBalanceAsPerRest, mc);
         }
     }
 
@@ -522,7 +526,7 @@ public final class LoanScheduleParams {
 
     public void minusUnCompoundedAmount(Money unCompoundedAmount) {
         if (this.unCompoundedAmount != null) {
-            this.unCompoundedAmount = this.unCompoundedAmount.minus(unCompoundedAmount);
+            this.unCompoundedAmount = this.unCompoundedAmount.minus(unCompoundedAmount, mc);
         }
     }
 
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
index b891ace31..2d6382b55 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
@@ -94,10 +94,10 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
                 : loanApplicationTerms.getSubmittedOnDate();
         if (loanScheduleParams == null) {
             scheduleParams = LoanScheduleParams.createLoanScheduleParams(currency, Money.of(currency, chargesDueAtTimeOfDisbursement),
-                    periodStartDate, getPrincipalToBeScheduled(loanApplicationTerms));
+                    periodStartDate, getPrincipalToBeScheduled(loanApplicationTerms), mc);
         } else if (!loanScheduleParams.isPartialUpdate()) {
             scheduleParams = LoanScheduleParams.createLoanScheduleParams(currency, Money.of(currency, chargesDueAtTimeOfDisbursement),
-                    periodStartDate, getPrincipalToBeScheduled(loanApplicationTerms), loanScheduleParams);
+                    periodStartDate, getPrincipalToBeScheduled(loanApplicationTerms), loanScheduleParams, mc);
         } else {
             scheduleParams = loanScheduleParams;
         }
@@ -345,7 +345,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
                     scheduleParams.getPeriodStartDate(), scheduledDueDate, currentPeriodParams.getPrincipalForThisPeriod(),
                     scheduleParams.getOutstandingBalance(), currentPeriodParams.getInterestForThisPeriod(),
                     currentPeriodParams.getFeeChargesForInstallment(), currentPeriodParams.getPenaltyChargesForInstallment(),
-                    totalInstallmentDue, !isCompletePeriod);
+                    totalInstallmentDue, !isCompletePeriod, mc);
             if (principalInterestForThisPeriod.getRescheduleInterestPortion() != null) {
                 installment.setRescheduleInterestPortion(principalInterestForThisPeriod.getRescheduleInterestPortion().getAmount());
             }
@@ -651,7 +651,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
                         scheduleParams.getPeriodStartDate(), transactionDate, currentPeriodParams.getPrincipalForThisPeriod(),
                         scheduleParams.getOutstandingBalance(), currentPeriodParams.getInterestForThisPeriod(),
                         currentPeriodParams.getFeeChargesForInstallment(), currentPeriodParams.getPenaltyChargesForInstallment(),
-                        currentPeriodParams.fetchTotalAmountForPeriod(), false);
+                        currentPeriodParams.fetchTotalAmountForPeriod(), false, mc);
                 scheduleParams.setTotalOutstandingInterestPaymentDueToGrace(interestTillDate.interestPaymentDueToGrace());
             }
         }
@@ -789,7 +789,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
                             installment = LoanScheduleModelRepaymentPeriod.repayment(scheduleParams.getInstalmentNumber(),
                                     scheduleParams.getPeriodStartDate(), transactionDate, principalForThisPeriod,
                                     scheduleParams.getOutstandingBalance(), interestForCurrentInstallment, feeChargesForInstallment,
-                                    penaltyChargesForInstallment, totalInstallmentDue, true);
+                                    penaltyChargesForInstallment, totalInstallmentDue, true, mc);
                             periods.add(installment);
                             addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), installment);
                             updateCompoundingMap(loanApplicationTerms, holidayDetailDTO, scheduleParams, lastRestDate, scheduledDueDate);
@@ -1416,7 +1416,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
                     LoanScheduleModelRepaymentPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(params.getInstalmentNumber(),
                             startDate, transactionDate, totalInterest.zero(), totalInterest.zero(), totalInterest, totalInterest.zero(),
-                            totalInterest.zero(), totalInterest, true);
+                            totalInterest.zero(), totalInterest, true, mc);
                     params.incrementInstalmentNumber();
                     periods.add(installment);
                     totalCumulativeInterest = totalCumulativeInterest.plus(totalInterest);
@@ -1489,7 +1489,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
         if (totalInterest.isGreaterThanZero()) {
             LoanScheduleModelRepaymentPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(params.getInstalmentNumber(),
                     startDate, params.getActualRepaymentDate(), totalInterest.zero(), totalInterest.zero(), totalInterest,
-                    totalInterest.zero(), totalInterest.zero(), totalInterest, true);
+                    totalInterest.zero(), totalInterest.zero(), totalInterest, true, mc);
             params.incrementInstalmentNumber();
             periods.add(installment);
             params.getCompoundingDateVariations().put(startDate, new TreeMap<>(params.getCompoundingMap()));
@@ -2189,7 +2189,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
         // for complete schedule generation
         LoanScheduleParams loanScheduleParams = LoanScheduleParams.createLoanScheduleParamsForCompleteUpdate(recalculationDetails,
-                loanRepaymentScheduleTransactionProcessor, scheduleTillDate, applyInterestRecalculation);
+                loanRepaymentScheduleTransactionProcessor, scheduleTillDate, applyInterestRecalculation, mc);
 
         List<LoanScheduleModelPeriod> periods = new ArrayList<>();
         final List<LoanRepaymentScheduleInstallment> retainedInstallments = new ArrayList<>();
@@ -2402,7 +2402,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
                 installment.resetDerivedComponents();
                 newRepaymentScheduleInstallments.add(installment);
                 outstandingBalance = outstandingBalance.minus(installment.getPrincipal(currency));
-                final LoanScheduleModelPeriod loanScheduleModelPeriod = createLoanScheduleModelPeriod(installment, outstandingBalance);
+                final LoanScheduleModelPeriod loanScheduleModelPeriod = createLoanScheduleModelPeriod(installment, outstandingBalance, mc);
                 periods.add(loanScheduleModelPeriod);
                 totalCumulativePrincipal = totalCumulativePrincipal.plus(installment.getPrincipal(currency));
                 totalCumulativeInterest = totalCumulativeInterest.plus(installment.getInterestCharged(currency));
@@ -2493,7 +2493,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
                         totalOutstandingInterestPaymentDueToGrace, reducePrincipal, principalPortionMap, latePaymentMap, compoundingMap,
                         uncompoundedAmount, disburseDetailMap, principalToBeScheduled, outstandingBalance, outstandingBalanceAsPerRest,
                         newRepaymentScheduleInstallments, recalculationDetails, loanRepaymentScheduleTransactionProcessor, scheduleTillDate,
-                        currency, applyInterestRecalculation);
+                        currency, applyInterestRecalculation, mc);
                 retainedInstallments.addAll(newRepaymentScheduleInstallments);
                 loanScheduleParams.getCompoundingDateVariations().putAll(compoundingDateVariations);
                 loanApplicationTerms.updateTotalInterestDue(Money.of(currency, loan.getSummary().getTotalInterestCharged()));
@@ -2729,13 +2729,13 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
     }
 
     private LoanScheduleModelPeriod createLoanScheduleModelPeriod(final LoanRepaymentScheduleInstallment installment,
-            final Money outstandingPrincipal) {
+            final Money outstandingPrincipal, final MathContext mc) {
         final MonetaryCurrency currency = outstandingPrincipal.getCurrency();
         return LoanScheduleModelRepaymentPeriod.repayment(installment.getInstallmentNumber(), installment.getFromDate(),
                 installment.getDueDate(), installment.getPrincipal(currency), outstandingPrincipal,
                 installment.getInterestCharged(currency), installment.getFeeChargesCharged(currency),
-                installment.getPenaltyChargesCharged(currency), installment.getDue(currency),
-                installment.isRecalculatedInterestComponent());
+                installment.getPenaltyChargesCharged(currency), installment.getDue(currency), installment.isRecalculatedInterestComponent(),
+                mc);
     }
 
     private LocalDate getNextRestScheduleDate(LocalDate startDate, LoanApplicationTerms loanApplicationTerms,
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
similarity index 90%
rename from fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
rename to fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
index eb077751e..c0e9f4d9b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGenerator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
@@ -45,9 +46,9 @@ import org.springframework.stereotype.Component;
 public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
 
     @Override
-    public List<LoanScheduleModelRepaymentPeriod> generateRepaymentPeriods(final LocalDate scheduleStartDate,
+    public List<LoanScheduleModelRepaymentPeriod> generateRepaymentPeriods(final MathContext mc, final LocalDate scheduleStartDate,
             final LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO) {
-        final Money zeroAmount = Money.zero(loanApplicationTerms.getCurrency());
+        final Money zeroAmount = Money.zero(loanApplicationTerms.getCurrency(), mc);
         final int numberOfRepayments = loanApplicationTerms.getNumberOfRepayments();
         final ArrayList<LoanScheduleModelRepaymentPeriod> repaymentPeriods = new ArrayList<>(numberOfRepayments);
         LocalDate lastRepaymentDate = scheduleStartDate;
@@ -65,7 +66,7 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
             }
             nextRepaymentDate = applyLoanTermVariations(loanApplicationTerms, nextRepaymentDate);
             repaymentPeriods.add(LoanScheduleModelRepaymentPeriod.repayment(repaymentPeriodNumber, lastRepaymentDate, nextRepaymentDate,
-                    zeroAmount, zeroAmount, zeroAmount, zeroAmount, zeroAmount, zeroAmount, false));
+                    zeroAmount, zeroAmount, zeroAmount, zeroAmount, zeroAmount, zeroAmount, false, mc));
             lastRepaymentDate = nextRepaymentDate;
             isFirstRepayment = false;
         }
@@ -75,11 +76,13 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
     private LocalDate applyLoanTermVariations(final LoanApplicationTerms loanApplicationTerms, final LocalDate scheduledDueDate) {
         LocalDate modifiedScheduledDueDate = scheduledDueDate;
         // due date changes should be applied only for that dueDate
-        if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) {
-            LoanTermVariationsData loanTermVariationsData = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
-            if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) {
-                modifiedScheduledDueDate = loanTermVariationsData.getDateValue();
-                loanApplicationTerms.updateVariationDays(DateUtils.getDifferenceInDays(scheduledDueDate, modifiedScheduledDueDate));
+        if (loanApplicationTerms.getLoanTermVariations() != null) {
+            if (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(scheduledDueDate)) {
+                LoanTermVariationsData loanTermVariationsData = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation();
+                if (DateUtils.isEqual(modifiedScheduledDueDate, loanTermVariationsData.getTermVariationApplicableFrom())) {
+                    modifiedScheduledDueDate = loanTermVariationsData.getDateValue();
+                    loanApplicationTerms.updateVariationDays(DateUtils.getDifferenceInDays(scheduledDueDate, modifiedScheduledDueDate));
+                }
             }
         }
         return modifiedScheduledDueDate;
@@ -197,28 +200,30 @@ public class DefaultScheduledDateGenerator implements ScheduledDateGenerator {
     private AdjustedDateDetailsDTO recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(
             final AdjustedDateDetailsDTO adjustedDateDetailsDTO, final LoanApplicationTerms loanApplicationTerms,
             final HolidayDetailDTO holidayDetailDTO, final boolean isFirstRepayment) {
-        final Recur recur = CalendarUtils.getICalRecur(holidayDetailDTO.getWorkingDays().getRecurrence());
-        final boolean isSevenDaysWeek = (recur.getDayList().size() == 7); // 7 Seven days in the week
-        // If Workings days are not seven day week
-        if (!isSevenDaysWeek) {
-            checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
+        if (holidayDetailDTO != null) {
+            final Recur recur = CalendarUtils.getICalRecur(holidayDetailDTO.getWorkingDays().getRecurrence());
+            final boolean isSevenDaysWeek = (recur.getDayList().size() == 7); // 7 Seven days in the week
+            // If Workings days are not seven day week
+            if (!isSevenDaysWeek) {
+                checkAndUpdateWorkingDayIfRepaymentDateIsNonWorkingDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
+                        isFirstRepayment);
+            }
+            // Check Holidays If applied
+            checkAndUpdateWorkingDayIfRepaymentDateIsHolidayDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
                     isFirstRepayment);
-        }
-        // Check Holidays If applied
-        checkAndUpdateWorkingDayIfRepaymentDateIsHolidayDay(adjustedDateDetailsDTO, holidayDetailDTO, loanApplicationTerms,
-                isFirstRepayment);
-
-        /**
-         * Check Changed Schedule Date is holiday or is not a working day Then re-call this method to get the non
-         * holiday and working day
-         */
-        if ((holidayDetailDTO.isHolidayEnabled() && HolidayUtil.getApplicableHoliday(adjustedDateDetailsDTO.getChangedScheduleDate(),
-                holidayDetailDTO.getHolidays()) != null)
-                || WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(), adjustedDateDetailsDTO.getChangedScheduleDate())) {
-            recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(adjustedDateDetailsDTO,
-                    loanApplicationTerms, holidayDetailDTO, isFirstRepayment);
-        }
 
+            /**
+             * Check Changed Schedule Date is holiday or is not a working day Then re-call this method to get the non
+             * holiday and working day
+             */
+            if ((holidayDetailDTO.isHolidayEnabled() && HolidayUtil.getApplicableHoliday(adjustedDateDetailsDTO.getChangedScheduleDate(),
+                    holidayDetailDTO.getHolidays()) != null)
+                    || WorkingDaysUtil.isNonWorkingDay(holidayDetailDTO.getWorkingDays(),
+                            adjustedDateDetailsDTO.getChangedScheduleDate())) {
+                recursivelyCheckNonWorkingDaysAndHolidaysAndWorkingDaysExemptionToGenerateNextRepaymentPeriodDate(adjustedDateDetailsDTO,
+                        loanApplicationTerms, holidayDetailDTO, isFirstRepayment);
+            }
+        }
         return adjustedDateDetailsDTO;
     }
 
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index 8f13670bc..e4fb8fd2b 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -249,6 +249,8 @@ public final class LoanApplicationTerms {
         this.inArrearsTolerance = builder.inArrearsTolerance;
         this.disbursementDatas = builder.disbursementDatas;
         this.downPaymentAmount = builder.downPaymentAmount;
+        this.submittedOnDate = builder.submittedOnDate;
+        this.seedDate = builder.seedDate;
     }
 
     public static class Builder {
@@ -272,6 +274,8 @@ public final class LoanApplicationTerms {
         private Money inArrearsTolerance;
         private List<DisbursementData> disbursementDatas;
         private Money downPaymentAmount;
+        private LocalDate submittedOnDate;
+        private LocalDate seedDate;
 
         public Builder currency(ApplicationCurrency currency) {
             this.currency = currency;
@@ -343,11 +347,6 @@ public final class LoanApplicationTerms {
             return this;
         }
 
-        public Builder variationsDataWrapper(LoanTermVariationsDataWrapper variationsDataWrapper) {
-            this.variationsDataWrapper = variationsDataWrapper;
-            return this;
-        }
-
         public Builder fixedLength(Integer fixedLength) {
             this.fixedLength = fixedLength;
             return this;
@@ -368,23 +367,41 @@ public final class LoanApplicationTerms {
             return this;
         }
 
+        public Builder submittedOnDate(LocalDate submittedOnDate) {
+            this.submittedOnDate = submittedOnDate;
+            return this;
+        }
+
+        public Builder seedDate(LocalDate seedDate) {
+            this.seedDate = seedDate;
+            return this;
+        }
+
         public LoanApplicationTerms build() {
             return new LoanApplicationTerms(this);
         }
     }
 
-    public static LoanApplicationTerms assembleFrom(LoanRepaymentScheduleModelData modelData) {
-        Money principal = Money.of(modelData.currency().toData(), modelData.disbursementAmount());
-        Money downPaymentAmount = Money.zero(modelData.currency().toData());
+    public static LoanApplicationTerms assembleFrom(LoanRepaymentScheduleModelData modelData, MathContext mc) {
+        Money principal = Money.of(modelData.currency().toData(), modelData.disbursementAmount(), mc);
+        Money downPaymentAmount = Money.zero(modelData.currency().toData(), mc);
 
         if (modelData.downPaymentEnabled()) {
             downPaymentAmount = Money.of(modelData.currency().toData(),
-                    MathUtil.percentageOf(principal.getAmount(), modelData.disbursementAmount(), 19));
+                    MathUtil.percentageOf(principal.getAmount(), modelData.disbursementAmount(), mc), mc);
             if (modelData.installmentAmountInMultiplesOf() != null) {
-                downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, modelData.installmentAmountInMultiplesOf());
+                downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, modelData.installmentAmountInMultiplesOf(), mc);
             }
         }
 
+        LocalDate seedDate;
+
+        if (modelData.disbursementDate() != null) {
+            seedDate = modelData.disbursementDate();
+        } else {
+            seedDate = modelData.scheduleGenerationStartDate();
+        }
+
         return new Builder().currency(modelData.currency()).loanTermFrequency(modelData.numberOfRepayments())
                 .loanTermPeriodFrequencyType(PeriodFrequencyType.valueOf(modelData.repaymentFrequencyType()))
                 .numberOfRepayments(modelData.numberOfRepayments()).repaymentEvery(modelData.repaymentFrequency())
@@ -394,8 +411,8 @@ public final class LoanApplicationTerms {
                 .annualNominalInterestRate(modelData.annualNominalInterestRate()).principal(principal)
                 .expectedDisbursementDate(modelData.disbursementDate()).repaymentsStartingFromDate(modelData.scheduleGenerationStartDate())
                 .daysInMonthType(modelData.daysInMonth()).daysInYearType(modelData.daysInYear()).fixedLength(modelData.fixedLength())
-                .inArrearsTolerance(Money.zero(modelData.currency().toData())).disbursementDatas(new ArrayList<>())
-                .downPaymentAmount(downPaymentAmount).build();
+                .inArrearsTolerance(Money.zero(modelData.currency().toData(), mc)).disbursementDatas(new ArrayList<>())
+                .downPaymentAmount(downPaymentAmount).submittedOnDate(modelData.scheduleGenerationStartDate()).seedDate(seedDate).build();
     }
 
     public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
index fd848751e..4460cfe8d 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleModelRepaymentPeriod.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.util.HashSet;
 import java.util.Set;
@@ -46,18 +47,20 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel
     private final Set<LoanInterestRecalcualtionAdditionalDetails> loanCompoundingDetails = new HashSet<>();
     private boolean isEMIFixedSpecificToInstallment = false;
     BigDecimal rescheduleInterestPortion;
+    private final MathContext mc;
 
     public static LoanScheduleModelRepaymentPeriod repayment(final int periodNumber, final LocalDate startDate,
             final LocalDate scheduledDueDate, final Money principalDue, final Money outstandingLoanBalance, final Money interestDue,
-            final Money feeChargesDue, final Money penaltyChargesDue, final Money totalDue, boolean recalculatedInterestComponent) {
+            final Money feeChargesDue, final Money penaltyChargesDue, final Money totalDue, boolean recalculatedInterestComponent,
+            final MathContext mc) {
 
         return new LoanScheduleModelRepaymentPeriod(periodNumber, startDate, scheduledDueDate, principalDue, outstandingLoanBalance,
-                interestDue, feeChargesDue, penaltyChargesDue, totalDue, recalculatedInterestComponent);
+                interestDue, feeChargesDue, penaltyChargesDue, totalDue, recalculatedInterestComponent, mc);
     }
 
     public LoanScheduleModelRepaymentPeriod(final int periodNumber, final LocalDate fromDate, final LocalDate dueDate,
             final Money principalDue, final Money outstandingLoanBalance, final Money interestDue, final Money feeChargesDue,
-            final Money penaltyChargesDue, final Money totalDue, final boolean recalculatedInterestComponent) {
+            final Money penaltyChargesDue, final Money totalDue, final boolean recalculatedInterestComponent, final MathContext mc) {
         this.periodNumber = periodNumber;
         this.fromDate = fromDate;
         this.dueDate = dueDate;
@@ -68,6 +71,7 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel
         this.penaltyChargesDue = penaltyChargesDue;
         this.totalDue = totalDue;
         this.recalculatedInterestComponent = recalculatedInterestComponent;
+        this.mc = mc;
     }
 
     @Override
@@ -144,15 +148,15 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel
 
     @Override
     public void addLoanCharges(BigDecimal feeCharge, BigDecimal penaltyCharge) {
-        this.feeChargesDue = this.feeChargesDue.plus(feeCharge);
-        this.penaltyChargesDue = this.penaltyChargesDue.plus(penaltyCharge);
-        this.totalDue = this.totalDue.plus(feeCharge).plus(penaltyCharge);
+        this.feeChargesDue = this.feeChargesDue.plus(feeCharge, mc);
+        this.penaltyChargesDue = this.penaltyChargesDue.plus(penaltyCharge, mc);
+        this.totalDue = this.totalDue.plus(feeCharge, mc).plus(penaltyCharge, mc);
     }
 
     @Override
     public void addPrincipalAmount(final Money principalDue) {
-        this.principalDue = this.principalDue.plus(principalDue);
-        this.totalDue = this.totalDue.plus(principalDue);
+        this.principalDue = this.principalDue.plus(principalDue, mc);
+        this.totalDue = this.totalDue.plus(principalDue, mc);
     }
 
     @Override
@@ -162,8 +166,8 @@ public final class LoanScheduleModelRepaymentPeriod implements LoanScheduleModel
 
     @Override
     public void addInterestAmount(Money interestDue) {
-        this.interestDue = this.interestDue.plus(interestDue);
-        this.totalDue = this.totalDue.plus(interestDue);
+        this.interestDue = this.interestDue.plus(interestDue, mc);
+        this.totalDue = this.totalDue.plus(interestDue, mc);
     }
 
     public void setPeriodNumber(int periodNumber) {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
index fd5e824e8..16ceae371 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ScheduledDateGenerator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.util.List;
 import org.apache.fineract.organisation.workingdays.data.AdjustedDateDetailsDTO;
@@ -27,8 +28,8 @@ import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
 
 public interface ScheduledDateGenerator {
 
-    List<LoanScheduleModelRepaymentPeriod> generateRepaymentPeriods(LocalDate scheduledDueDate, LoanApplicationTerms loanApplicationTerms,
-            HolidayDetailDTO holidayDetailDTO);
+    List<LoanScheduleModelRepaymentPeriod> generateRepaymentPeriods(MathContext mc, LocalDate scheduledDueDate,
+            LoanApplicationTerms loanApplicationTerms, HolidayDetailDTO holidayDetailDTO);
 
     LocalDate getLastRepaymentDate(LoanApplicationTerms loanApplicationTerms, HolidayDetailDTO holidayDetailDTO);
 
diff --git a/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapperTest.java b/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapperTest.java
index ada2be619..c1eb1ad8b 100644
--- a/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapperTest.java
+++ b/fineract-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/SingleLoanChargeRepaymentScheduleProcessingWrapperTest.java
@@ -24,6 +24,7 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.HashMap;
@@ -64,6 +65,7 @@ public class SingleLoanChargeRepaymentScheduleProcessingWrapperTest {
     @BeforeAll
     public static void init() {
         MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
+        MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
     }
 
     @Test
@@ -142,11 +144,12 @@ public class SingleLoanChargeRepaymentScheduleProcessingWrapperTest {
     @NotNull
     private LoanRepaymentScheduleInstallment createPeriod(int periodId, LocalDate start, LocalDate end) {
         LoanRepaymentScheduleInstallment period = Mockito.mock(LoanRepaymentScheduleInstallment.class);
+        MathContext mc = new MathContext(12, RoundingMode.HALF_EVEN);
         Mockito.when(period.getInstallmentNumber()).thenReturn(periodId);
         Mockito.when(period.getFromDate()).thenReturn(start);
         Mockito.when(period.getDueDate()).thenReturn(end);
-        Money principal = Money.of(currency, new BigDecimal("1000.0"));
-        Money interest = Money.of(currency, BigDecimal.ZERO);
+        Money principal = Money.of(currency, new BigDecimal("1000.0"), mc);
+        Money interest = Money.of(currency, BigDecimal.ZERO, mc);
 
         Mockito.when(period.getPrincipal(eq(currency))).thenReturn(principal);
         Mockito.when(period.getInterestCharged(eq(currency))).thenReturn(interest);
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index 7499fccaa..6375353af 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -176,7 +176,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
         final Integer installmentAmountInMultiplesOf = loan.getLoanProduct().getInstallmentAmountInMultiplesOf();
         final LoanProductRelatedDetail loanProductRelatedDetail = loan.getLoanRepaymentScheduleDetail();
         ProgressiveLoanInterestScheduleModel scheduleModel = emiCalculator.generateModel(loanProductRelatedDetail,
-                installmentAmountInMultiplesOf, installments);
+                installmentAmountInMultiplesOf, installments, overpaymentHolder.getMoneyObject().getMc());
         ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(currency, installments, charges, overpaymentHolder,
                 changedTransactionDetail, scheduleModel);
 
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/InterestPeriod.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/InterestPeriod.java
index 85366e602..62c79443d 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/InterestPeriod.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/InterestPeriod.java
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.data;
 
 import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.util.Optional;
 import lombok.EqualsAndHashCode;
@@ -44,9 +45,10 @@ public class InterestPeriod implements Comparable<InterestPeriod> {
     private Money disbursementAmount;
     private Money balanceCorrectionAmount;
     private Money outstandingLoanBalance;
+    private final MathContext mc;
 
     public InterestPeriod(RepaymentPeriod repaymentPeriod, LocalDate fromDate, LocalDate dueDate, BigDecimal rateFactor,
-            Money disbursementAmount, Money balanceCorrectionAmount, Money outstandingLoanBalance) {
+            Money disbursementAmount, Money balanceCorrectionAmount, Money outstandingLoanBalance, MathContext mc) {
         this.repaymentPeriod = repaymentPeriod;
         this.fromDate = fromDate;
         this.dueDate = dueDate;
@@ -54,12 +56,13 @@ public class InterestPeriod implements Comparable<InterestPeriod> {
         this.disbursementAmount = disbursementAmount;
         this.balanceCorrectionAmount = balanceCorrectionAmount;
         this.outstandingLoanBalance = outstandingLoanBalance;
+        this.mc = mc;
     }
 
-    public InterestPeriod(RepaymentPeriod repaymentPeriod, InterestPeriod interestPeriod) {
+    public InterestPeriod(RepaymentPeriod repaymentPeriod, InterestPeriod interestPeriod, MathContext mc) {
         this(repaymentPeriod, interestPeriod.getFromDate(), interestPeriod.getDueDate(), interestPeriod.getRateFactor(),
                 interestPeriod.getDisbursementAmount(), interestPeriod.getBalanceCorrectionAmount(),
-                interestPeriod.getOutstandingLoanBalance());
+                interestPeriod.getOutstandingLoanBalance(), mc);
     }
 
     @Override
@@ -72,11 +75,11 @@ public class InterestPeriod implements Comparable<InterestPeriod> {
     }
 
     public void addDisbursementAmount(final Money disbursementAmount) {
-        this.disbursementAmount = MathUtil.plus(this.disbursementAmount, disbursementAmount);
+        this.disbursementAmount = MathUtil.plus(this.disbursementAmount, disbursementAmount, mc);
     }
 
     public Money getCalculatedDueInterest() {
-        return getOutstandingLoanBalance().multipliedBy(getRateFactor());
+        return getOutstandingLoanBalance().multipliedBy(getRateFactor(), mc);
     }
 
     public void updateOutstandingLoanBalance() {
@@ -86,17 +89,17 @@ public class InterestPeriod implements Comparable<InterestPeriod> {
                 InterestPeriod previousInterestPeriod = previousRepaymentPeriod.get().getInterestPeriods()
                         .get(previousRepaymentPeriod.get().getInterestPeriods().size() - 1);
                 this.outstandingLoanBalance = previousInterestPeriod.getOutstandingLoanBalance()//
-                        .plus(previousInterestPeriod.getDisbursementAmount())//
-                        .plus(previousInterestPeriod.getBalanceCorrectionAmount())//
-                        .minus(previousRepaymentPeriod.get().getDuePrincipal())//
-                        .plus(previousRepaymentPeriod.get().getPaidPrincipal());//
+                        .plus(previousInterestPeriod.getDisbursementAmount(), mc)//
+                        .plus(previousInterestPeriod.getBalanceCorrectionAmount(), mc)//
+                        .minus(previousRepaymentPeriod.get().getDuePrincipal(), mc)//
+                        .plus(previousRepaymentPeriod.get().getPaidPrincipal(), mc);//
             }
         } else {
             int index = getRepaymentPeriod().getInterestPeriods().indexOf(this);
             InterestPeriod previousInterestPeriod = getRepaymentPeriod().getInterestPeriods().get(index - 1);
             this.outstandingLoanBalance = previousInterestPeriod.getOutstandingLoanBalance() //
-                    .plus(previousInterestPeriod.getBalanceCorrectionAmount()) //
-                    .plus(previousInterestPeriod.getDisbursementAmount()); //
+                    .plus(previousInterestPeriod.getBalanceCorrectionAmount(), mc) //
+                    .plus(previousInterestPeriod.getDisbursementAmount(), mc); //
         }
     }
 
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
index 45f61c02f..7f51b9db4 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/ProgressiveLoanInterestScheduleModel.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.data;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
@@ -38,33 +39,36 @@ public class ProgressiveLoanInterestScheduleModel {
     private final List<InterestRate> interestRates;
     private final LoanProductRelatedDetail loanProductRelatedDetail;
     private final Integer installmentAmountInMultiplesOf;
+    private MathContext mc;
 
     public ProgressiveLoanInterestScheduleModel(List<RepaymentPeriod> repaymentPeriods, LoanProductRelatedDetail loanProductRelatedDetail,
-            Integer installmentAmountInMultiplesOf) {
+            Integer installmentAmountInMultiplesOf, MathContext mc) {
         this.repaymentPeriods = repaymentPeriods;
         this.interestRates = new ArrayList<>();
         this.loanProductRelatedDetail = loanProductRelatedDetail;
         this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
+        this.mc = mc;
     }
 
     private ProgressiveLoanInterestScheduleModel(List<RepaymentPeriod> repaymentPeriods, final List<InterestRate> interestRates,
-            LoanProductRelatedDetail loanProductRelatedDetail, Integer installmentAmountInMultiplesOf) {
+            LoanProductRelatedDetail loanProductRelatedDetail, Integer installmentAmountInMultiplesOf, MathContext mc) {
+        this.mc = mc;
         this.repaymentPeriods = copyRepaymentPeriods(repaymentPeriods);
         this.interestRates = new ArrayList<>(interestRates);
         this.loanProductRelatedDetail = loanProductRelatedDetail;
         this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
     }
 
-    public ProgressiveLoanInterestScheduleModel deepCopy() {
+    public ProgressiveLoanInterestScheduleModel deepCopy(MathContext mc) {
         return new ProgressiveLoanInterestScheduleModel(repaymentPeriods, interestRates, loanProductRelatedDetail,
-                installmentAmountInMultiplesOf);
+                installmentAmountInMultiplesOf, mc);
     }
 
     private List<RepaymentPeriod> copyRepaymentPeriods(final List<RepaymentPeriod> repaymentPeriods) {
         final List<RepaymentPeriod> repaymentCopies = new ArrayList<>(repaymentPeriods.size());
         RepaymentPeriod previousPeriod = null;
         for (RepaymentPeriod repaymentPeriod : repaymentPeriods) {
-            RepaymentPeriod currentPeriod = new RepaymentPeriod(previousPeriod, repaymentPeriod);
+            RepaymentPeriod currentPeriod = new RepaymentPeriod(previousPeriod, repaymentPeriod, mc);
             previousPeriod = currentPeriod;
             repaymentCopies.add(currentPeriod);
         }
@@ -175,11 +179,11 @@ public class ProgressiveLoanInterestScheduleModel {
         previousInterestPeriod.addDisbursementAmount(disbursedAmount);
         previousInterestPeriod.addBalanceCorrectionAmount(correctionAmount);
         final InterestPeriod interestPeriod = new InterestPeriod(repaymentPeriod, previousInterestPeriod.getDueDate(), originalDueDate,
-                BigDecimal.ZERO, getZero(), getZero(), getZero());
+                BigDecimal.ZERO, getZero(mc), getZero(mc), getZero(mc), mc);
         repaymentPeriod.getInterestPeriods().add(interestPeriod);
     }
 
-    private Money getZero() {
-        return Money.zero(loanProductRelatedDetail.getCurrency());
+    private Money getZero(MathContext mc) {
+        return Money.zero(loanProductRelatedDetail.getCurrency(), mc);
     }
 }
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/RepaymentPeriod.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/RepaymentPeriod.java
index d9ff4e89f..129433527 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/RepaymentPeriod.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/RepaymentPeriod.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.loanaccount.loanschedule.data;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.List;
@@ -54,20 +55,23 @@ public class RepaymentPeriod {
     private Memo<Money> calculatedDueInterestCalculation;
     private Memo<Money> dueInterestCalculation;
     private Memo<Money> outstandingBalanceCalculation;
+    private final MathContext mc;
 
-    public RepaymentPeriod(RepaymentPeriod previous, LocalDate fromDate, LocalDate dueDate, Money emi) {
+    public RepaymentPeriod(RepaymentPeriod previous, LocalDate fromDate, LocalDate dueDate, Money emi, MathContext mc) {
         this.previous = previous;
         this.fromDate = fromDate;
         this.dueDate = dueDate;
         this.emi = emi;
+        this.mc = mc;
         this.interestPeriods = new ArrayList<>();
         // There is always at least 1 interest period, by default with same from-due date as repayment period
-        getInterestPeriods().add(new InterestPeriod(this, getFromDate(), getDueDate(), BigDecimal.ZERO, getZero(), getZero(), getZero()));
-        this.paidInterest = getZero();
-        this.paidPrincipal = getZero();
+        getInterestPeriods()
+                .add(new InterestPeriod(this, getFromDate(), getDueDate(), BigDecimal.ZERO, getZero(mc), getZero(mc), getZero(mc), mc));
+        this.paidInterest = getZero(mc);
+        this.paidPrincipal = getZero(mc);
     }
 
-    public RepaymentPeriod(RepaymentPeriod previous, RepaymentPeriod repaymentPeriod) {
+    public RepaymentPeriod(RepaymentPeriod previous, RepaymentPeriod repaymentPeriod, MathContext mc) {
         this.previous = previous;
         this.fromDate = repaymentPeriod.fromDate;
         this.dueDate = repaymentPeriod.dueDate;
@@ -75,9 +79,10 @@ public class RepaymentPeriod {
         this.interestPeriods = new ArrayList<>();
         this.paidPrincipal = repaymentPeriod.paidPrincipal;
         this.paidInterest = repaymentPeriod.paidInterest;
+        this.mc = mc;
         // There is always at least 1 interest period, by default with same from-due date as repayment period
         for (InterestPeriod interestPeriod : repaymentPeriod.interestPeriods) {
-            interestPeriods.add(new InterestPeriod(this, interestPeriod));
+            interestPeriods.add(new InterestPeriod(this, interestPeriod, mc));
         }
     }
 
@@ -105,21 +110,21 @@ public class RepaymentPeriod {
     }
 
     private Money calculateCalculatedDueInterest() {
-        Money calculatedDueInterest = getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest).reduce(getZero(),
-                Money::plus);
+        Money calculatedDueInterest = getInterestPeriods().stream().map(InterestPeriod::getCalculatedDueInterest).reduce(getZero(mc),
+                (m1, m2) -> m1.plus(m2, mc));
         if (getPrevious().isPresent()) {
-            calculatedDueInterest = calculatedDueInterest.add(getPrevious().get().getUnrecognizedInterest());
+            calculatedDueInterest = calculatedDueInterest.add(getPrevious().get().getUnrecognizedInterest(), mc);
         }
         return calculatedDueInterest;
     }
 
-    private Money getZero() {
+    private Money getZero(MathContext mc) {
         // EMI is always initiated
-        return this.emi.zero();
+        return this.emi.zero(mc);
     }
 
     public Money getCalculatedDuePrincipal() {
-        return getEmi().minus(getCalculatedDueInterest());
+        return getEmi().minus(getCalculatedDueInterest(), mc);
     }
 
     public boolean isFullyPaid() {
@@ -138,11 +143,11 @@ public class RepaymentPeriod {
 
     public Money getDuePrincipal() {
         // Due principal might be the maximum paid if there is pay-off or early repayment
-        return MathUtil.max(getEmi().minus(getDueInterest()), getPaidPrincipal(), false);
+        return MathUtil.max(getEmi().minus(getDueInterest(), mc), getPaidPrincipal(), false);
     }
 
     public Money getUnrecognizedInterest() {
-        return getCalculatedDueInterest().minus(getDueInterest());
+        return getCalculatedDueInterest().minus(getDueInterest(), mc);
     }
 
     public Money getOutstandingLoanBalance() {
@@ -150,22 +155,22 @@ public class RepaymentPeriod {
             outstandingBalanceCalculation = Memo.of(() -> {
                 InterestPeriod lastInstallmentPeriod = getInterestPeriods().get(getInterestPeriods().size() - 1);
                 Money calculatedOutStandingLoanBalance = lastInstallmentPeriod.getOutstandingLoanBalance() //
-                        .plus(lastInstallmentPeriod.getBalanceCorrectionAmount()) //
-                        .plus(lastInstallmentPeriod.getDisbursementAmount()) //
-                        .minus(getDuePrincipal())//
-                        .plus(getPaidPrincipal());//
-                return MathUtil.negativeToZero(calculatedOutStandingLoanBalance);
+                        .plus(lastInstallmentPeriod.getBalanceCorrectionAmount(), mc) //
+                        .plus(lastInstallmentPeriod.getDisbursementAmount(), mc) //
+                        .minus(getDuePrincipal(), mc)//
+                        .plus(getPaidPrincipal(), mc);//
+                return MathUtil.negativeToZero(calculatedOutStandingLoanBalance, mc);
             }, () -> new Object[] { paidPrincipal, paidInterest, interestPeriods });
         }
         return outstandingBalanceCalculation.get();
     }
 
     public void addPaidPrincipalAmount(Money paidPrincipal) {
-        this.paidPrincipal = MathUtil.plus(this.paidPrincipal, paidPrincipal);
+        this.paidPrincipal = MathUtil.plus(this.paidPrincipal, paidPrincipal, mc);
     }
 
     public void addPaidInterestAmount(Money paidInterest) {
-        this.paidInterest = MathUtil.plus(this.paidInterest, paidInterest);
+        this.paidInterest = MathUtil.plus(this.paidInterest, paidInterest, mc);
     }
 
     public Money getInitialBalanceForEmiRecalculation() {
@@ -173,10 +178,10 @@ public class RepaymentPeriod {
         if (getPrevious().isPresent()) {
             initialBalance = getPrevious().get().getOutstandingLoanBalance();
         } else {
-            initialBalance = getZero();
+            initialBalance = getZero(mc);
         }
-        Money totalDisbursedAmount = getInterestPeriods().stream().map(InterestPeriod::getDisbursementAmount).reduce(getZero(),
-                Money::plus);
-        return initialBalance.add(totalDisbursedAmount);
+        Money totalDisbursedAmount = getInterestPeriods().stream().map(InterestPeriod::getDisbursementAmount).reduce(getZero(mc),
+                (m1, m2) -> m1.plus(m2, mc));
+        return initialBalance.add(totalDisbursedAmount, mc);
     }
 }
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
index 2de29d2c9..e4382e54d 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
@@ -87,17 +87,17 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
                 : loanApplicationTerms.getSubmittedOnDate();
 
         final LoanScheduleParams scheduleParams = LoanScheduleParams.createLoanScheduleParams(currency,
-                Money.of(currency, chargesDueAtTimeOfDisbursement), periodStartDate, Money.zero(currency));
+                Money.of(currency, chargesDueAtTimeOfDisbursement, mc), periodStartDate, Money.zero(currency, mc), mc);
 
         // charges which depends on total loan interest will be added to this
         // set and handled separately after all installments generated
         final Set<LoanCharge> nonCompoundingCharges = separateTotalCompoundingPercentageCharges(loanCharges);
 
-        final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator
-                .generateRepaymentPeriods(periodStartDate, loanApplicationTerms, holidayDetailDTO);
+        final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = scheduledDateGenerator.generateRepaymentPeriods(mc,
+                periodStartDate, loanApplicationTerms, holidayDetailDTO);
         final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator.generateInterestScheduleModel(
                 expectedRepaymentPeriods, loanApplicationTerms.toLoanProductRelatedDetail(),
-                loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+                loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
         final List<LoanScheduleModelPeriod> periods = new ArrayList<>(expectedRepaymentPeriods.size());
 
         prepareDisbursementsOnLoanApplicationTerms(loanApplicationTerms);
@@ -110,7 +110,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
             scheduleParams.setActualRepaymentDate(repaymentPeriod.getDueDate());
 
             processDisbursements(loanApplicationTerms, disbursementDataList, scheduleParams, interestScheduleModel, periods,
-                    chargesDueAtTimeOfDisbursement, false);
+                    chargesDueAtTimeOfDisbursement, false, mc);
             repaymentPeriod.setPeriodNumber(scheduleParams.getInstalmentNumber());
 
             if (loanApplicationTerms.getLoanTermVariations() != null) {
@@ -135,7 +135,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
                 scheduleParams.addTotalCumulativePrincipal(principalDue);
                 scheduleParams.addTotalCumulativeInterest(interestDue);
                 // add everything
-                scheduleParams.addTotalRepaymentExpected(principalDue.plus(interestDue));
+                scheduleParams.addTotalRepaymentExpected(principalDue.plus(interestDue, mc));
             });
 
             applyChargesForCurrentPeriod(repaymentPeriod, loanCharges, scheduleParams, currency, mc);
@@ -147,7 +147,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
 
         if (loanApplicationTerms.isMultiDisburseLoan()) {
             processDisbursements(loanApplicationTerms, disbursementDataList, scheduleParams, interestScheduleModel, periods,
-                    chargesDueAtTimeOfDisbursement, true);
+                    chargesDueAtTimeOfDisbursement, true, mc);
         }
 
         // determine fees and penalties for charges which depends on total
@@ -158,8 +158,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
         final BigDecimal totalOutstanding = BigDecimal.ZERO;
 
         return LoanScheduleModel.from(periods, applicationCurrency, interestScheduleModel.getLoanTermInDays(),
-                scheduleParams.getPrincipalToBeScheduled().plus(loanApplicationTerms.getDownPaymentAmount()),
-                scheduleParams.getTotalCumulativePrincipal().plus(loanApplicationTerms.getDownPaymentAmount()).getAmount(),
+                scheduleParams.getPrincipalToBeScheduled().plus(loanApplicationTerms.getDownPaymentAmount(), mc),
+                scheduleParams.getTotalCumulativePrincipal().plus(loanApplicationTerms.getDownPaymentAmount(), mc).getAmount(),
                 totalPrincipalPaid, scheduleParams.getTotalCumulativeInterest().getAmount(),
                 scheduleParams.getTotalFeeChargesCharged().getAmount(), scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
                 scheduleParams.getTotalRepaymentExpected().getAmount(), totalOutstanding);
@@ -167,7 +167,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
 
     public LoanScheduleModel generate(final MathContext mc, final LoanRepaymentScheduleModelData modelData) {
 
-        LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(modelData);
+        LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(modelData, mc);
 
         return generate(mc, loanApplicationTerms, null, null);
     }
@@ -184,7 +184,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
     private void processDisbursements(final LoanApplicationTerms loanApplicationTerms,
             final ArrayList<DisbursementData> disbursementDataList, final LoanScheduleParams scheduleParams,
             final ProgressiveLoanInterestScheduleModel interestScheduleModel, final List<LoanScheduleModelPeriod> periods,
-            final BigDecimal chargesDueAtTimeOfDisbursement, final boolean includeDisbursementsAfterMaturityDate) {
+            final BigDecimal chargesDueAtTimeOfDisbursement, final boolean includeDisbursementsAfterMaturityDate, final MathContext mc) {
 
         for (DisbursementData disbursementData : disbursementDataList) {
             final LocalDate disbursementDate = disbursementData.disbursementDate();
@@ -202,7 +202,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
 
             Money outstandingBalance = emiCalculator.getOutstandingLoanBalance(interestScheduleModel, periodDueDate, disbursementDate);
 
-            final Money disbursedAmount = Money.of(loanApplicationTerms.getCurrency(), disbursementData.getPrincipal());
+            final Money disbursedAmount = Money.of(loanApplicationTerms.getCurrency(), disbursementData.getPrincipal(), mc);
             final LoanScheduleModelDisbursementPeriod disbursementPeriod = LoanScheduleModelDisbursementPeriod
                     .disbursement(disbursementData.disbursementDate(), disbursedAmount, chargesDueAtTimeOfDisbursement);
             periods.add(disbursementPeriod);
@@ -218,7 +218,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
                 }
             }
 
-            Money downPaymentAmount = Money.zero(loanApplicationTerms.getCurrency());
+            Money downPaymentAmount = Money.zero(loanApplicationTerms.getCurrency(), mc);
             if (loanApplicationTerms.isDownPaymentEnabled()) {
                 downPaymentAmount = Money.of(loanApplicationTerms.getCurrency(), MathUtil.percentageOf(disbursedAmount.getAmount(),
                         loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
@@ -321,7 +321,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
             final MonetaryCurrency monetaryCurrency, final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
             final Money totalInterestChargedForFullLoanTerm, boolean isInstallmentChargeApplicable, final boolean isFirstPeriod,
             final MathContext mc) {
-        Money cumulative = Money.zero(monetaryCurrency);
+        Money cumulative = Money.zero(monetaryCurrency, mc);
         if (loanCharges != null) {
             for (final LoanCharge loanCharge : loanCharges) {
                 if (!loanCharge.isDueAtDisbursement() && loanCharge.isFeeCharge()) {
@@ -356,7 +356,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
             final PrincipalInterest principalInterestForThisPeriod, final Money principalDisbursed,
             final Money totalInterestChargedForFullLoanTerm, boolean isInstallmentChargeApplicable, final boolean isFirstPeriod,
             final MathContext mc) {
-        Money cumulative = Money.zero(monetaryCurrency);
+        Money cumulative = Money.zero(monetaryCurrency, mc);
         if (loanCharges != null) {
             for (final LoanCharge loanCharge : loanCharges) {
                 if (loanCharge.isPenaltyCharge()) {
@@ -407,8 +407,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
             final Collection<LoanScheduleModelPeriod> periods, final Set<LoanCharge> nonCompoundingCharges, MathContext mc) {
         for (LoanScheduleModelPeriod loanScheduleModelPeriod : periods) {
             if (loanScheduleModelPeriod.isRepaymentPeriod()) {
-                PrincipalInterest principalInterest = new PrincipalInterest(Money.of(currency, loanScheduleModelPeriod.principalDue()),
-                        Money.of(currency, loanScheduleModelPeriod.interestDue()), null);
+                PrincipalInterest principalInterest = new PrincipalInterest(Money.of(currency, loanScheduleModelPeriod.principalDue(), mc),
+                        Money.of(currency, loanScheduleModelPeriod.interestDue(), mc), null);
                 Money feeChargesForInstallment = cumulativeFeeChargesDueWithin(loanScheduleModelPeriod.periodFromDate(),
                         loanScheduleModelPeriod.periodDueDate(), nonCompoundingCharges, currency, principalInterest,
                         scheduleParams.getPrincipalToBeScheduled(), scheduleParams.getTotalCumulativeInterest(),
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
index 157989912..ac10aeab3 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.loanproduct.calc;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.util.List;
 import java.util.Optional;
@@ -33,10 +34,10 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail
 public interface EMICalculator {
 
     ProgressiveLoanInterestScheduleModel generateInterestScheduleModel(List<LoanScheduleModelRepaymentPeriod> periods,
-            LoanProductRelatedDetail loanProductRelatedDetail, Integer installmentAmountInMultiplesOf);
+            LoanProductRelatedDetail loanProductRelatedDetail, Integer installmentAmountInMultiplesOf, MathContext mc);
 
     ProgressiveLoanInterestScheduleModel generateModel(LoanProductRelatedDetail loanProductRelatedDetail,
-            Integer installmentAmountInMultiplesOf, List<LoanRepaymentScheduleInstallment> repaymentPeriods);
+            Integer installmentAmountInMultiplesOf, List<LoanRepaymentScheduleInstallment> repaymentPeriods, MathContext mc);
 
     Optional<RepaymentPeriod> findRepaymentPeriod(ProgressiveLoanInterestScheduleModel scheduleModel, LocalDate dueDate);
 
diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
index c2ab25fa8..c97ef747f 100644
--- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
+++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.loanproduct.calc;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.time.LocalDate;
 import java.time.Year;
 import java.util.ArrayList;
@@ -29,7 +30,6 @@ import lombok.RequiredArgsConstructor;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.domain.Money;
-import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
 import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
 import org.apache.fineract.portfolio.common.domain.DaysInYearType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
@@ -40,12 +40,10 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.ProgressiveLo
 import org.apache.fineract.portfolio.loanaccount.loanschedule.data.RepaymentPeriod;
 import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelRepaymentPeriod;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
-import org.springframework.context.annotation.DependsOn;
 import org.springframework.stereotype.Component;
 
 @Component
 @RequiredArgsConstructor
-@DependsOn("moneyHelper")
 public final class ProgressiveEMICalculator implements EMICalculator {
 
     private static final BigDecimal DIVISOR_100 = new BigDecimal("100");
@@ -53,19 +51,19 @@ public final class ProgressiveEMICalculator implements EMICalculator {
 
     @Override
     public ProgressiveLoanInterestScheduleModel generateInterestScheduleModel(final List<LoanScheduleModelRepaymentPeriod> periods,
-            final LoanProductRelatedDetail loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf) {
-        final Money zeroAmount = Money.zero(loanProductRelatedDetail.getCurrency());
+            final LoanProductRelatedDetail loanProductRelatedDetail, final Integer installmentAmountInMultiplesOf, final MathContext mc) {
+        final Money zeroAmount = Money.zero(loanProductRelatedDetail.getCurrency(), mc);
         final ArrayList<RepaymentPeriod> interestRepaymentModelList = new ArrayList<>(periods.size());
         RepaymentPeriod previousPeriod = null;
         for (final LoanScheduleModelRepaymentPeriod period : periods) {
-            RepaymentPeriod currentPeriod = new RepaymentPeriod(previousPeriod, period.periodFromDate(), period.periodDueDate(),
-                    zeroAmount);
+            RepaymentPeriod currentPeriod = new RepaymentPeriod(previousPeriod, period.periodFromDate(), period.periodDueDate(), zeroAmount,
+                    mc);
             previousPeriod = currentPeriod;
             interestRepaymentModelList.add(currentPeriod);
 
         }
         return new ProgressiveLoanInterestScheduleModel(interestRepaymentModelList, loanProductRelatedDetail,
-                installmentAmountInMultiplesOf);
+                installmentAmountInMultiplesOf, mc);
     }
 
     @Override
@@ -85,7 +83,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
             final Money disbursedAmount) {
         scheduleModel
                 .changeOutstandingBalanceAndUpdateInterestPeriods(disbursementDueDate, disbursedAmount,
-                        Money.zero(disbursedAmount.getCurrency()))
+                        Money.zero(disbursedAmount.getCurrency(), scheduleModel.mc()))
                 .ifPresent((repaymentPeriod) -> calculateEMIValueAndRateFactors(repaymentPeriod.getDueDate(), scheduleModel));
     }
 
@@ -130,7 +128,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
     @Override
     public PayableDetails getPayableDetails(final ProgressiveLoanInterestScheduleModel scheduleModel,
             final LocalDate repaymentPeriodDueDate, final LocalDate targetDate) {
-        RepaymentPeriod repaymentPeriod = scheduleModel.deepCopy().repaymentPeriods().stream()
+        MathContext mc = scheduleModel.mc();
+        RepaymentPeriod repaymentPeriod = scheduleModel.deepCopy(mc).repaymentPeriods().stream()
                 .filter(rp -> rp.getDueDate().equals(repaymentPeriodDueDate)).findFirst().orElseThrow();
         LocalDate adjustedTargetDate = targetDate;
         InterestPeriod interestPeriod;
@@ -151,19 +150,19 @@ public final class ProgressiveEMICalculator implements EMICalculator {
 
         // TODO: gather all the unrecognized interest from previous periods based on target date
         Money payableInterest = targetDate.isBefore(repaymentPeriod.getFromDate())
-                ? Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency())
+                ? Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency(), mc)
                 : repaymentPeriod.getDueInterest();
         Money outstandingLoanBalance = interestPeriod.getOutstandingLoanBalance().add(interestPeriod.getDisbursementAmount());
 
-        Money calculatedEmi = outstandingLoanBalance.plus(payableInterest);
+        Money calculatedEmi = outstandingLoanBalance.plus(payableInterest, mc);
         if (calculatedEmi.isLessThan(repaymentPeriod.getEmi())) {
             // Review this logic
-            repaymentPeriod.setEmi(outstandingLoanBalance.plus(payableInterest).plus(repaymentPeriod.getPaidInterest())
-                    .plus(repaymentPeriod.getPaidPrincipal()));
+            repaymentPeriod.setEmi(outstandingLoanBalance.plus(payableInterest).plus(repaymentPeriod.getPaidInterest(), mc)
+                    .plus(repaymentPeriod.getPaidPrincipal(), mc));
         }
-        Money payablePrincipal = repaymentPeriod.getEmi().minus(payableInterest);
+        Money payablePrincipal = repaymentPeriod.getEmi().minus(payableInterest, mc);
         return new PayableDetails(repaymentPeriod.getEmi(), payablePrincipal, payableInterest,
-                interestPeriod.getOutstandingLoanBalance().add(interestPeriod.getDisbursementAmount()));
+                interestPeriod.getOutstandingLoanBalance().add(interestPeriod.getDisbursementAmount(), mc));
     }
 
     @Override
@@ -189,18 +188,19 @@ public final class ProgressiveEMICalculator implements EMICalculator {
     }
 
     private void calculateLastUnpaidRepaymentPeriodEMI(ProgressiveLoanInterestScheduleModel scheduleModel) {
+        MathContext mc = scheduleModel.mc();
         Money totalDueInterest = scheduleModel.repaymentPeriods().stream().map(RepaymentPeriod::getDueInterest)
-                .reduce(Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency()), Money::plus); // 1.46
+                .reduce(Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency(), mc), (m1, m2) -> m1.plus(m2, mc)); // 1.46
         Money totalEMI = scheduleModel.repaymentPeriods().stream().map(RepaymentPeriod::getEmi)
-                .reduce(Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency()), Money::plus); // 101.48
+                .reduce(Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency(), mc), (m1, m2) -> m1.plus(m2, mc)); // 101.48
         Money totalDisbursedAmount = scheduleModel.repaymentPeriods().stream()
                 .flatMap(rp -> rp.getInterestPeriods().stream().map(InterestPeriod::getDisbursementAmount))
-                .reduce(Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency()), Money::plus); // 100
+                .reduce(Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency(), mc), (m1, m2) -> m1.plus(m2, mc)); // 100
 
-        Money diff = totalDisbursedAmount.plus(totalDueInterest).minus(totalEMI);
+        Money diff = totalDisbursedAmount.plus(totalDueInterest, mc).minus(totalEMI, mc);
         Optional<RepaymentPeriod> findLastUnpaidRepaymentPeriod = scheduleModel.repaymentPeriods().stream().filter(rp -> !rp.isFullyPaid())
                 .reduce((first, second) -> second);
-        findLastUnpaidRepaymentPeriod.ifPresent(repaymentPeriod -> repaymentPeriod.setEmi(repaymentPeriod.getEmi().add(diff)));
+        findLastUnpaidRepaymentPeriod.ifPresent(repaymentPeriod -> repaymentPeriod.setEmi(repaymentPeriod.getEmi().add(diff, mc)));
     }
 
     private void calculateOutstandingBalance(ProgressiveLoanInterestScheduleModel scheduleModel) {
@@ -209,24 +209,26 @@ public final class ProgressiveEMICalculator implements EMICalculator {
 
     private void checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(final ProgressiveLoanInterestScheduleModel scheduleModel,
             final List<RepaymentPeriod> relatedRepaymentPeriods) {
+        MathContext mc = scheduleModel.mc();
         final Money emiDifference = getDifferenceBetweenLastTwoPeriod(relatedRepaymentPeriods, scheduleModel);
         final int numberOfRelatedPeriods = relatedRepaymentPeriods.size();
         double lowerHalfOfRelatedPeriods = Math.floor(numberOfRelatedPeriods / 2.0);
-        if (emiDifference.isZero() || lowerHalfOfRelatedPeriods == 0.0) {
+        if (emiDifference.isZero(mc) || lowerHalfOfRelatedPeriods == 0.0) {
             return;
         }
         final Money originalEmi = relatedRepaymentPeriods.get(numberOfRelatedPeriods - 2).getEmi();
-        boolean shouldBeAdjusted = emiDifference.abs().multipliedBy(100)
-                .isGreaterThan(Money.of(originalEmi.getCurrency(), BigDecimal.valueOf(lowerHalfOfRelatedPeriods)));
+        boolean shouldBeAdjusted = emiDifference.abs(mc).multipliedBy(100, mc)
+                .isGreaterThan(Money.of(originalEmi.getCurrency(), BigDecimal.valueOf(lowerHalfOfRelatedPeriods), mc));
 
         if (shouldBeAdjusted) {
-            Money adjustment = emiDifference.dividedBy(numberOfRelatedPeriods, MoneyHelper.getMathContext().getRoundingMode());
-            Money adjustedEqualMonthlyInstallmentValue = applyInstallmentAmountInMultiplesOf(scheduleModel, originalEmi.plus(adjustment));
+            Money adjustment = emiDifference.dividedBy(numberOfRelatedPeriods, mc.getRoundingMode(), mc);
+            Money adjustedEqualMonthlyInstallmentValue = applyInstallmentAmountInMultiplesOf(scheduleModel,
+                    originalEmi.plus(adjustment, mc));
             if (adjustedEqualMonthlyInstallmentValue.isEqualTo(originalEmi)) {
                 return;
             }
             final LocalDate relatedPeriodsFirstDueDate = relatedRepaymentPeriods.get(0).getDueDate();
-            final ProgressiveLoanInterestScheduleModel newScheduleModel = scheduleModel.deepCopy();
+            final ProgressiveLoanInterestScheduleModel newScheduleModel = scheduleModel.deepCopy(mc);
             newScheduleModel.repaymentPeriods().forEach(period -> {
                 if (!period.getDueDate().isBefore(relatedPeriodsFirstDueDate)) {
                     period.setEmi(adjustedEqualMonthlyInstallmentValue);
@@ -235,7 +237,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
             calculateOutstandingBalance(newScheduleModel);
             calculateLastUnpaidRepaymentPeriodEMI(newScheduleModel);
             final Money newEmiDifference = getDifferenceBetweenLastTwoPeriod(newScheduleModel.repaymentPeriods(), scheduleModel);
-            final boolean newEmiHasLessDifference = newEmiDifference.abs().isLessThan(emiDifference.abs());
+            final boolean newEmiHasLessDifference = newEmiDifference.abs(mc).isLessThan(emiDifference.abs(mc));
             if (!newEmiHasLessDifference) {
                 return;
             }
@@ -263,8 +265,8 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      *
      * @return Rate Interest Rate in fraction format
      */
-    BigDecimal calcNominalInterestRatePercentage(final BigDecimal interestRate) {
-        return MathUtil.nullToZero(interestRate).divide(DIVISOR_100, MoneyHelper.getMathContext());
+    BigDecimal calcNominalInterestRatePercentage(final BigDecimal interestRate, MathContext mc) {
+        return MathUtil.nullToZero(interestRate).divide(DIVISOR_100, mc);
     }
 
     /**
@@ -286,8 +288,10 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      */
     BigDecimal calculateRateFactorPerPeriod(final RepaymentPeriod repaymentPeriod, final InterestPeriod interestPeriod,
             final ProgressiveLoanInterestScheduleModel scheduleModel) {
+        final MathContext mc = scheduleModel.mc();
         final LoanProductRelatedDetail loanProductRelatedDetail = scheduleModel.loanProductRelatedDetail();
-        final BigDecimal interestRate = calcNominalInterestRatePercentage(scheduleModel.getInterestRate(interestPeriod.getFromDate()));
+        final BigDecimal interestRate = calcNominalInterestRatePercentage(scheduleModel.getInterestRate(interestPeriod.getFromDate()),
+                scheduleModel.mc());
         final DaysInYearType daysInYearType = DaysInYearType.fromInt(loanProductRelatedDetail.getDaysInYearType());
         final DaysInMonthType daysInMonthType = DaysInMonthType.fromInt(loanProductRelatedDetail.getDaysInMonthType());
         final PeriodFrequencyType repaymentFrequency = loanProductRelatedDetail.getRepaymentPeriodFrequencyType();
@@ -306,13 +310,13 @@ public final class ProgressiveEMICalculator implements EMICalculator {
         // TODO review: (repayment frequency: days, weeks, years; validation day is month fix 30)
         // TODO refactor this logic to represent in interest period
         if (partialPeriodCalculationNeeded) {
-            final BigDecimal cumulatedPeriodFractions = calculatePeriodFractions(interestPeriod);
+            final BigDecimal cumulatedPeriodFractions = calculatePeriodFractions(interestPeriod, mc);
             return rateFactorByRepaymentPartialPeriod(interestRate, repaymentEvery, cumulatedPeriodFractions, BigDecimal.ONE,
-                    BigDecimal.ONE);
+                    BigDecimal.ONE, mc);
         }
 
         return calculateRateFactorPerPeriodBasedOnRepaymentFrequency(interestRate, repaymentFrequency, repaymentEvery, daysInMonth,
-                daysInYear, actualDaysInPeriod, calculatedDaysInPeriod);
+                daysInYear, actualDaysInPeriod, calculatedDaysInPeriod, mc);
     }
 
     /**
@@ -321,7 +325,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      * @param interestPeriod
      * @return
      */
-    BigDecimal calculatePeriodFractions(InterestPeriod interestPeriod) {
+    BigDecimal calculatePeriodFractions(InterestPeriod interestPeriod, MathContext mc) {
         BigDecimal cumulatedRateFactor = BigDecimal.ZERO;
         int actualYear = interestPeriod.getFromDate().getYear();
         int endYear = interestPeriod.getDueDate().getYear();
@@ -332,8 +336,7 @@ public final class ProgressiveEMICalculator implements EMICalculator {
             endOfActualYear = actualYear == endYear ? interestPeriod.getDueDate() : LocalDate.of(actualYear, 12, 31);
             BigDecimal numberOfDaysInYear = BigDecimal.valueOf(Year.of(actualYear).length());
             BigDecimal calculatedDaysInActualYear = BigDecimal.valueOf(DateUtils.getDifferenceInDays(actualDate, endOfActualYear));
-            cumulatedRateFactor = cumulatedRateFactor
-                    .add(calculatedDaysInActualYear.divide(numberOfDaysInYear, MoneyHelper.getMathContext()), MoneyHelper.getMathContext());
+            cumulatedRateFactor = cumulatedRateFactor.add(calculatedDaysInActualYear.divide(numberOfDaysInYear, mc), mc);
             actualDate = endOfActualYear;
             actualYear++;
         }
@@ -354,14 +357,15 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      */
     BigDecimal calculateRateFactorPerPeriodBasedOnRepaymentFrequency(final BigDecimal interestRate,
             final PeriodFrequencyType repaymentFrequency, final BigDecimal repaymentEvery, final BigDecimal daysInMonth,
-            final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod) {
+            final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod,
+            final MathContext mc) {
         return switch (repaymentFrequency) {
             case DAYS ->
-                rateFactorByRepaymentEveryDay(interestRate, repaymentEvery, daysInYear, actualDaysInPeriod, calculatedDaysInPeriod);
+                rateFactorByRepaymentEveryDay(interestRate, repaymentEvery, daysInYear, actualDaysInPeriod, calculatedDaysInPeriod, mc);
             case WEEKS ->
-                rateFactorByRepaymentEveryWeek(interestRate, repaymentEvery, daysInYear, actualDaysInPeriod, calculatedDaysInPeriod);
+                rateFactorByRepaymentEveryWeek(interestRate, repaymentEvery, daysInYear, actualDaysInPeriod, calculatedDaysInPeriod, mc);
             case MONTHS -> rateFactorByRepaymentEveryMonth(interestRate, repaymentEvery, daysInMonth, daysInYear, actualDaysInPeriod,
-                    calculatedDaysInPeriod);
+                    calculatedDaysInPeriod, mc);
             default -> throw new UnsupportedOperationException("Invalid repayment frequency"); // not supported yet
         };
     }
@@ -370,14 +374,15 @@ public final class ProgressiveEMICalculator implements EMICalculator {
         if (repaymentPeriods.isEmpty()) {
             return;
         }
-        final BigDecimal rateFactorN = MathUtil.stripTrailingZeros(calculateRateFactorPlus1N(repaymentPeriods));
-        final BigDecimal fnResult = MathUtil.stripTrailingZeros(calculateFnResult(repaymentPeriods));
+        final MathContext mc = scheduleModel.mc();
+        final BigDecimal rateFactorN = MathUtil.stripTrailingZeros(calculateRateFactorPlus1N(repaymentPeriods, mc));
+        final BigDecimal fnResult = MathUtil.stripTrailingZeros(calculateFnResult(repaymentPeriods, mc));
         final RepaymentPeriod startPeriod = repaymentPeriods.get(0);
         // TODO: double check
         final Money outstandingBalance = startPeriod.getInitialBalanceForEmiRecalculation();
 
         final Money equalMonthlyInstallment = Money.of(outstandingBalance.getCurrency(),
-                calculateEMIValue(rateFactorN, outstandingBalance.getAmount(), fnResult));
+                calculateEMIValue(rateFactorN, outstandingBalance.getAmount(), fnResult, mc), mc);
         final Money finalEqualMonthlyInstallment = applyInstallmentAmountInMultiplesOf(scheduleModel, equalMonthlyInstallment);
 
         repaymentPeriods.forEach(period -> period.setEmi(finalEqualMonthlyInstallment));
@@ -392,39 +397,40 @@ public final class ProgressiveEMICalculator implements EMICalculator {
 
     Money getDifferenceBetweenLastTwoPeriod(final List<RepaymentPeriod> repaymentPeriods,
             final ProgressiveLoanInterestScheduleModel scheduleModel) {
+        MathContext mc = scheduleModel.mc();
         int numberOfUpcomingPeriods = repaymentPeriods.size();
         if (numberOfUpcomingPeriods < 2) {
-            return Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency());
+            return Money.zero(scheduleModel.loanProductRelatedDetail().getCurrency(), mc);
         }
         final RepaymentPeriod lastPeriod = repaymentPeriods.get(numberOfUpcomingPeriods - 1);
         final RepaymentPeriod penultimatePeriod = repaymentPeriods.get(numberOfUpcomingPeriods - 2);
-        return lastPeriod.getEmi().minus(penultimatePeriod.getEmi());
+        return lastPeriod.getEmi().minus(penultimatePeriod.getEmi(), mc);
     }
 
     /**
      * Calculate Rate Factor Product from rate factors
      */
-    BigDecimal calculateRateFactorPlus1N(final List<RepaymentPeriod> periods) {
+    BigDecimal calculateRateFactorPlus1N(final List<RepaymentPeriod> periods, MathContext mc) {
         return periods.stream().map(RepaymentPeriod::getRateFactorPlus1).reduce(BigDecimal.ONE,
-                (BigDecimal acc, BigDecimal value) -> acc.multiply(value, MoneyHelper.getMathContext()));
+                (BigDecimal acc, BigDecimal value) -> acc.multiply(value, mc));
     }
 
     /**
      * Summarize Fn values
      */
-    BigDecimal calculateFnResult(final List<RepaymentPeriod> periods) {
+    BigDecimal calculateFnResult(final List<RepaymentPeriod> periods, final MathContext mc) {
         return periods.stream()//
                 .skip(1)//
                 .map(RepaymentPeriod::getRateFactorPlus1)//
-                .reduce(BigDecimal.ONE, this::fnValue);//
+                .reduce(BigDecimal.ONE, (previousFnValue, currentRateFactor) -> fnValue(previousFnValue, currentRateFactor, mc));//
     }
 
     /**
      * Calculate the EMI (Equal Monthly Installment) value
      */
-    BigDecimal calculateEMIValue(final BigDecimal rateFactorPlus1N, final BigDecimal outstandingBalanceForRest, final BigDecimal fnResult) {
-        return rateFactorPlus1N.multiply(outstandingBalanceForRest, MoneyHelper.getMathContext()).divide(fnResult,
-                MoneyHelper.getMathContext());
+    BigDecimal calculateEMIValue(final BigDecimal rateFactorPlus1N, final BigDecimal outstandingBalanceForRest, final BigDecimal fnResult,
+            MathContext mc) {
+        return rateFactorPlus1N.multiply(outstandingBalanceForRest, mc).divide(fnResult, mc);
     }
 
     /**
@@ -452,9 +458,9 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      * @return Rate Factor for period
      */
     BigDecimal rateFactorByRepaymentEveryDay(final BigDecimal interestRate, final BigDecimal repaymentEvery, final BigDecimal daysInYear,
-            final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod) {
+            final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod, MathContext mc) {
         return rateFactorByRepaymentPeriod(interestRate, BigDecimal.ONE, repaymentEvery, daysInYear, actualDaysInPeriod,
-                calculatedDaysInPeriod);
+                calculatedDaysInPeriod, mc);
     }
 
     /**
@@ -482,9 +488,9 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      * @return Rate Factor for period
      */
     BigDecimal rateFactorByRepaymentEveryWeek(final BigDecimal interestRate, final BigDecimal repaymentEvery, final BigDecimal daysInYear,
-            final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod) {
+            final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod, MathContext mc) {
         return rateFactorByRepaymentPeriod(interestRate, ONE_WEEK_IN_DAYS, repaymentEvery, daysInYear, actualDaysInPeriod,
-                calculatedDaysInPeriod);
+                calculatedDaysInPeriod, mc);
     }
 
     /**
@@ -515,9 +521,10 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      * @return Rate Factor for period
      */
     BigDecimal rateFactorByRepaymentEveryMonth(final BigDecimal interestRate, final BigDecimal repaymentEvery, final BigDecimal daysInMonth,
-            final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod) {
+            final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod,
+            final MathContext mc) {
         return rateFactorByRepaymentPeriod(interestRate, daysInMonth, repaymentEvery, daysInYear, actualDaysInPeriod,
-                calculatedDaysInPeriod);
+                calculatedDaysInPeriod, mc);
     }
 
     /**
@@ -549,14 +556,14 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      */
     BigDecimal rateFactorByRepaymentPeriod(final BigDecimal interestRate, final BigDecimal repaymentPeriodMultiplierInDays,
             final BigDecimal repaymentEvery, final BigDecimal daysInYear, final BigDecimal actualDaysInPeriod,
-            final BigDecimal calculatedDaysInPeriod) {
+            final BigDecimal calculatedDaysInPeriod, final MathContext mc) {
         final BigDecimal interestFractionPerPeriod = repaymentPeriodMultiplierInDays//
-                .multiply(repaymentEvery, MoneyHelper.getMathContext())//
-                .divide(daysInYear, MoneyHelper.getMathContext());//
+                .multiply(repaymentEvery, mc)//
+                .divide(daysInYear, mc);//
         return interestRate//
-                .multiply(interestFractionPerPeriod, MoneyHelper.getMathContext())//
-                .multiply(actualDaysInPeriod, MoneyHelper.getMathContext())//
-                .divide(calculatedDaysInPeriod, MoneyHelper.getMathContext());//
+                .multiply(interestFractionPerPeriod, mc)//
+                .multiply(actualDaysInPeriod, mc)//
+                .divide(calculatedDaysInPeriod, mc);//
     }
 
     /**
@@ -564,12 +571,13 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      *
      */
     BigDecimal rateFactorByRepaymentPartialPeriod(final BigDecimal interestRate, final BigDecimal repaymentEvery,
-            final BigDecimal cumulatedPeriodRatio, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod) {
+            final BigDecimal cumulatedPeriodRatio, final BigDecimal actualDaysInPeriod, final BigDecimal calculatedDaysInPeriod,
+            final MathContext mc) {
         final BigDecimal interestFractionPerPeriod = repaymentEvery.multiply(cumulatedPeriodRatio);
         return interestRate//
-                .multiply(interestFractionPerPeriod, MoneyHelper.getMathContext())//
-                .multiply(actualDaysInPeriod, MoneyHelper.getMathContext())//
-                .divide(calculatedDaysInPeriod, MoneyHelper.getMathContext());//
+                .multiply(interestFractionPerPeriod, mc)//
+                .multiply(actualDaysInPeriod, mc)//
+                .divide(calculatedDaysInPeriod, mc);//
     }
 
     /**
@@ -582,13 +590,13 @@ public final class ProgressiveEMICalculator implements EMICalculator {
      * @param currentRateFactor
      *
      */
-    BigDecimal fnValue(final BigDecimal previousFnValue, final BigDecimal currentRateFactor) {
-        return BigDecimal.ONE.add(previousFnValue.multiply(currentRateFactor, MoneyHelper.getMathContext()), MoneyHelper.getMathContext());
+    BigDecimal fnValue(final BigDecimal previousFnValue, final BigDecimal currentRateFactor, final MathContext mc) {
+        return BigDecimal.ONE.add(previousFnValue.multiply(currentRateFactor, mc), mc);
     }
 
     @Override
     public ProgressiveLoanInterestScheduleModel generateModel(LoanProductRelatedDetail loanProductRelatedDetail,
-            Integer installmentAmountInMultiplesOf, List<LoanRepaymentScheduleInstallment> repaymentPeriods) {
+            Integer installmentAmountInMultiplesOf, List<LoanRepaymentScheduleInstallment> repaymentPeriods, MathContext mc) {
         List<LoanRepaymentScheduleInstallment> repaymentModelsWithoutDownPayment = repaymentPeriods.stream()
                 .filter(period -> !period.isDownPayment() && !period.isAdditional()).toList();
 
@@ -596,11 +604,11 @@ public final class ProgressiveEMICalculator implements EMICalculator {
         RepaymentPeriod previousPeriod = null;
         for (LoanRepaymentScheduleInstallment repaymentModel : repaymentModelsWithoutDownPayment) {
             RepaymentPeriod currentPeriod = new RepaymentPeriod(previousPeriod, repaymentModel.getFromDate(), repaymentModel.getDueDate(),
-                    Money.zero(repaymentModel.getLoan().getCurrency()));
+                    Money.zero(repaymentModel.getLoan().getCurrency(), mc), mc);
             previousPeriod = currentPeriod;
             repaymentModels.add(currentPeriod);
         }
 
-        return new ProgressiveLoanInterestScheduleModel(repaymentModels, loanProductRelatedDetail, installmentAmountInMultiplesOf);
+        return new ProgressiveLoanInterestScheduleModel(repaymentModels, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
     }
 }
diff --git a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
index ffef3502a..d1f9de0e0 100644
--- a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
+++ b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessorTest.java
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.ArrayList;
@@ -90,11 +91,12 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
     private static final MonetaryCurrency MONETARY_CURRENCY = new MonetaryCurrency("USD", 2, 1);
     private static final MockedStatic<MoneyHelper> MONEY_HELPER = mockStatic(MoneyHelper.class);
     private AdvancedPaymentScheduleTransactionProcessor underTest;
-    private final EMICalculator emiCalculator = Mockito.mock(EMICalculator.class);
+    private static final EMICalculator emiCalculator = Mockito.mock(EMICalculator.class);
 
     @BeforeAll
     public static void init() {
         MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
+        MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
     }
 
     @AfterAll
diff --git a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
index b0015c29c..c5b7f65d1 100644
--- a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
+++ b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
@@ -20,77 +20,36 @@ package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
-import java.util.ArrayList;
 import java.util.List;
 import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
-import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
-import org.apache.fineract.organisation.monetary.domain.Money;
-import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
 import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
 import org.apache.fineract.portfolio.common.domain.DaysInYearType;
 import org.apache.fineract.portfolio.loanproduct.calc.ProgressiveEMICalculator;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.MockedStatic;
-import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 @ExtendWith(MockitoExtension.class)
 class LoanScheduleGeneratorTest {
 
     private static final ProgressiveEMICalculator emiCalculator = new ProgressiveEMICalculator();
-    private static MockedStatic<MoneyHelper> moneyHelper = Mockito.mockStatic(MoneyHelper.class);
     private static final ApplicationCurrency APPLICATION_CURRENCY = new ApplicationCurrency("USD", "USD", 2, 1, "USD", "$");
-    private static final MonetaryCurrency MONETARY_CURRENCY = MonetaryCurrency.fromApplicationCurrency(APPLICATION_CURRENCY);
     private static final BigDecimal DISBURSEMENT_AMOUNT = BigDecimal.valueOf(192.22);
     private static final BigDecimal NOMINAL_INTEREST_RATE = BigDecimal.valueOf(9.99);
     private static final int NUMBER_OF_REPAYMENTS = 6;
     private static final int REPAYMENT_FREQUENCY = 1;
     private static final String REPAYMENT_FREQUENCY_TYPE = "MONTHS";
     private static final LocalDate DISBURSEMENT_DATE = LocalDate.of(2024, 1, 15);
-
-    @BeforeAll
-    public static void init() {
-        moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
-        moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
-    }
-
-    @AfterAll
-    public static void destruct() {
-        moneyHelper.close();
-    }
+    private static final MathContext mc = new MathContext(12, RoundingMode.HALF_EVEN);
 
     @Test
     void testGenerateLoanSchedule() {
-        LoanRepaymentScheduleModelData modelData = new LoanRepaymentScheduleModelData(LocalDate.of(2024, 1, 1), APPLICATION_CURRENCY,
-                DISBURSEMENT_AMOUNT, DISBURSEMENT_DATE, NUMBER_OF_REPAYMENTS, REPAYMENT_FREQUENCY, REPAYMENT_FREQUENCY_TYPE,
-                NOMINAL_INTEREST_RATE, true, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, null, null, null);
-
-        final MathContext mc = MoneyHelper.getMathContext();
-        final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods = new ArrayList<>();
-
-        expectedRepaymentPeriods.add(repayment(1, LocalDate.of(2024, 1, 1), LocalDate.of(2024, 2, 1)));
-        expectedRepaymentPeriods.add(repayment(2, LocalDate.of(2024, 2, 1), LocalDate.of(2024, 3, 1)));
-        expectedRepaymentPeriods.add(repayment(3, LocalDate.of(2024, 3, 1), LocalDate.of(2024, 4, 1)));
-        expectedRepaymentPeriods.add(repayment(4, LocalDate.of(2024, 4, 1), LocalDate.of(2024, 5, 1)));
-        expectedRepaymentPeriods.add(repayment(5, LocalDate.of(2024, 5, 1), LocalDate.of(2024, 6, 1)));
-        expectedRepaymentPeriods.add(repayment(6, LocalDate.of(2024, 6, 1), LocalDate.of(2024, 7, 1)));
-
-        ScheduledDateGenerator mockScheduledDateGenerator = Mockito.mock(ScheduledDateGenerator.class);
-        ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(mockScheduledDateGenerator, emiCalculator);
-        when(mockScheduledDateGenerator.generateRepaymentPeriods(any(), any(), any())).thenReturn(expectedRepaymentPeriods);
-
-        LoanScheduleModel loanSchedule = generator.generate(mc, modelData);
-        List<LoanScheduleModelPeriod> periods = loanSchedule.getPeriods();
+        List<LoanScheduleModelPeriod> periods = getLoanScheduleModelPeriods();
 
         assertEquals(7, periods.size(), "Expected 7 periods including the downpayment period.");
 
@@ -111,6 +70,18 @@ class LoanScheduleGeneratorTest {
                 BigDecimal.valueOf(0.27), BigDecimal.valueOf(32.87), BigDecimal.ZERO);
     }
 
+    private static List<LoanScheduleModelPeriod> getLoanScheduleModelPeriods() {
+        LoanRepaymentScheduleModelData modelData = new LoanRepaymentScheduleModelData(LocalDate.of(2024, 1, 1), APPLICATION_CURRENCY,
+                DISBURSEMENT_AMOUNT, DISBURSEMENT_DATE, NUMBER_OF_REPAYMENTS, REPAYMENT_FREQUENCY, REPAYMENT_FREQUENCY_TYPE,
+                NOMINAL_INTEREST_RATE, true, DaysInMonthType.DAYS_30, DaysInYearType.DAYS_360, null, null, null);
+
+        ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
+        ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
+
+        LoanScheduleModel loanSchedule = generator.generate(mc, modelData);
+        return loanSchedule.getPeriods();
+    }
+
     private void checkPeriod(LoanScheduleModelPeriod period, int expectedPeriodNumber, LocalDate expectedFromDate,
             LocalDate expectedDueDate, BigDecimal expectedPrincipalDue, BigDecimal expectedInterestDue, BigDecimal expectedTotalDue,
             BigDecimal expectedOutstandingLoanBalance) {
@@ -123,10 +94,4 @@ class LoanScheduleGeneratorTest {
         assertEquals(0, expectedTotalDue.compareTo(repaymentPeriod.getTotalDue().getAmount()));
         assertEquals(0, expectedOutstandingLoanBalance.compareTo(repaymentPeriod.getOutstandingLoanBalance().getAmount()));
     }
-
-    private static LoanScheduleModelRepaymentPeriod repayment(int periodNumber, LocalDate fromDate, LocalDate dueDate) {
-        final Money zeroAmount = Money.zero(MONETARY_CURRENCY);
-        return LoanScheduleModelRepaymentPeriod.repayment(periodNumber, fromDate, dueDate, zeroAmount, zeroAmount, zeroAmount, zeroAmount,
-                zeroAmount, zeroAmount, false);
-    }
 }
diff --git a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
index 1f7b6cb87..1137b2e68 100644
--- a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
+++ b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
@@ -59,6 +59,7 @@ class ProgressiveEMICalculatorTest {
 
     private static MockedStatic<ThreadLocalContextUtil> threadLocalContextUtil = Mockito.mockStatic(ThreadLocalContextUtil.class);
     private static MockedStatic<MoneyHelper> moneyHelper = Mockito.mockStatic(MoneyHelper.class);
+    private static MathContext mc = new MathContext(12, RoundingMode.HALF_EVEN);
     private static LoanProductRelatedDetail loanProductRelatedDetail = Mockito.mock(LoanProductRelatedDetail.class);
 
     private static final MonetaryCurrency monetaryCurrency = MonetaryCurrency
@@ -95,7 +96,7 @@ class ProgressiveEMICalculatorTest {
         final BigDecimal daysInYear = BigDecimal.valueOf(daysInYearType.getNumberOfDays(period.getFromDate()));
         final BigDecimal daysInMonth = BigDecimal.valueOf(daysInMonthType.getNumberOfDays(period.getFromDate()));
         final BigDecimal rateFactor = emiCalculator.rateFactorByRepaymentEveryMonth(interestRate, BigDecimal.ONE, daysInMonth, daysInYear,
-                daysInPeriod, daysInPeriod);
+                daysInPeriod, daysInPeriod, mc);
         return rateFactor.setScale(12, MoneyHelper.getRoundingMode());
     }
 
@@ -145,7 +146,7 @@ class ProgressiveEMICalculatorTest {
             BigDecimal rateFactorPlus1 = getRateFactorsByMonth(daysInYearType, daysInMonthType, interestRate, period).add(BigDecimal.ONE,
                     MoneyHelper.getMathContext());
 
-            final BigDecimal currentFnValue = emiCalculator.fnValue(previousFnValue, rateFactorPlus1);
+            final BigDecimal currentFnValue = emiCalculator.fnValue(previousFnValue, rateFactorPlus1, mc);
             fnValuesCalculated.add(currentFnValue);
 
             previousFnValue = currentFnValue;
@@ -171,7 +172,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestScheduleModel = emiCalculator
-                .generateInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                .generateInterestScheduleModel(expectedRepaymentPeriods, loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         Assertions.assertTrue(interestScheduleModel != null);
         Assertions.assertTrue(interestScheduleModel.loanProductRelatedDetail() != null);
@@ -211,7 +212,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = toMoney(100.0);
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -256,7 +257,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = toMoney(100.0);
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -293,7 +294,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -330,7 +331,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -370,7 +371,7 @@ class ProgressiveEMICalculatorTest {
         threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -414,7 +415,7 @@ class ProgressiveEMICalculatorTest {
         threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 14));
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -460,7 +461,7 @@ class ProgressiveEMICalculatorTest {
         threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -577,7 +578,7 @@ class ProgressiveEMICalculatorTest {
         threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -661,7 +662,7 @@ class ProgressiveEMICalculatorTest {
         threadLocalContextUtil.when(ThreadLocalContextUtil::getBusinessDate).thenReturn(LocalDate.of(2024, 2, 15));
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = toMoney(100.0);
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -739,7 +740,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -788,7 +789,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -837,7 +838,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 5), disbursedAmount);
@@ -881,7 +882,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2023, 12, 12), disbursedAmount);
@@ -915,7 +916,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(1000));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -948,7 +949,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -981,7 +982,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1014,7 +1015,7 @@ class ProgressiveEMICalculatorTest {
         Mockito.when(loanProductRelatedDetail.getCurrency()).thenReturn(monetaryCurrency);
 
         final ProgressiveLoanInterestScheduleModel interestSchedule = emiCalculator.generateInterestScheduleModel(expectedRepaymentPeriods,
-                loanProductRelatedDetail, installmentAmountInMultiplesOf);
+                loanProductRelatedDetail, installmentAmountInMultiplesOf, mc);
 
         final Money disbursedAmount = Money.of(monetaryCurrency, BigDecimal.valueOf(100));
         emiCalculator.addDisbursement(interestSchedule, LocalDate.of(2024, 1, 1), disbursedAmount);
@@ -1031,7 +1032,7 @@ class ProgressiveEMICalculatorTest {
     private static LoanScheduleModelRepaymentPeriod repayment(int periodNumber, LocalDate fromDate, LocalDate dueDate) {
         final Money zeroAmount = Money.zero(monetaryCurrency);
         return LoanScheduleModelRepaymentPeriod.repayment(periodNumber, fromDate, dueDate, zeroAmount, zeroAmount, zeroAmount, zeroAmount,
-                zeroAmount, zeroAmount, false);
+                zeroAmount, zeroAmount, false, mc);
     }
 
     @NotNull
diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
index 345e23c33..b3aad08fb 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/CheckLoanRepaymentOverdueBusinessStepTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.ZoneId;
@@ -88,6 +89,7 @@ public class CheckLoanRepaymentOverdueBusinessStepTest {
 
     @BeforeAll
     public static void init() {
+        MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
         MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
     }
 
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 3abad3fe7..6299535e9 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
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
 
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.ZoneId;
@@ -116,8 +117,12 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
     @Mock
     private AvroDateTimeMapper mapper;
 
+    private MockedStatic<MoneyHelper> moneyHelper = Mockito.mockStatic(MoneyHelper.class);
+
     @BeforeEach
     public void setUp() {
+        moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
+        moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
         ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
         ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
         ThreadLocalContextUtil
@@ -127,6 +132,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
     @AfterEach
     public void tearDown() {
         ThreadLocalContextUtil.reset();
+        moneyHelper.close();
     }
 
     @Test
@@ -141,7 +147,6 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
         LoanAccountData loanAccountData = mock(LoanAccountData.class);
         CollectionData delinquentData = mock(CollectionData.class);
         MonetaryCurrency loanCurrency = new MonetaryCurrency("CODE", 1, 1);
-        MockedStatic<MoneyHelper> moneyHelper = Mockito.mockStatic(MoneyHelper.class);
         String delinquentDateAsStr = "2022-12-01";
         LocalDate delinquentDate = LocalDate.parse(delinquentDateAsStr);
 
@@ -168,8 +173,6 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
         when(loanChargeReadPlatformService.retrieveLoanCharges(anyLong())).thenAnswer(a -> repaymentScheduleInstallments.get(0)
                 .getInstallmentCharges().stream().map(c -> c.getLoanCharge().toData()).collect(Collectors.toList()));
 
-        moneyHelper.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
-
         // when
         LoanAccountDelinquencyRangeDataV1 data = (LoanAccountDelinquencyRangeDataV1) serializer.toAvroDTO(event);
 
@@ -190,8 +193,6 @@ 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());
-
-        moneyHelper.close();
     }
 
     @Test
@@ -206,7 +207,6 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
         LoanAccountData loanAccountData = mock(LoanAccountData.class);
         CollectionData delinquentData = mock(CollectionData.class);
         MonetaryCurrency loanCurrency = new MonetaryCurrency("CODE", 1, 1);
-        MockedStatic<MoneyHelper> moneyHelper = Mockito.mockStatic(MoneyHelper.class);
         String delinquentDateAsStr = "2022-12-01";
         LocalDate delinquentDate = LocalDate.parse(delinquentDateAsStr);
         when(loanForProcessing.getId()).thenReturn(1L);
@@ -263,8 +263,6 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
         when(loanForProcessing.getLoanCharges()).thenAnswer(a -> repaymentScheduleInstallments.get(0).getInstallmentCharges().stream()
                 .map(c -> c.getLoanCharge()).collect(Collectors.toList()));
 
-        moneyHelper.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
-
         // when
         LoanAccountDelinquencyRangeDataV1 data = (LoanAccountDelinquencyRangeDataV1) serializer.toAvroDTO(event);
 
@@ -314,7 +312,6 @@ public class LoanAccountDelinquencyRangeEventSerializerTest {
         assertEquals(0, installmentDelinquencyBucketDataV1_2.getAmount().getFeeAmount().compareTo(new BigDecimal("0.0")));
         assertEquals(0, installmentDelinquencyBucketDataV1_2.getAmount().getPenaltyAmount().compareTo(new BigDecimal("0.0")));
         assertEquals(0, installmentDelinquencyBucketDataV1_2.getCharges().size());
-        moneyHelper.close();
     }
 
     @Test
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 3728a6bd9..3ea0da970 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
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.when;
 
 import java.io.IOException;
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.ZoneId;
@@ -85,7 +86,8 @@ public class LoanRepaymentBusinessEventSerializerTest {
         ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
         ThreadLocalContextUtil
                 .setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
-        moneyHelper.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
+        moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
+        moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
     }
 
     @AfterEach
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
index e4da2691a..037120297 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
@@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.ZoneId;
@@ -104,7 +105,8 @@ public class LoanDelinquencyDomainServiceTest {
         currency = new MonetaryCurrency("USD", 2, null);
 
         moneyHelperStatic = Mockito.mockStatic(MoneyHelper.class);
-        moneyHelperStatic.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
+        moneyHelperStatic.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
+        moneyHelperStatic.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
     }
 
     @AfterEach
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java
index 98034716f..a93177cde 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoInteractions;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.event.business.domain.loan.LoanStatusChangedBusinessEvent;
@@ -55,7 +56,8 @@ class DefaultLoanLifecycleStateMachineTest {
     public void setUp() {
 
         moneyHelperStatic = Mockito.mockStatic(MoneyHelper.class);
-        moneyHelperStatic.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
+        moneyHelperStatic.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
+        moneyHelperStatic.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
         underTest = new DefaultLoanLifecycleStateMachine(businessEventNotifierService);
     }
 
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessorTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessorTest.java
index 19213fdf1..38f5369ef 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessorTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactionProcessorTest.java
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.refEq;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.HashMap;
@@ -87,6 +88,7 @@ public class DuePenFeeIntPriInAdvancePriPenFeeIntLoanRepaymentScheduleTransactio
 
     @BeforeAll
     public static void init() {
+        MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
         MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
     }
 
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessorTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessorTest.java
index b566bb29d..6567ae6c5 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessorTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactionProcessorTest.java
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.refEq;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.HashMap;
@@ -88,6 +89,7 @@ public class DuePenIntPriFeeInAdvancePenIntPriFeeLoanRepaymentScheduleTransactio
 
     @BeforeAll
     public static void init() {
+        MONEY_HELPER.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.HALF_EVEN));
         MONEY_HELPER.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
     }
 
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java
index 3dc81175d..4a212eee5 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DefaultScheduledDateGeneratorTest.java
@@ -37,6 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.BDDMockito.given;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.List;
 import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
@@ -82,6 +84,7 @@ public class DefaultScheduledDateGeneratorTest {
     public void test_generateRepaymentPeriods() {
         // given
         HolidayDetailDTO holidayDetailDTO = createHolidayDTO();
+        MathContext mathContext = new MathContext(12, RoundingMode.HALF_EVEN);
 
         ApplicationCurrency dollarCurrency = new ApplicationCurrency("USD", "US Dollar", 2, 0, "currency.USD", "$");
         Money principalAmount = Money.of(fromApplicationCurrency(dollarCurrency), BigDecimal.valueOf(100));
@@ -98,8 +101,8 @@ public class DefaultScheduledDateGeneratorTest {
                 submittedOnDate, CUMULATIVE, LoanScheduleProcessingType.HORIZONTAL, null, false, null);
 
         // when
-        List<? extends LoanScheduleModelPeriod> result = underTest.generateRepaymentPeriods(expectedDisbursementDate, loanApplicationTerms,
-                holidayDetailDTO);
+        List<? extends LoanScheduleModelPeriod> result = underTest.generateRepaymentPeriods(mathContext, expectedDisbursementDate,
+                loanApplicationTerms, holidayDetailDTO);
 
         // then
         assertThat(result.size()).isEqualTo(4);
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueServiceTest.java
index def517ca9..599382e15 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueServiceTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanCalculateRepaymentPastDueServiceTest.java
@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.Mockito.when;
 
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.ZoneId;
@@ -64,7 +65,8 @@ public class LoanCalculateRepaymentPastDueServiceTest {
         ThreadLocalContextUtil
                 .setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
         underTest = new LoanCalculateRepaymentPastDueService();
-        moneyHelper.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
+        moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
+        moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
     }
 
     @AfterEach
diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImplTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImplTest.java
index 0bfa16ad2..5670c7869 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImplTest.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImplTest.java
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.math.MathContext;
 import java.math.RoundingMode;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.event.business.domain.loan.LoanBalanceChangedBusinessEvent;
@@ -75,7 +76,8 @@ public class LoanDownPaymentHandlerServiceImplTest {
     @BeforeEach
     public void setUp() {
         underTest = new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService);
-        moneyHelper.when(() -> MoneyHelper.getRoundingMode()).thenReturn(RoundingMode.UP);
+        moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
+        moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
     }
 
     @AfterEach