FINERACT-1847: Removing Edit function from Goodwill Credit or Payout Refund or Merchant Issued Refund transactions on API level
This commit is contained in:
committed by
Adam Saghy
parent
66e4ac6194
commit
6d3cac8c02
+4
@@ -651,6 +651,10 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return getTypeOf().isChargeback() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isEditable() {
|
||||
return !(isChargeback() || isGoodwillCredit() || isPayoutRefund() || isMerchantIssuedRefund());
|
||||
}
|
||||
|
||||
public boolean isPenaltyPayment() {
|
||||
boolean isPenalty = false;
|
||||
if (isChargePayment()) {
|
||||
|
||||
-1
@@ -37,7 +37,6 @@ public class LoanRepaymentAdjustmentCommandHandler implements NewCommandSourceHa
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.writePlatformService.adjustLoanTransaction(command.getLoanId(), command.entityId(), command);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-6
@@ -163,6 +163,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepositor
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.DateMismatchException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.ExceedingTrancheCountException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanTransactionTypeException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidPaidInAdvanceAmountException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanForeclosureException;
|
||||
import org.apache.fineract.portfolio.loanaccount.exception.LoanMultiDisbursementException;
|
||||
@@ -1066,16 +1067,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
transactionId);
|
||||
}
|
||||
|
||||
if (transactionToAdjust.isChargeback()) {
|
||||
throw new PlatformServiceUnavailableException("error.msg.loan.transaction.update.not.allowed", "Loan transaction:"
|
||||
+ transactionId + " update not allowed as loan transaction is charge back and is linked to other transaction",
|
||||
transactionId);
|
||||
}
|
||||
|
||||
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
|
||||
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
|
||||
final ExternalId txnExternalId = externalIdFactory.createFromCommand(command, LoanApiConstants.externalIdParameterName);
|
||||
|
||||
final boolean isAdjustCommand = (transactionAmount.compareTo(BigDecimal.ZERO) > 0);
|
||||
if (isAdjustCommand && !transactionToAdjust.isEditable()) {
|
||||
final String errorMessage = "Loan transaction: " + transactionId + " update not allowed as loan transaction is a "
|
||||
+ transactionToAdjust.getTypeOf().getCode();
|
||||
throw new InvalidLoanTransactionTypeException("transaction", "error.msg.loan.transaction.update.not.allowed", errorMessage);
|
||||
}
|
||||
|
||||
// We dont need auto generation for reversal external id... if it is not provided, it remains null (empty)
|
||||
final String reversalExternalId = command.stringValueOfParameterNamedAllowingNull(LoanApiConstants.REVERSAL_EXTERNAL_ID_PARAMNAME);
|
||||
final ExternalId reversalTxnExternalId = ExternalIdFactory.produce(reversalExternalId);
|
||||
|
||||
+141
@@ -27,6 +27,7 @@ import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||
import org.apache.fineract.integrationtests.common.CommonConstants;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
@@ -50,6 +51,7 @@ public class ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest.class);
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private ResponseSpecification responseSpec403;
|
||||
private RequestSpecification requestSpec;
|
||||
private LoanTransactionHelper loanTransactionHelper;
|
||||
private LoanTransactionHelper loanTransactionHelperValidationError;
|
||||
@@ -73,6 +75,7 @@ public class ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
|
||||
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
this.responseSpec403 = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||
this.loanTransactionHelperValidationError = new LoanTransactionHelper(this.requestSpec, new ResponseSpecBuilder().build());
|
||||
this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
|
||||
@@ -438,4 +441,142 @@ public class ClientLoanCreditBalanceRefundandRepaymentTypeIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undoGoodWillCreditTransactionTest() {
|
||||
// Given
|
||||
disburseLoanOfAccountingRule(CASH_BASED);
|
||||
HashMap loanSummaryMap = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, disbursedLoanID);
|
||||
|
||||
// pay off all of principal, interest (no fees or penalties)
|
||||
final Float principalOutstanding = (Float) loanSummaryMap.get("principalOutstanding");
|
||||
final Float interestOutstanding = (Float) loanSummaryMap.get("interestOutstanding");
|
||||
final Float totalOutstanding = (Float) loanSummaryMap.get("totalOutstanding");
|
||||
final Float overpaidAmount = 159.00f;
|
||||
final Float transactionAmount = totalOutstanding + overpaidAmount;
|
||||
final String transactionDate = "09 January 2022";
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(GOODWILL_CREDIT,
|
||||
transactionDate, transactionAmount, this.disbursedLoanID);
|
||||
Assertions.assertNotNull(loanTransactionResponse);
|
||||
Assertions.assertNotNull(loanTransactionResponse.getResourceId());
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.reverseLoanTransaction(this.disbursedLoanID, loanTransactionResponse.getResourceId(), transactionDate,
|
||||
responseSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undoPayoutRefundTransactionTest() {
|
||||
// Given
|
||||
disburseLoanOfAccountingRule(CASH_BASED);
|
||||
HashMap loanSummaryMap = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, disbursedLoanID);
|
||||
|
||||
// pay off all of principal, interest (no fees or penalties)
|
||||
final Float principalOutstanding = (Float) loanSummaryMap.get("principalOutstanding");
|
||||
final Float interestOutstanding = (Float) loanSummaryMap.get("interestOutstanding");
|
||||
final Float totalOutstanding = (Float) loanSummaryMap.get("totalOutstanding");
|
||||
final Float overpaidAmount = 159.00f;
|
||||
final Float transactionAmount = totalOutstanding + overpaidAmount;
|
||||
final String transactionDate = "09 January 2022";
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(PAYOUT_REFUND,
|
||||
transactionDate, transactionAmount, this.disbursedLoanID);
|
||||
Assertions.assertNotNull(loanTransactionResponse);
|
||||
Assertions.assertNotNull(loanTransactionResponse.getResourceId());
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.reverseLoanTransaction(this.disbursedLoanID, loanTransactionResponse.getResourceId(), transactionDate,
|
||||
responseSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void undoMerchantIssuedRefundTransactionTest() {
|
||||
// Given
|
||||
disburseLoanOfAccountingRule(CASH_BASED);
|
||||
HashMap loanSummaryMap = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, disbursedLoanID);
|
||||
|
||||
// pay off all of principal, interest (no fees or penalties)
|
||||
final Float principalOutstanding = (Float) loanSummaryMap.get("principalOutstanding");
|
||||
final Float interestOutstanding = (Float) loanSummaryMap.get("interestOutstanding");
|
||||
final Float totalOutstanding = (Float) loanSummaryMap.get("totalOutstanding");
|
||||
final Float overpaidAmount = 159.00f;
|
||||
final Float transactionAmount = totalOutstanding + overpaidAmount;
|
||||
final String transactionDate = "09 January 2022";
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(MERCHANT_ISSUED_REFUND,
|
||||
transactionDate, transactionAmount, this.disbursedLoanID);
|
||||
Assertions.assertNotNull(loanTransactionResponse);
|
||||
Assertions.assertNotNull(loanTransactionResponse.getResourceId());
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.reverseLoanTransaction(this.disbursedLoanID, loanTransactionResponse.getResourceId(), transactionDate,
|
||||
responseSpec);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adjustGoodWillCreditTransactionTest() {
|
||||
// Given
|
||||
disburseLoanOfAccountingRule(CASH_BASED);
|
||||
HashMap loanSummaryMap = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, disbursedLoanID);
|
||||
|
||||
// pay off all of principal, interest (no fees or penalties)
|
||||
final Float principalOutstanding = (Float) loanSummaryMap.get("principalOutstanding");
|
||||
final Float interestOutstanding = (Float) loanSummaryMap.get("interestOutstanding");
|
||||
final Float totalOutstanding = (Float) loanSummaryMap.get("totalOutstanding");
|
||||
final Float overpaidAmount = 159.00f;
|
||||
final Float transactionAmount = totalOutstanding + overpaidAmount;
|
||||
final String transactionDate = "09 January 2022";
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(GOODWILL_CREDIT,
|
||||
transactionDate, transactionAmount, this.disbursedLoanID);
|
||||
Assertions.assertNotNull(loanTransactionResponse);
|
||||
Assertions.assertNotNull(loanTransactionResponse.getResourceId());
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.adjustLoanTransaction(this.disbursedLoanID, loanTransactionResponse.getResourceId(), transactionDate,
|
||||
responseSpec403);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adjustPayoutRefundTransactionTest() {
|
||||
// Given
|
||||
disburseLoanOfAccountingRule(CASH_BASED);
|
||||
HashMap loanSummaryMap = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, disbursedLoanID);
|
||||
|
||||
// pay off all of principal, interest (no fees or penalties)
|
||||
final Float principalOutstanding = (Float) loanSummaryMap.get("principalOutstanding");
|
||||
final Float interestOutstanding = (Float) loanSummaryMap.get("interestOutstanding");
|
||||
final Float totalOutstanding = (Float) loanSummaryMap.get("totalOutstanding");
|
||||
final Float overpaidAmount = 159.00f;
|
||||
final Float transactionAmount = totalOutstanding + overpaidAmount;
|
||||
final String transactionDate = "09 January 2022";
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(PAYOUT_REFUND,
|
||||
transactionDate, transactionAmount, this.disbursedLoanID);
|
||||
Assertions.assertNotNull(loanTransactionResponse);
|
||||
Assertions.assertNotNull(loanTransactionResponse.getResourceId());
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.adjustLoanTransaction(this.disbursedLoanID, loanTransactionResponse.getResourceId(), transactionDate,
|
||||
responseSpec403);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void adjustMerchantIssuedRefundTransactionTest() {
|
||||
// Given
|
||||
disburseLoanOfAccountingRule(CASH_BASED);
|
||||
HashMap loanSummaryMap = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, disbursedLoanID);
|
||||
|
||||
// pay off all of principal, interest (no fees or penalties)
|
||||
final Float principalOutstanding = (Float) loanSummaryMap.get("principalOutstanding");
|
||||
final Float interestOutstanding = (Float) loanSummaryMap.get("interestOutstanding");
|
||||
final Float totalOutstanding = (Float) loanSummaryMap.get("totalOutstanding");
|
||||
final Float overpaidAmount = 159.00f;
|
||||
final Float transactionAmount = totalOutstanding + overpaidAmount;
|
||||
final String transactionDate = "09 January 2022";
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(MERCHANT_ISSUED_REFUND,
|
||||
transactionDate, transactionAmount, this.disbursedLoanID);
|
||||
Assertions.assertNotNull(loanTransactionResponse);
|
||||
Assertions.assertNotNull(loanTransactionResponse.getResourceId());
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.adjustLoanTransaction(this.disbursedLoanID, loanTransactionResponse.getResourceId(), transactionDate,
|
||||
responseSpec403);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
-2
@@ -57,6 +57,7 @@ public class LoanTransactionChargebackTest {
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private ResponseSpecification responseSpecErr400;
|
||||
private ResponseSpecification responseSpecErr403;
|
||||
private ResponseSpecification responseSpecErr503;
|
||||
private RequestSpecification requestSpec;
|
||||
private LoanTransactionHelper loanTransactionHelper;
|
||||
@@ -71,6 +72,7 @@ public class LoanTransactionChargebackTest {
|
||||
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
this.responseSpecErr400 = new ResponseSpecBuilder().expectStatusCode(400).build();
|
||||
this.responseSpecErr403 = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
this.responseSpecErr503 = new ResponseSpecBuilder().expectStatusCode(503).build();
|
||||
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
|
||||
|
||||
@@ -114,12 +116,30 @@ public class LoanTransactionChargebackTest {
|
||||
|
||||
// Try to reverse a Loan Transaction charge back
|
||||
PostLoansLoanIdTransactionsResponse reverseTransactionResponse = loanTransactionHelper.reverseLoanTransaction(loanId,
|
||||
chargebackTransactionId, operationDate, responseSpecErr503);
|
||||
chargebackTransactionId, operationDate, responseSpecErr403);
|
||||
|
||||
// Try to reverse a Loan Transaction repayment with linked transactions
|
||||
reverseTransactionResponse = loanTransactionHelper.reverseLoanTransaction(loanId, transactionId, operationDate, responseSpecErr503);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyAndAdjustLoanTransactionChargeback() {
|
||||
// Client and Loan account creation
|
||||
final Integer loanId = createAccounts(15, 1);
|
||||
|
||||
Float amount = Float.valueOf(amountVal);
|
||||
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(operationDate, amount,
|
||||
loanId);
|
||||
assertNotNull(loanTransactionResponse);
|
||||
final Long transactionId = loanTransactionResponse.getResourceId();
|
||||
|
||||
final Long chargebackTransactionId = loanTransactionHelper.applyChargebackTransaction(loanId, transactionId, "1000.00", 0,
|
||||
responseSpec);
|
||||
|
||||
// Then
|
||||
loanTransactionHelper.adjustLoanTransaction(loanId, chargebackTransactionId, operationDate, responseSpecErr403);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void applyLoanTransactionChargebackWithAmountZero() {
|
||||
// Client and Loan account creation
|
||||
@@ -141,7 +161,6 @@ public class LoanTransactionChargebackTest {
|
||||
loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, "loanStatusType.closed.obligations.met");
|
||||
|
||||
loanTransactionHelper.applyChargebackTransaction(loanId, transactionId, "0.00", 0, responseSpecErr400);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+23
-6
@@ -504,7 +504,14 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
}
|
||||
|
||||
public HashMap reverseRepayment(final Integer loanId, final Integer transactionId, String date) {
|
||||
return (HashMap) performLoanTransaction(createLoanTransactionURL(UNDO, loanId, transactionId), getUndoJsonBody(date), "");
|
||||
return (HashMap) performLoanTransaction(createLoanTransactionURL(UNDO, loanId, transactionId),
|
||||
getAdjustTransactionJsonBody(date, "0"), "");
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeLoanRepayment(final String repaymentTypeCommand, final String date,
|
||||
final Float amountToBePaid, final Integer loanID) {
|
||||
log.info("Repayment with amount {} in {} for Loan {}", amountToBePaid, date, loanID);
|
||||
return postLoanTransaction(createLoanTransactionURL(repaymentTypeCommand, loanID), getRepaymentBodyAsJSON(date, amountToBePaid));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse makeLoanRepayment(final String date, final Float amountToBePaid, final Integer loanID) {
|
||||
@@ -701,9 +708,16 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return ok(fineract().loanTransactions.adjustLoanTransaction1(loanId, transactionExternalId, request, "adjust"));
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse adjustLoanTransaction(final Integer loanId, final Long transactionId, String date,
|
||||
ResponseSpecification responseSpec) {
|
||||
return postLoanTransaction(createLoanTransactionURL(null, loanId, transactionId.intValue()),
|
||||
getAdjustTransactionJsonBody(date, "10"), responseSpec);
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final Integer loanId, final Long transactionId, String date,
|
||||
ResponseSpecification responseSpec) {
|
||||
return postLoanTransaction(createLoanTransactionURL(UNDO, loanId, transactionId.intValue()), getUndoJsonBody(date), responseSpec);
|
||||
return postLoanTransaction(createLoanTransactionURL(UNDO, loanId, transactionId.intValue()),
|
||||
getAdjustTransactionJsonBody(date, "0"), responseSpec);
|
||||
}
|
||||
|
||||
public PostLoansLoanIdTransactionsResponse reverseLoanTransaction(final Long loanId, final Long transactionId,
|
||||
@@ -1074,10 +1088,10 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
private String getUndoJsonBody(String date) {
|
||||
private String getAdjustTransactionJsonBody(String date, String amount) {
|
||||
final HashMap<String, String> map = new HashMap<>();
|
||||
map.put("transactionDate", date);
|
||||
map.put("transactionAmount", "0");
|
||||
map.put("transactionAmount", amount);
|
||||
map.put("dateFormat", "dd MMMM yyyy");
|
||||
map.put("locale", "en");
|
||||
return new Gson().toJson(map);
|
||||
@@ -1257,8 +1271,11 @@ public class LoanTransactionHelper extends IntegrationTest {
|
||||
}
|
||||
|
||||
private String createLoanTransactionURL(final String command, final Integer loanID, final Integer transactionId) {
|
||||
return "/fineract-provider/api/v1/loans/" + loanID + "/transactions/" + transactionId + "?command=" + command + "&"
|
||||
+ Utils.TENANT_IDENTIFIER;
|
||||
String url = "/fineract-provider/api/v1/loans/" + loanID + "/transactions/" + transactionId + "?";
|
||||
if (command != null) {
|
||||
url = url + "command=" + command + "&";
|
||||
}
|
||||
return url + Utils.TENANT_IDENTIFIER;
|
||||
}
|
||||
|
||||
private String createGlimAccountURL(final String command, final Integer glimID) {
|
||||
|
||||
Reference in New Issue
Block a user