FINERACT-1500:SavingsHoldAccountLien

This commit is contained in:
rrpawar96
2022-02-21 19:34:01 +01:00
committed by Aleksandar Vidakovic
parent 4a5919a4a7
commit a2be1eb985
5 changed files with 113 additions and 6 deletions
@@ -142,6 +142,7 @@ public class SavingsApiConstants {
// transaction parameters
public static final String transactionDateParamName = "transactionDate";
public static final String lienParamName = "lien";
public static final String transactionAmountParamName = "transactionAmount";
public static final String paymentDetailDataParamName = "paymentDetailData";
public static final String runningBalanceParamName = "runningBalance";
@@ -23,6 +23,7 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.activate
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.bankNumberParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.checkNumberParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.closedOnDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.paymentTypeIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.receiptNumberParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.routingCodeParamName;
@@ -68,7 +69,7 @@ public class SavingsAccountTransactionDataValidator {
private final FromJsonHelper fromApiJsonHelper;
private static final Set<String> SAVINGS_ACCOUNT_HOLD_AMOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(transactionDateParamName, SavingsApiConstants.dateFormatParamName, SavingsApiConstants.localeParamName,
transactionAmountParamName));
transactionAmountParamName, lienParamName));
private final ConfigurationDomainService configurationDomainService;
@Autowired
@@ -206,6 +207,7 @@ public class SavingsAccountTransactionDataValidator {
public SavingsAccountTransaction validateHoldAndAssembleForm(final String json, final SavingsAccount account, final AppUser createdUser,
final boolean backdatedTxnsAllowedTill) {
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
@@ -222,6 +224,7 @@ public class SavingsAccountTransactionDataValidator {
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(transactionAmountParamName, element);
baseDataValidator.reset().parameter(transactionAmountParamName).value(amount).notNull().positiveAmount();
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDate).notNull();
boolean isActive = account.isActive();
@@ -230,8 +233,22 @@ public class SavingsAccountTransactionDataValidator {
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
account.holdAmount(amount);
if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO) < 0) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient balance", account.getId());
if (account.getEnforceMinRequiredBalance()) {
if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO) < 0) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient balance", account.getId());
}
}
Boolean lien = false;
if (this.fromApiJsonHelper.parameterExists(lienParamName, element)) {
lien = this.fromApiJsonHelper.extractBooleanNamed(lienParamName, element);
if (!lien) {
if (account.getWithdrawableBalanceWithoutMinimumBalance().compareTo(BigDecimal.ZERO) < 0) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient balance", account.getId());
}
}
}
LocalDate lastTransactionDate = null;
@@ -1935,6 +1935,10 @@ public class SavingsAccount extends AbstractPersistableCustom {
return this.savingsOfficer;
}
public Boolean getEnforceMinRequiredBalance() {
return this.enforceMinRequiredBalance;
}
public void unassignSavingsOfficer() {
this.savingsOfficer = null;
}
@@ -3367,6 +3371,10 @@ public class SavingsAccount extends AbstractPersistableCustom {
.subtract(this.getSavingsHoldAmount());
}
public BigDecimal getWithdrawableBalanceWithoutMinimumBalance() {
return getAccountBalance().subtract(this.getOnHoldFunds()).subtract(this.getSavingsHoldAmount());
}
public TaxGroup getTaxGroup() {
return this.taxGroup;
}
@@ -2156,7 +2156,7 @@ public class ClientSavingsIntegrationTest {
assertEquals(Float.parseFloat(DEPOSIT_AMOUNT), depositTransaction.get("amount"), "Verifying Deposit Amount");
Integer holdTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, String.valueOf(balance - 100),
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
false, SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
error = (List) savingsAccountHelperValidationError.withdrawalFromSavingsAccount(savingsId, "300",
SavingsAccountHelper.TRANSACTION_DATE_PLUS_ONE, CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
@@ -2175,6 +2175,74 @@ public class ClientSavingsIntegrationTest {
}
@SuppressWarnings("unchecked")
@Test
public void testSavingsAccountLienStatus() {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec,
new ResponseSpecBuilder().build());
final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build();
final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse);
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final String minBalanceForInterestCalculation = null;
final String minRequiredBalance = null;
final String enforceMinRequiredBalance = "false";
final boolean allowOverdraft = false;
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE,
minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft);
Assertions.assertNotNull(savingsProductID);
final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
Assertions.assertNotNull(savingsProductID);
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
List<HashMap> error = (List) savingsAccountHelperValidationError.holdAmountInSavingsAccount(savingsId, "1500", false,
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR); // lien:false
assertEquals("validation.msg.savingsaccount.insufficient balance", error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
Integer holdTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId, "1500", true,
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId);
Float balance = Float.parseFloat("-500");
assertEquals(balance, summary.get("availableBalance"), "Verifying available Balance is -500");
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, "1000",
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
Calendar todaysDate = Calendar.getInstance();
final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime());
ArrayList<HashMap> savingsAccountErrorData = (ArrayList<HashMap>) validationErrorHelper.withdrawalFromSavingsAccount(savingsId,
"1000", TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, "500", TRANSACTION_DATE,
CommonConstants.RESPONSE_RESOURCE_ID);
Assertions.assertNotNull(withdrawTransactionId);
}
/**
* incorrect savings account balance when charge transaction is reversed during an overdraft recalculate Daily
* Balances
@@ -369,10 +369,11 @@ public class SavingsAccountHelper {
getActivatedSavingsAsJSON(), isBlock);
}
public Object holdAmountInSavingsAccount(final Integer savingsID, final String amount, String date, String jsonAttributeToGetback) {
public Object holdAmountInSavingsAccount(final Integer savingsID, final String amount, final Boolean lienStatus, String date,
String jsonAttributeToGetback) {
LOG.info("--------------------------------- SAVINGS TRANSACTION HOLD AMOUNT--------------------------------");
return performSavingActions(createSavingsTransactionURL(HOLD_AMOUNT_SAVINGS_COMMAND, savingsID),
getSavingsTransactionJSON(amount, date), jsonAttributeToGetback);
getLienSavingsTransactionJSON(amount, date, lienStatus), jsonAttributeToGetback);
}
public Integer releaseAmount(final Integer savingsId, final Integer transactionId) {
@@ -439,6 +440,18 @@ public class SavingsAccountHelper {
return savingsAccountWithdrawalJson;
}
private String getLienSavingsTransactionJSON(final String amount, final String transactionDate, final Boolean lien) {
final HashMap<String, Object> map = new HashMap<>();
map.put("locale", CommonConstants.LOCALE);
map.put("dateFormat", CommonConstants.DATE_FORMAT);
map.put("transactionDate", transactionDate);
map.put("transactionAmount", amount);
map.put("lien", lien);
String savingsAccountWithdrawalJson = new Gson().toJson(map);
LOG.info(savingsAccountWithdrawalJson);
return savingsAccountWithdrawalJson;
}
private String getSavingsTransactionPaymentTypeJSON(final String amount, final String transactionDate, final String paymentTypeId) {
final HashMap<String, String> map = new HashMap<>();
map.put("locale", CommonConstants.LOCALE);