FINERACT-1981: Remove hardcoded MoneyHelper dependency during progressive loan
This commit is contained in:
committed by
Adam Saghy
parent
806ee69798
commit
a9ecdf97a4
+17
@@ -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);
|
||||
}
|
||||
|
||||
+149
-30
@@ -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 MonetaryCurrency currency, MathContext mc) {
|
||||
return new Money(currency.getCode(), currency.getDigitsAfterDecimal(), BigDecimal.ZERO, currency.getCurrencyInMultiplesOf(), mc);
|
||||
}
|
||||
|
||||
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());
|
||||
return new Money(currency.getCode(), currency.getDecimalPlaces(), BigDecimal.ZERO, currency.getInMultiplesOf(), null);
|
||||
}
|
||||
|
||||
protected Money() {
|
||||
this.currencyCode = null;
|
||||
this.currencyDigitsAfterDecimal = 0;
|
||||
this.inMultiplesOf = 0;
|
||||
this.amount = 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();
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user