From 7af4b12d24bbfa86e08065a7cf7a51f45f32453d Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Thu, 8 Nov 2012 11:26:51 +0000 Subject: [PATCH] MIFOSX-90: disallow ability to remove loan charge if it is waived (or partially waived). --- .../platform/api/LoansApiResource.java | 25 +++++++--------- .../mifosng/platform/loan/domain/Loan.java | 29 ++++++++++++++----- .../platform/loan/domain/LoanCharge.java | 4 +++ ...WritePlatformServiceJpaRepositoryImpl.java | 2 +- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java index 4c50e584f..8016ba11f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java @@ -507,16 +507,16 @@ public class LoansApiResource { @Path("{loanId}/charges/{chargeId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public Response updateLoanCharge( + public String updateLoanCharge( @PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId, 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 @@ -526,16 +526,13 @@ public class LoansApiResource { public String waiveLoanCharge( @PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId, - @QueryParam("command") final String commandParam, - final String jsonRequestBody){ + @QueryParam("command") final String commandParam){ -// LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(loanChargeId, loanId, jsonRequestBody); - - LoanChargeCommand command = LoanChargeCommand.forWaiver(loanChargeId, loanId); + final LoanChargeCommand command = LoanChargeCommand.forWaiver(loanChargeId, loanId); String json = ""; if (is(commandParam, "waive")) { - EntityIdentifier identifier = this.loanWritePlatformService.waiveLoanCharge(command); + final EntityIdentifier identifier = this.loanWritePlatformService.waiveLoanCharge(command); json = this.apiJsonSerializerService.serializeEntityIdentifier(identifier); } else { throw new UnrecognizedQueryParamException("command", commandParam); @@ -548,13 +545,11 @@ public class LoansApiResource { @Path("{loanId}/charges/{chargeId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public Response deleteLoanCharge( + public String deleteLoanCharge( @PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId){ - EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId); - - return Response.ok().entity(identifier).build(); + final EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId); + return this.apiJsonSerializerService.serializeEntityIdentifier(identifier); } - } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java index 1cb5f9d94..dcddf13f0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/Loan.java @@ -299,6 +299,13 @@ public class Loan extends AbstractAuditableCustom { 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) { if (loanCharge.isSpecifiedDueDate() && !loanCharge.isDueForCollectionBetween(disbursementDate, lastRepaymentPeriodDueDate)) { @@ -315,12 +322,26 @@ public class Loan extends AbstractAuditableCustom { 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); if (removed) { 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 allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); + loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, this.charges); + } + } + + private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) { if (loanCharge.isDueAtDisbursement()) { LoanTransaction transactionToRemove = null; for (LoanTransaction transaction : this.loanTransactions) { @@ -345,12 +366,6 @@ public class Loan extends AbstractAuditableCustom { this.loanTransactions.remove(transactionToRemove); } } - - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor.determineProcessor(this.transactionProcessingStrategy); - if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) { - final List allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); - loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, this.charges); - } } public void updateLoanCharge(final LoanCharge loanCharge, final LoanChargeCommand command) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java index 435e52206..65d5acee4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanCharge.java @@ -411,6 +411,10 @@ public class LoanCharge extends AbstractPersistable { final Money amountWaivedOrWrittenOff = getAmountWaived(currency).plus(getAmountWrittenOff(currency)); 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) { return Money.of(currency, this.amount); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 8e49b006d..a775616fe 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -707,7 +707,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId); loan.removeLoanCharge(loanCharge); - this.loanRepository.saveAndFlush(loan); + this.loanRepository.save(loan); return new EntityIdentifier(loanCharge.getId()); }