This is an automated email from the ASF dual-hosted git repository.
victorromero 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 bd404e8c7 Fix to accept Loan Charge amounts using locales (#2393)
bd404e8c7 is described below
commit bd404e8c7b88dad566692c01c1ec5a8630a35492
Author: José Alberto Hernández
<[email protected]>
AuthorDate: Wed Aug 10 13:31:19 2022 -0500
Fix to accept Loan Charge amounts using locales (#2393)
Co-authored-by: Jose Alberto Hernandez <[email protected]>
---
.../core/serialization/JsonParserHelper.java | 12 ++++++--
.../fineract/portfolio/charge/domain/Charge.java | 25 +++++++--------
.../portfolio/loanaccount/domain/LoanCharge.java | 4 ++-
.../ClientLoanIntegrationTest.java | 36 +++++++++++++++++++++-
.../common/charges/ChargesHelper.java | 2 +-
.../common/loans/LoanTransactionHelper.java | 9 ++++--
6 files changed, 68 insertions(+), 20 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/JsonParserHelper.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/JsonParserHelper.java
index 7ad675592..d93b55519 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/JsonParserHelper.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/serialization/JsonParserHelper.java
@@ -122,9 +122,15 @@ public class JsonParserHelper {
if (object.has(parameterName) &&
object.get(parameterName).isJsonPrimitive()) {
modifiedParameters.add(parameterName);
final JsonPrimitive primitive =
object.get(parameterName).getAsJsonPrimitive();
- final String valueAsString = primitive.getAsString();
- if (StringUtils.isNotBlank(valueAsString)) {
- value = convertFrom(valueAsString, parameterName, locale);
+ if (!primitive.isJsonNull()) {
+ if (primitive.isNumber()) {
+ value = primitive.getAsBigDecimal();
+ } else {
+ final String valueAsString = primitive.getAsString();
+ if (StringUtils.isNotBlank(valueAsString)) {
+ value = convertFrom(valueAsString, parameterName,
locale);
+ }
+ }
}
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
index 3ca6660ed..eb0e63dbe 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java
@@ -23,6 +23,7 @@ import java.time.MonthDay;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import javax.persistence.Column;
@@ -390,7 +391,7 @@ public class Charge extends AbstractPersistableCustom {
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
- final String localeAsInput = command.locale();
+ final Locale locale = command.extractLocale();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new
DataValidatorBuilder(dataValidationErrors).resource("charges");
@@ -411,9 +412,9 @@ public class Charge extends AbstractPersistableCustom {
final String amountParamName = "amount";
if (command.isChangeInBigDecimalParameterNamed(amountParamName,
this.amount)) {
- final BigDecimal newValue =
command.bigDecimalValueOfParameterNamed(amountParamName);
+ final BigDecimal newValue =
command.bigDecimalValueOfParameterNamed(amountParamName, locale);
actualChanges.put(amountParamName, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.amount = newValue;
}
@@ -421,7 +422,7 @@ public class Charge extends AbstractPersistableCustom {
if (command.isChangeInIntegerParameterNamed(chargeTimeParamName,
this.chargeTimeType)) {
final Integer newValue =
command.integerValueOfParameterNamed(chargeTimeParamName);
actualChanges.put(chargeTimeParamName, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.chargeTimeType = ChargeTimeType.fromInt(newValue).getValue();
if (isSavingsCharge()) {
@@ -510,7 +511,7 @@ public class Charge extends AbstractPersistableCustom {
if
(command.isChangeInIntegerParameterNamed(chargeCalculationParamName,
this.chargeCalculation)) {
final Integer newValue =
command.integerValueOfParameterNamed(chargeCalculationParamName);
actualChanges.put(chargeCalculationParamName, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.chargeCalculation =
ChargeCalculationType.fromInt(newValue).getValue();
if (isSavingsCharge()) {
@@ -540,7 +541,7 @@ public class Charge extends AbstractPersistableCustom {
if (command.isChangeInIntegerParameterNamed(paymentModeParamName,
this.chargePaymentMode)) {
final Integer newValue =
command.integerValueOfParameterNamed(paymentModeParamName);
actualChanges.put(paymentModeParamName, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.chargePaymentMode =
ChargePaymentMode.fromInt(newValue).getValue();
}
}
@@ -551,14 +552,14 @@ public class Charge extends AbstractPersistableCustom {
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
if (!this.feeOnDay.equals(dayOfMonthValue)) {
actualChanges.put("feeOnMonthDay", actualValueEntered);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.feeOnDay = dayOfMonthValue;
}
final Integer monthOfYear = monthDay.getMonthValue();
if (!this.feeOnMonth.equals(monthOfYear)) {
actualChanges.put("feeOnMonthDay", actualValueEntered);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.feeOnMonth = monthOfYear;
}
}
@@ -567,7 +568,7 @@ public class Charge extends AbstractPersistableCustom {
if (command.isChangeInIntegerParameterNamed(feeInterval,
this.feeInterval)) {
final Integer newValue =
command.integerValueOfParameterNamed(feeInterval);
actualChanges.put(feeInterval, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.feeInterval = newValue;
}
@@ -575,7 +576,7 @@ public class Charge extends AbstractPersistableCustom {
if (command.isChangeInIntegerParameterNamed(feeFrequency,
this.feeFrequency)) {
final Integer newValue =
command.integerValueOfParameterNamed(feeFrequency);
actualChanges.put(feeFrequency, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.feeFrequency = newValue;
}
@@ -602,14 +603,14 @@ public class Charge extends AbstractPersistableCustom {
if (command.isChangeInBigDecimalParameterNamed(minCapParamName,
this.minCap)) {
final BigDecimal newValue =
command.bigDecimalValueOfParameterNamed(minCapParamName);
actualChanges.put(minCapParamName, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.minCap = newValue;
}
final String maxCapParamName = "maxCap";
if (command.isChangeInBigDecimalParameterNamed(maxCapParamName,
this.maxCap)) {
final BigDecimal newValue =
command.bigDecimalValueOfParameterNamed(maxCapParamName);
actualChanges.put(maxCapParamName, newValue);
- actualChanges.put("locale", localeAsInput);
+ actualChanges.put("locale", locale.getLanguage());
this.maxCap = newValue;
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
index 22e5410ef..9d04250cf 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
@@ -145,7 +146,8 @@ public class LoanCharge extends AbstractPersistableCustom {
public static LoanCharge createNewFromJson(final Loan loan, final Charge
chargeDefinition, final JsonCommand command,
final LocalDate dueDate) {
- final BigDecimal amount =
command.bigDecimalValueOfParameterNamed("amount");
+ final Locale locale = command.extractLocale();
+ final BigDecimal amount =
command.bigDecimalValueOfParameterNamed("amount", locale);
final ChargeTimeType chargeTime = null;
final ChargeCalculationType chargeCalculation = null;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
index 6c52a8d13..632b24bbe 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -865,6 +865,39 @@ public class ClientLoanIntegrationTest {
validateChargeExcludePrecission(flatAccTransfer, loanCharges, "100.0",
"300", "100.0", "0.0");
validateChargeExcludePrecission(flat, loanCharges, "50.0", "150",
"0.0", "50.0");
+ // Loan Charges with US Locale using the amount as a number in the
JSON body
+ this.loanTransactionHelper.addChargesForLoan(loanID,
+
LoanTransactionHelper.getInstallmentChargesForLoanAsJSON(String.valueOf(flat),
50.05, Locale.US));
+ loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+ loanSchedule =
this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec,
this.responseSpec, loanID);
+ loanSchedule.remove(0);
+ for (HashMap installment : loanSchedule) {
+ validateNumberForEqualExcludePrecission("200.05",
String.valueOf(installment.get("feeChargesDue")));
+ }
+
+ // Loan Charges with other Locale using comma (,) as decimal delimiter
+ this.loanTransactionHelper.addChargesForLoan(loanID,
+
LoanTransactionHelper.getInstallmentChargesForLoanAsJSON(String.valueOf(flat),
"50,05", Locale.GERMAN));
+ loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+ loanSchedule =
this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec,
this.responseSpec, loanID);
+ loanSchedule.remove(0);
+ for (HashMap installment : loanSchedule) {
+ validateNumberForEqualExcludePrecission("250.10",
String.valueOf(installment.get("feeChargesDue")));
+ }
+
+ // Loan Charges with German Locale (where the comma is the decimal
delimiter) using the amount as a number in
+ // the JSON body
+ this.loanTransactionHelper.addChargesForLoan(loanID,
+
LoanTransactionHelper.getInstallmentChargesForLoanAsJSON(String.valueOf(flat),
50.05, Locale.GERMAN));
+ loanCharges = this.loanTransactionHelper.getLoanCharges(loanID);
+
+ loanSchedule =
this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec,
this.responseSpec, loanID);
+ loanSchedule.remove(0);
+ for (HashMap installment : loanSchedule) {
+ validateNumberForEqualExcludePrecission("300.15",
String.valueOf(installment.get("feeChargesDue")));
+ }
}
@Test
@@ -1080,7 +1113,8 @@ public class ClientLoanIntegrationTest {
private void validateNumberForEqualExcludePrecission(String val, String
val2) {
DecimalFormat twoDForm = new DecimalFormat("#");
Assertions.assertTrue(
-
Float.valueOf(twoDForm.format(Float.valueOf(val))).compareTo(Float.valueOf(twoDForm.format(Float.valueOf(val2))))
== 0);
+
Float.valueOf(twoDForm.format(Float.valueOf(val))).compareTo(Float.valueOf(twoDForm.format(Float.valueOf(val2))))
== 0,
+ String.format("%s is not equal to %s", val, val2));
}
private Integer createLoanProduct(final boolean multiDisburseLoan, final
String accountingRule, final Account... accounts) {
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
index b2401d2e0..baf1cfa7f 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java
@@ -415,7 +415,7 @@ public final class ChargesHelper {
public static String getModifyChargeJSON() {
final HashMap<String, Object> map = new HashMap<>();
map.put("locale", CommonConstants.LOCALE);
- map.put("amount", "200.0");
+ map.put("amount", 200.0);
String json = new Gson().toJson(map);
LOG.info("{}", json);
return json;
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index f568cba5a..326614bb7 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -33,6 +33,7 @@ import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
@@ -674,8 +675,12 @@ public class LoanTransactionHelper {
}
public static String getInstallmentChargesForLoanAsJSON(final String
chargeId, final String amount) {
- final HashMap<String, String> map = new HashMap<>();
- map.put("locale", "en_GB");
+ return getInstallmentChargesForLoanAsJSON(chargeId, amount, Locale.UK);
+ }
+
+ public static String getInstallmentChargesForLoanAsJSON(final String
chargeId, final Object amount, final Locale locale) {
+ final HashMap<String, Object> map = new HashMap<>();
+ map.put("locale", locale.getLanguage());
map.put("dateFormat", "dd MMMM yyyy");
map.put("amount", amount);
map.put("chargeId", chargeId);