MIFOSX-90: disallow ability to remove loan charge if it is waived (or partially waived).
This commit is contained in:
@@ -507,16 +507,16 @@ public class LoansApiResource {
|
|||||||
@Path("{loanId}/charges/{chargeId}")
|
@Path("{loanId}/charges/{chargeId}")
|
||||||
@Consumes({ MediaType.APPLICATION_JSON })
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
public Response updateLoanCharge(
|
public String updateLoanCharge(
|
||||||
@PathParam("loanId") final Long loanId,
|
@PathParam("loanId") final Long loanId,
|
||||||
@PathParam("chargeId") final Long loanChargeId,
|
@PathParam("chargeId") final Long loanChargeId,
|
||||||
final String jsonRequestBody){
|
final String jsonRequestBody){
|
||||||
|
|
||||||
LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(loanChargeId, loanId, jsonRequestBody);
|
final LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(loanChargeId, loanId, jsonRequestBody);
|
||||||
|
|
||||||
EntityIdentifier identifier = this.loanWritePlatformService.updateLoanCharge(command);
|
final EntityIdentifier identifier = this.loanWritePlatformService.updateLoanCharge(command);
|
||||||
|
|
||||||
return Response.ok().entity(identifier).build();
|
return this.apiJsonSerializerService.serializeEntityIdentifier(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@@ -526,16 +526,13 @@ public class LoansApiResource {
|
|||||||
public String waiveLoanCharge(
|
public String waiveLoanCharge(
|
||||||
@PathParam("loanId") final Long loanId,
|
@PathParam("loanId") final Long loanId,
|
||||||
@PathParam("chargeId") final Long loanChargeId,
|
@PathParam("chargeId") final Long loanChargeId,
|
||||||
@QueryParam("command") final String commandParam,
|
@QueryParam("command") final String commandParam){
|
||||||
final String jsonRequestBody){
|
|
||||||
|
|
||||||
// LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(loanChargeId, loanId, jsonRequestBody);
|
final LoanChargeCommand command = LoanChargeCommand.forWaiver(loanChargeId, loanId);
|
||||||
|
|
||||||
LoanChargeCommand command = LoanChargeCommand.forWaiver(loanChargeId, loanId);
|
|
||||||
|
|
||||||
String json = "";
|
String json = "";
|
||||||
if (is(commandParam, "waive")) {
|
if (is(commandParam, "waive")) {
|
||||||
EntityIdentifier identifier = this.loanWritePlatformService.waiveLoanCharge(command);
|
final EntityIdentifier identifier = this.loanWritePlatformService.waiveLoanCharge(command);
|
||||||
json = this.apiJsonSerializerService.serializeEntityIdentifier(identifier);
|
json = this.apiJsonSerializerService.serializeEntityIdentifier(identifier);
|
||||||
} else {
|
} else {
|
||||||
throw new UnrecognizedQueryParamException("command", commandParam);
|
throw new UnrecognizedQueryParamException("command", commandParam);
|
||||||
@@ -548,13 +545,11 @@ public class LoansApiResource {
|
|||||||
@Path("{loanId}/charges/{chargeId}")
|
@Path("{loanId}/charges/{chargeId}")
|
||||||
@Consumes({ MediaType.APPLICATION_JSON })
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
@Produces({ MediaType.APPLICATION_JSON })
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
public Response deleteLoanCharge(
|
public String deleteLoanCharge(
|
||||||
@PathParam("loanId") final Long loanId,
|
@PathParam("loanId") final Long loanId,
|
||||||
@PathParam("chargeId") final Long loanChargeId){
|
@PathParam("chargeId") final Long loanChargeId){
|
||||||
|
|
||||||
EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId);
|
final EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId);
|
||||||
|
return this.apiJsonSerializerService.serializeEntityIdentifier(identifier);
|
||||||
return Response.ok().entity(identifier).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -299,6 +299,13 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
throw new LoanChargeCannotBeAddedException("loanCharge", "loan.is.closed", defaultUserMessage, getId(), loanCharge.name());
|
throw new LoanChargeCannotBeAddedException("loanCharge", "loan.is.closed", defaultUserMessage, getId(), loanCharge.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateLoanChargeIsNotWaived(final LoanCharge loanCharge) {
|
||||||
|
if (loanCharge.isWaivedOrPartiallyWaived(loanCurrency())) {
|
||||||
|
final String defaultUserMessage = "This loan charge cannot be removed as the charge as already been waived.";
|
||||||
|
throw new LoanChargeCannotBeAddedException("loanCharge", "loanCharge.is.waived", defaultUserMessage, getId(), loanCharge.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void validateChargeHasValidSpecifiedDateIfApplicable(final LoanCharge loanCharge, final LocalDate disbursementDate, final LocalDate lastRepaymentPeriodDueDate) {
|
private void validateChargeHasValidSpecifiedDateIfApplicable(final LoanCharge loanCharge, final LocalDate disbursementDate, final LocalDate lastRepaymentPeriodDueDate) {
|
||||||
if (loanCharge.isSpecifiedDueDate() && !loanCharge.isDueForCollectionBetween(disbursementDate, lastRepaymentPeriodDueDate)) {
|
if (loanCharge.isSpecifiedDueDate() && !loanCharge.isDueForCollectionBetween(disbursementDate, lastRepaymentPeriodDueDate)) {
|
||||||
@@ -315,12 +322,26 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
validateLoanIsNotClosed(loanCharge);
|
validateLoanIsNotClosed(loanCharge);
|
||||||
|
|
||||||
|
// NOTE: to remove this constraint requires that loan transactions
|
||||||
|
// that represent the waive of charges also be removed (or reversed)
|
||||||
|
// if you want ability to remove loan charges that are waived.
|
||||||
|
validateLoanChargeIsNotWaived(loanCharge);
|
||||||
|
|
||||||
boolean removed = this.charges.remove(loanCharge);
|
boolean removed = this.charges.remove(loanCharge);
|
||||||
if (removed) {
|
if (removed) {
|
||||||
updateTotalChargesDueAtDisbursement();
|
updateTotalChargesDueAtDisbursement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if removing disbursement charge - accomodate this on the transaction that tracked its payment
|
removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(loanCharge);
|
||||||
|
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy);
|
||||||
|
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||||
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, this.charges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) {
|
||||||
if (loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isDueAtDisbursement()) {
|
||||||
LoanTransaction transactionToRemove = null;
|
LoanTransaction transactionToRemove = null;
|
||||||
for (LoanTransaction transaction : this.loanTransactions) {
|
for (LoanTransaction transaction : this.loanTransactions) {
|
||||||
@@ -345,12 +366,6 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.loanTransactions.remove(transactionToRemove);
|
this.loanTransactions.remove(transactionToRemove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy);
|
|
||||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, this.charges);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanCharge(final LoanCharge loanCharge, final LoanChargeCommand command) {
|
public void updateLoanCharge(final LoanCharge loanCharge, final LoanChargeCommand command) {
|
||||||
|
|||||||
@@ -411,6 +411,10 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency));
|
final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency));
|
||||||
return Money.of(currency, this.amountPaid).plus(amountWaivedOrWrittenOff).isGreaterThanZero();
|
return Money.of(currency, this.amountPaid).plus(amountWaivedOrWrittenOff).isGreaterThanZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWaivedOrPartiallyWaived(final MonetaryCurrency currency) {
|
||||||
|
return getAmountWaived(currency).isGreaterThanZero();
|
||||||
|
}
|
||||||
|
|
||||||
private Money getAmount(final MonetaryCurrency currency) {
|
private Money getAmount(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.amount);
|
return Money.of(currency, this.amount);
|
||||||
|
|||||||
+1
-1
@@ -707,7 +707,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||||
|
|
||||||
loan.removeLoanCharge(loanCharge);
|
loan.removeLoanCharge(loanCharge);
|
||||||
this.loanRepository.saveAndFlush(loan);
|
this.loanRepository.save(loan);
|
||||||
|
|
||||||
return new EntityIdentifier(loanCharge.getId());
|
return new EntityIdentifier(loanCharge.getId());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user