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 4ccb1efed..546373ce8 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 @@ -26,7 +26,7 @@ import org.mifosng.platform.api.commands.SubmitLoanApplicationCommand; import org.mifosng.platform.api.commands.UndoStateTransitionCommand; import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.LoanAccountData; -import org.mifosng.platform.api.data.LoanRepaymentData; +import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.LoanSchedule; import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; @@ -49,7 +49,7 @@ public class LoansApiResource { private String loanFilterName = "loanFilter"; private String loanAllowedFieldList = ""; private String loanRepaymentFilterName = "loanRepaymentFilter"; - private String loanRepaymentDefaultFieldList = "date,total"; + private String loanRepaymentDefaultFieldList = "transactionType,date,total"; private String loanRepaymentAllowedFieldList = ""; @Autowired @@ -280,13 +280,13 @@ public class LoansApiResource { String json = ""; String selectedFields = loanRepaymentDefaultFieldList; if (is(commandParam, "repayment")) { - LoanRepaymentData loanRepaymentData = this.loanReadPlatformService + LoanTransactionData loanRepaymentData = this.loanReadPlatformService .retrieveNewLoanRepaymentDetails(loanId); json = this.jsonFormattingService.convertRequest(loanRepaymentData, loanRepaymentFilterName, loanRepaymentAllowedFieldList, selectedFields, uriInfo.getQueryParameters()); } else if (is(commandParam, "waiver")) { - LoanRepaymentData loanWaiverData = this.loanReadPlatformService + LoanTransactionData loanWaiverData = this.loanReadPlatformService .retrieveNewLoanWaiverDetails(loanId); json = this.jsonFormattingService.convertRequest(loanWaiverData, loanRepaymentFilterName, loanRepaymentAllowedFieldList, selectedFields, @@ -304,15 +304,15 @@ public class LoansApiResource { @Path("{loanId}/transactions/{transactionId}") @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Produces({ MediaType.APPLICATION_JSON}) - public String retrieveRepaymentDetails( + public String retrieveTransaction( @PathParam("loanId") final Long loanId, @PathParam("transactionId") final Long transactionId, @Context UriInfo uriInfo) { - LoanRepaymentData loanRepaymentData = this.loanReadPlatformService - .retrieveLoanRepaymentDetails(loanId, transactionId); + LoanTransactionData loanRepaymentData = this.loanReadPlatformService + .retrieveLoanTransactionDetails(loanId, transactionId); - String selectedFields = ""; + String selectedFields = loanRepaymentDefaultFieldList; return this.jsonFormattingService.convertRequest(loanRepaymentData, loanRepaymentFilterName, loanRepaymentAllowedFieldList, selectedFields, uriInfo.getQueryParameters()); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ApiGlobalErrorResponse.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ApiGlobalErrorResponse.java index bfcd051c6..ca5096026 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ApiGlobalErrorResponse.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/ApiGlobalErrorResponse.java @@ -99,7 +99,7 @@ public class ApiGlobalErrorResponse { public static ApiGlobalErrorResponse dataIntegrityError(final String globalisationMessageCode, final String defaultUserMessage, final String parameterName, final Object... defaultUserMessageArgs) { ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse(); - globalErrorResponse.setHttpStatusCode("400"); + globalErrorResponse.setHttpStatusCode("403"); globalErrorResponse.setDeveloperMessage("The request caused a data integrity issue to be fired by the database."); globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes"); globalErrorResponse.setUserMessageGlobalisationCode(globalisationMessageCode); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java index d33cf0abb..353b859ea 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java @@ -6,13 +6,13 @@ public class DerivedLoanData { private LoanRepaymentScheduleData repaymentSchedule; private LoanAccountSummaryData summary; - private List loanRepayments; + private List loanRepayments; public DerivedLoanData() { // } - public DerivedLoanData(LoanRepaymentScheduleData repaymentScheduleData, LoanAccountSummaryData summaryData, List loanRepayments) { + public DerivedLoanData(LoanRepaymentScheduleData repaymentScheduleData, LoanAccountSummaryData summaryData, List loanRepayments) { this.repaymentSchedule = repaymentScheduleData; this.summary = summaryData; this.loanRepayments = loanRepayments; @@ -34,11 +34,11 @@ public class DerivedLoanData { this.summary = summary; } - public List getLoanRepayments() { + public List getLoanRepayments() { return loanRepayments; } - public void setLoanRepayments(List loanRepayments) { + public void setLoanRepayments(List loanRepayments) { this.loanRepayments = loanRepayments; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java index b3b9c0f05..7cc391bf0 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java @@ -41,7 +41,7 @@ public class LoanAccountData { private LoanAccountSummaryData summary; private LoanRepaymentScheduleData repaymentSchedule; - private List loanRepayments; + private List loanRepayments; private LoanPermissionData permissions; @@ -55,7 +55,7 @@ public class LoanAccountData { public LoanAccountData(LoanBasicDetailsData basicDetails, LoanAccountSummaryData summary, LoanRepaymentScheduleData repaymentSchedule, - List loanRepayments, LoanPermissionData permissions) { + List loanRepayments, LoanPermissionData permissions) { this.summary = summary; this.repaymentSchedule = repaymentSchedule; this.loanRepayments = loanRepayments; @@ -130,11 +130,11 @@ public class LoanAccountData { this.repaymentSchedule = repaymentSchedule; } - public List getLoanRepayments() { + public List getLoanRepayments() { return loanRepayments; } - public void setLoanRepayments(List loanRepayments) { + public void setLoanRepayments(List loanRepayments) { this.loanRepayments = loanRepayments; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionData.java similarity index 78% rename from mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentData.java rename to mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionData.java index 24252d747..81e3f765b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionData.java @@ -4,9 +4,10 @@ import org.codehaus.jackson.map.annotate.JsonFilter; import org.joda.time.LocalDate; @JsonFilter("loanRepaymentFilter") -public class LoanRepaymentData { +public class LoanTransactionData { private Long id; + private EnumOptionData transactionType; private LocalDate date; private MoneyData principal; private MoneyData interest; @@ -14,16 +15,17 @@ public class LoanRepaymentData { private MoneyData totalWaived; private MoneyData overpaid; - public LoanRepaymentData() { + public LoanTransactionData() { // } - public LoanRepaymentData( - Long id, final LocalDate date, + public LoanTransactionData( + Long id, EnumOptionData transactionType, final LocalDate date, final MoneyData principal, final MoneyData interest, final MoneyData total, final MoneyData overpaid) { this.id = id; + this.transactionType = transactionType; this.date = date; this.principal = principal; this.interest = interest; @@ -38,15 +40,19 @@ public class LoanRepaymentData { public void setId(Long id) { this.id = id; } + + public EnumOptionData getTransactionType() { + return transactionType; + } + + public void setTransactionType(EnumOptionData transactionType) { + this.transactionType = transactionType; + } public LocalDate getDate() { return date; } -// public int getTransactionOffsetFromToday() { -// return Days.daysBetween(new DateMidnight().toDateTime(), this.date.toDateMidnight().toDateTime()).getDays(); -// } - public void setDate(LocalDate date) { this.date = date; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/PlatformDataIntegrityExceptionMapper.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/PlatformDataIntegrityExceptionMapper.java index e08cb3105..890a9a628 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/PlatformDataIntegrityExceptionMapper.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/PlatformDataIntegrityExceptionMapper.java @@ -26,6 +26,6 @@ public class PlatformDataIntegrityExceptionMapper implements ExceptionMapper loanRepaymentPeriods = repaymentScheduleDetails.getPeriods(); // break up payments based on principal and interest - List loanRepayments = new ArrayList(); + List loanRepayments = new ArrayList(); int repaymentScheduleIndex = 0; for (LoanTransaction transaction : loanTransactions) { if (transaction.isRepayment() || transaction.isWaiver()) { @@ -40,7 +42,7 @@ public class DerivedLoanDataProcessor { .get(repaymentScheduleIndex); if (transaction.isRepayment()) { - LoanRepaymentData repaymentData = processLoanRepayment( + LoanTransactionData repaymentData = processLoanRepayment( transaction, scheduledRepaymentPeriod, repaymentScheduleIndex, loanRepaymentPeriods, arrearsTolerance, currencyDetail); @@ -48,7 +50,7 @@ public class DerivedLoanDataProcessor { } if (transaction.isWaiver()) { - LoanRepaymentData repaymentData = processWaiver(transaction, scheduledRepaymentPeriod, currencyDetail); + LoanTransactionData repaymentData = processWaiver(transaction, scheduledRepaymentPeriod, currencyDetail); loanRepayments.add(repaymentData); } @@ -73,7 +75,7 @@ public class DerivedLoanDataProcessor { return new DerivedLoanData(processRepaymentScheduleData, summaryData, loanRepayments); } - private LoanRepaymentData processWaiver(LoanTransaction transaction, + private LoanTransactionData processWaiver(LoanTransaction transaction, LoanRepaymentPeriodData scheduledRepaymentPeriod, CurrencyData currencyData) { MonetaryCurrency currency = new MonetaryCurrency(currencyData.getCode(), currencyData.getDecimalPlaces()); @@ -125,7 +127,8 @@ public class DerivedLoanDataProcessor { Money remainingOutstanding = totalOutstanding.minus(moneyFrom(totalWaived)); scheduledRepaymentPeriod.setTotalOutstanding(moneyDataFrom(currencyData, remainingOutstanding)); - LoanRepaymentData loanRepaymentData = new LoanRepaymentData(transaction.getId(), transaction.getTransactionDate(), moneyDataFrom(currencyData, principalWaived), + EnumOptionData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WAIVED); + LoanTransactionData loanRepaymentData = new LoanTransactionData(transaction.getId(), transactionType, transaction.getTransactionDate(), moneyDataFrom(currencyData, principalWaived), moneyDataFrom(currencyData, interestWaived), totalWaived, zero); loanRepaymentData.setTotalWaived(totalWaived); return loanRepaymentData; @@ -270,7 +273,7 @@ public class DerivedLoanDataProcessor { /** * TODO - pays off interest first then principal so should make this configurable when generating 'derived view of loan account' */ - private LoanRepaymentData processLoanRepayment(LoanTransaction repayment, + private LoanTransactionData processLoanRepayment(LoanTransaction repayment, LoanRepaymentPeriodData scheduledRepayment, int repaymentScheduleIndex, List repaymentSchedulePeriods, @@ -443,7 +446,8 @@ public class DerivedLoanDataProcessor { MoneyData totalPaid = moneyDataFrom(currencyDetail, totalPrincipalComponent.plus(totalInterestComponent)); - LoanRepaymentData loanRepaymentData = new LoanRepaymentData(repayment.getId(), repayment.getTransactionDate(), cumulativePrincipalPaid, cumulativeInterestPaid, totalPaid, overpaid); + EnumOptionData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT); + LoanTransactionData loanRepaymentData = new LoanTransactionData(repayment.getId(), transactionType, repayment.getTransactionDate(), cumulativePrincipalPaid, cumulativeInterestPaid, totalPaid, overpaid); return loanRepaymentData; } 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 e5b57600c..647b2a6cd 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 @@ -32,13 +32,14 @@ import org.mifosng.platform.api.data.LoanAccountData; import org.mifosng.platform.api.data.LoanAccountSummaryData; import org.mifosng.platform.api.data.LoanBasicDetailsData; import org.mifosng.platform.api.data.LoanPermissionData; -import org.mifosng.platform.api.data.LoanRepaymentData; import org.mifosng.platform.api.data.LoanRepaymentScheduleData; +import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.currency.domain.Money; import org.mifosng.platform.exceptions.InvalidLoanStateTransitionException; +import org.mifosng.platform.exceptions.InvalidLoanTransactionTypeException; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; import org.mifosng.platform.loanproduct.service.LoanEnumerations; import org.mifosng.platform.organisation.domain.Organisation; @@ -336,6 +337,17 @@ public class Loan extends AbstractAuditableCustom { throw new InvalidLoanStateTransitionException("waive", "cannot.be.a.futre.date", errorMessage, loanTransactionDate); } + if (getTotalOutstanding().isGreaterThan(this.getInArrearsTolerance())) { + final String errorMessage = "Waiver is only allowed when the total outstanding amount left on loan (" + getTotalOutstanding() +") is less than thethe in arrears tolerance setting of " + getInArrearsTolerance().getAmount(); + throw new InvalidLoanStateTransitionException("waive", "cannot.exceed.in.arrears.tolerance.setting", errorMessage, getTotalOutstanding(), getInArrearsTolerance()); + } + + Money waived = Money.of(getCurrency(), loanTransaction.getAmount()); + if (waived.isGreaterThan(this.getInArrearsTolerance())) { + final String errorMessage = "The amount being waived cannot exceed the in arrears tolerance setting of " + getInArrearsTolerance().getAmount(); + throw new InvalidLoanStateTransitionException("waive", "cannot.exceed.in.arrears.tolerance.setting", errorMessage, waived, getInArrearsTolerance()); + } + if (this.isRepaidInFull()) { this.loanStatus = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, this.loanStatus); this.closedOnDate = loanTransaction.getTransactionDate().toDate(); @@ -361,8 +373,8 @@ public class Loan extends AbstractAuditableCustom { deriveLoanRepaymentScheduleCompletedData(); if (loanTransaction.isNotRepayment()) { - throw new IllegalArgumentException( - "Only repayment transactions can be passed to makeRepayment."); + final String errorMessage = "A transaction of type repayment was expected but not received."; + throw new InvalidLoanTransactionTypeException("transaction", "is.not.a.repayment.transaction", errorMessage); } LocalDate loanTransactionDate = loanTransaction.getTransactionDate(); @@ -469,7 +481,8 @@ public class Loan extends AbstractAuditableCustom { LoanTransaction newTransactionDetail, LoanLifecycleStateMachine loanLifecycleStateMachine) { if (transactionForAdjustment.isNotRepayment() && transactionForAdjustment.isNotWaiver()) { - throw new IllegalArgumentException("Only repayment and waiver transactions can be adjusted."); + final String errorMessage = "A transaction of type repayment or waiver was expected but not received."; + throw new InvalidLoanTransactionTypeException("transaction", "is.not.a.repayment.or.waiver.transaction", errorMessage); } transactionForAdjustment.contra(); @@ -982,7 +995,7 @@ public class Loan extends AbstractAuditableCustom { } public LoanAccountData toLoanAccountData(LoanAccountSummaryData summary, LoanRepaymentScheduleData repaymentSchedule, - List loanRepayments, + List loanRepayments, CurrencyData currencyData) { LoanBasicDetailsData basicDetails = toBasicDetailsData(currencyData); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentDataComparator.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentDataComparator.java index 81f738234..abc896f1f 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentDataComparator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentDataComparator.java @@ -2,13 +2,13 @@ package org.mifosng.platform.loan.domain; import java.util.Comparator; -import org.mifosng.platform.api.data.LoanRepaymentData; +import org.mifosng.platform.api.data.LoanTransactionData; -public class LoanRepaymentDataComparator implements Comparator { +public class LoanRepaymentDataComparator implements Comparator { @Override - public int compare(final LoanRepaymentData o1, final LoanRepaymentData o2) { + public int compare(final LoanTransactionData o1, final LoanTransactionData o2) { return o2.getDate().compareTo(o1.getDate()); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java index e486d23e2..53dc9b21b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransaction.java @@ -140,6 +140,14 @@ public class LoanTransaction extends AbstractAuditableCustom { public boolean isIdentifiedBy(Long identifier) { return this.getId().equals(identifier); } + + public boolean isBelongingToLoanOf(Loan check) { + return this.loan.getId().equals(check.getId()); + } + + public boolean isNotBelongingToLoanOf(Loan check) { + return !isBelongingToLoanOf(check); + } public void contra() { this.contra = LoanTransaction.contra(this); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransactionType.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransactionType.java index 9e4145259..3f69ebd36 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransactionType.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanTransactionType.java @@ -1,22 +1,28 @@ package org.mifosng.platform.loan.domain; public enum LoanTransactionType { - UNKNOWN(0), DISBURSEMENT(1), REPAYMENT(2), REVERSAL(3), WAIVED(4); + INVALID(0, "loanTransactionType.invalid"), DISBURSEMENT(1, "loanTransactionType.disbursement"), REPAYMENT(2, "loanTransactionType.repayment"), REVERSAL(3, "loanTransactionType.reversal"), WAIVED(4, "loanTransactionType.waiver"); private final Integer value; + private final String code; - private LoanTransactionType(final Integer value) { + private LoanTransactionType(final Integer value, final String code) { this.value = value; + this.code = code; } public Integer getValue() { return this.value; } + + public String getCode() { + return code; + } public static LoanTransactionType fromInt(final Integer transactionType) { if (transactionType == null) { - return LoanTransactionType.UNKNOWN; + return LoanTransactionType.INVALID; } LoanTransactionType loanTransactionType = null; @@ -34,7 +40,7 @@ public enum LoanTransactionType { loanTransactionType = LoanTransactionType.WAIVED; break; default: - loanTransactionType = LoanTransactionType.UNKNOWN; + loanTransactionType = LoanTransactionType.INVALID; break; } return loanTransactionType; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java index b28b9c2c7..ab16a1bc5 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java @@ -1,7 +1,7 @@ package org.mifosng.platform.loan.service; import org.mifosng.platform.api.data.LoanAccountData; -import org.mifosng.platform.api.data.LoanRepaymentData; +import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.NewLoanData; public interface LoanReadPlatformService { @@ -10,9 +10,9 @@ public interface LoanReadPlatformService { NewLoanData retrieveClientAndProductDetails(Long clientId, Long productId); - LoanRepaymentData retrieveNewLoanRepaymentDetails(Long loanId); + LoanTransactionData retrieveNewLoanRepaymentDetails(Long loanId); - LoanRepaymentData retrieveNewLoanWaiverDetails(Long loanId); + LoanTransactionData retrieveNewLoanWaiverDetails(Long loanId); - LoanRepaymentData retrieveLoanRepaymentDetails(Long loanId, Long transactionId); + LoanTransactionData retrieveLoanTransactionDetails(Long loanId, Long transactionId); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java index 29860f271..c33fea436 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -13,7 +13,7 @@ import org.mifosng.platform.api.data.DerivedLoanData; import org.mifosng.platform.api.data.LoanAccountData; import org.mifosng.platform.api.data.LoanProductData; import org.mifosng.platform.api.data.LoanProductLookup; -import org.mifosng.platform.api.data.LoanRepaymentData; +import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.client.service.ClientReadPlatformService; @@ -27,6 +27,8 @@ import org.mifosng.platform.loan.domain.Loan; import org.mifosng.platform.loan.domain.LoanRepository; import org.mifosng.platform.loan.domain.LoanTransaction; import org.mifosng.platform.loan.domain.LoanTransactionRepository; +import org.mifosng.platform.loan.domain.LoanTransactionType; +import org.mifosng.platform.loanproduct.service.LoanEnumerations; import org.mifosng.platform.loanproduct.service.LoanProductReadPlatformService; import org.mifosng.platform.security.PlatformSecurityContext; import org.mifosng.platform.user.domain.AppUser; @@ -137,7 +139,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public LoanRepaymentData retrieveNewLoanRepaymentDetails(Long loanId) { + public LoanTransactionData retrieveNewLoanRepaymentDetails(Long loanId) { AppUser currentUser = context.authenticatedUser(); @@ -167,7 +169,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { MoneyData possibleNextRepayment = MoneyData.of(currencyData, possibleNextRepaymentAmount.getAmount()); - LoanRepaymentData newRepaymentDetails = new LoanRepaymentData(); + LoanTransactionData newRepaymentDetails = new LoanTransactionData(); + newRepaymentDetails.setTransactionType(LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT)); newRepaymentDetails.setDate(earliestUnpaidInstallmentDate); newRepaymentDetails.setTotal(possibleNextRepayment); @@ -175,7 +178,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public LoanRepaymentData retrieveNewLoanWaiverDetails(Long loanId) { + public LoanTransactionData retrieveNewLoanWaiverDetails(Long loanId) { AppUser currentUser = context.authenticatedUser(); @@ -203,7 +206,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { MoneyData totalOutstandingData = MoneyData.of(currencyData, totalOutstanding.getAmount()); - LoanRepaymentData newWaiverDetails = new LoanRepaymentData(); + LoanTransactionData newWaiverDetails = new LoanTransactionData(); + newWaiverDetails.setTransactionType(LoanEnumerations.transactionType(LoanTransactionType.WAIVED)); newWaiverDetails.setDate(new LocalDate()); newWaiverDetails.setTotal(totalOutstandingData); @@ -211,7 +215,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public LoanRepaymentData retrieveLoanRepaymentDetails(Long loanId, + public LoanTransactionData retrieveLoanTransactionDetails(Long loanId, Long transactionId) { AppUser currentUser = context.authenticatedUser(); @@ -236,6 +240,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { if (transaction == null) { throw new LoanTransactionNotFoundException(transactionId); } + + if (transaction.isNotBelongingToLoanOf(loan)) { + throw new LoanTransactionNotFoundException(transactionId, loanId); + } CurrencyData currencyData = new CurrencyData(currency.getCode(), currency.getName(), currency.getDecimalPlaces(), @@ -243,7 +251,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { MoneyData total = MoneyData.of(currencyData, transaction.getAmount()); LocalDate date = transaction.getTransactionDate(); - LoanRepaymentData loanRepaymentData = new LoanRepaymentData(); + LoanTransactionData loanRepaymentData = new LoanTransactionData(); + loanRepaymentData.setTransactionType(LoanEnumerations.transactionType(transaction.getTypeOf())); loanRepaymentData.setId(transactionId); loanRepaymentData.setTotal(total); loanRepaymentData.setDate(date); 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 fa8d67af5..536d4c8bd 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 @@ -152,7 +152,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -175,7 +175,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -206,7 +206,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -237,7 +237,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -324,7 +324,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -352,7 +352,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -389,7 +389,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -435,7 +435,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } @Transactional @@ -470,6 +470,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loan.getClient().getId()); + return new EntityIdentifier(loan.getId()); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanEnumerations.java b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanEnumerations.java index 33918d842..be9b64a7a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loanproduct/service/LoanEnumerations.java @@ -4,6 +4,7 @@ import org.mifosng.platform.api.data.EnumOptionData; import org.mifosng.platform.loan.domain.AmortizationMethod; import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod; import org.mifosng.platform.loan.domain.InterestMethod; +import org.mifosng.platform.loan.domain.LoanTransactionType; import org.mifosng.platform.loan.domain.PeriodFrequencyType; public class LoanEnumerations { @@ -87,7 +88,7 @@ public class LoanEnumerations { optionData = new EnumOptionData(InterestMethod.DECLINING_BALANCE.getValue().longValue(), InterestMethod.DECLINING_BALANCE.getCode(), "Declining Balance"); break; default: - optionData = new EnumOptionData(AmortizationMethod.INVALID.getValue().longValue(), AmortizationMethod.INVALID.getCode(), "Invalid"); + optionData = new EnumOptionData(InterestMethod.INVALID.getValue().longValue(), InterestMethod.INVALID.getCode(), "Invalid"); break; } return optionData; @@ -107,7 +108,33 @@ public class LoanEnumerations { optionData = new EnumOptionData(InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD.getValue().longValue(), InterestCalculationPeriodMethod.SAME_AS_REPAYMENT_PERIOD.getCode(), "Same as repayment period"); break; default: - optionData = new EnumOptionData(AmortizationMethod.INVALID.getValue().longValue(), AmortizationMethod.INVALID.getCode(), "Invalid"); + optionData = new EnumOptionData(InterestCalculationPeriodMethod.INVALID.getValue().longValue(), InterestCalculationPeriodMethod.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + + public static EnumOptionData transactionType(Integer id) { + return transactionType(LoanTransactionType.fromInt(id)); + } + + public static EnumOptionData transactionType(LoanTransactionType type) { + EnumOptionData optionData = null; + switch (type) { + case DISBURSEMENT: + optionData= new EnumOptionData(LoanTransactionType.DISBURSEMENT.getValue().longValue(), LoanTransactionType.DISBURSEMENT.getCode(), "Dibursement"); + break; + case REPAYMENT: + optionData = new EnumOptionData(LoanTransactionType.REPAYMENT.getValue().longValue(), LoanTransactionType.REPAYMENT.getCode(), "Repayment"); + break; + case REVERSAL: + optionData = new EnumOptionData(LoanTransactionType.REVERSAL.getValue().longValue(), LoanTransactionType.REVERSAL.getCode(), "Reversal"); + break; + case WAIVED: + optionData = new EnumOptionData(LoanTransactionType.WAIVED.getValue().longValue(), LoanTransactionType.WAIVED.getCode(), "Waiver"); + break; + default: + optionData = new EnumOptionData(LoanTransactionType.INVALID.getValue().longValue(), LoanTransactionType.INVALID.getCode(), "Invalid"); break; } return optionData; diff --git a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java index b5c2d9557..2d721a4b8 100644 --- a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java +++ b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java @@ -12,7 +12,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mifosng.platform.api.data.CurrencyData; import org.mifosng.platform.api.data.DerivedLoanData; -import org.mifosng.platform.api.data.LoanRepaymentData; +import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentScheduleData; import org.mifosng.platform.api.data.MoneyData; @@ -81,11 +81,11 @@ public class DerivedLoanDataProcessorTest { assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); + List loanRepayments = derivedData.getLoanRepayments(); assertThat(loanRepayments, is(notNullValue())); assertThat(loanRepayments.size(), is(1)); - LoanRepaymentData firstRepayment = loanRepayments.get(0); + LoanTransactionData firstRepayment = loanRepayments.get(0); assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); assertThat(firstRepayment.getTotal(), is(expectedTotal)); @@ -147,11 +147,11 @@ public class DerivedLoanDataProcessorTest { assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); + List loanRepayments = derivedData.getLoanRepayments(); assertThat(loanRepayments, is(notNullValue())); assertThat(loanRepayments.size(), is(1)); - LoanRepaymentData firstRepayment = loanRepayments.get(0); + LoanTransactionData firstRepayment = loanRepayments.get(0); assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); assertThat(firstRepayment.getTotal(), is(expectedTotal)); @@ -210,11 +210,11 @@ public class DerivedLoanDataProcessorTest { assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); + List loanRepayments = derivedData.getLoanRepayments(); assertThat(loanRepayments, is(notNullValue())); assertThat(loanRepayments.size(), is(1)); - LoanRepaymentData firstRepayment = loanRepayments.get(0); + LoanTransactionData firstRepayment = loanRepayments.get(0); assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); assertThat(firstRepayment.getTotal(), is(expectedTotal)); @@ -273,11 +273,11 @@ public class DerivedLoanDataProcessorTest { assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); + List loanRepayments = derivedData.getLoanRepayments(); assertThat(loanRepayments, is(notNullValue())); assertThat(loanRepayments.size(), is(1)); - LoanRepaymentData firstRepayment = loanRepayments.get(0); + LoanTransactionData firstRepayment = loanRepayments.get(0); assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); assertThat(firstRepayment.getTotal(), is(expectedTotal)); @@ -359,11 +359,11 @@ public class DerivedLoanDataProcessorTest { assertThat(secondPeriod.getInterestOutstanding(), is(expectedInterestOutstanding)); // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); + List loanRepayments = derivedData.getLoanRepayments(); assertThat(loanRepayments, is(notNullValue())); assertThat(loanRepayments.size(), is(1)); - LoanRepaymentData firstRepayment = loanRepayments.get(0); + LoanTransactionData firstRepayment = loanRepayments.get(0); assertThat(firstRepayment.getPrincipal(), is(moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1180").build()))); assertThat(firstRepayment.getInterest(), is(moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("20").build()))); assertThat(firstRepayment.getTotal(), is(moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1200").build())));