diff --git a/mifosng-db/migrations/core_db/V56__track-overpaid-amount-on-loans.sql b/mifosng-db/migrations/core_db/V56__track-overpaid-amount-on-loans.sql new file mode 100644 index 000000000..ab9f5e4bc --- /dev/null +++ b/mifosng-db/migrations/core_db/V56__track-overpaid-amount-on-loans.sql @@ -0,0 +1,2 @@ +ALTER TABLE `m_loan` +ADD COLUMN `total_overpaid_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `total_outstanding_derived`; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java index 0adbb3507..3e9437e05 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoansApiResource.java @@ -86,12 +86,12 @@ public class LoansApiResource { private final Set LOAN_DATA_PARAMETERS = new HashSet(Arrays.asList("id", "accountNo", "status", "externalId", "clientId", "group", "loanProductId", "loanProductName", "loanProductDescription", "fundId", "fundName", "loanPurposeId", - "loanPurposeName", "loanOfficerId", "loanOfficerName", "currency", "principal", "inArrearsTolerance", "termFrequency", - "termPeriodFrequencyType", "numberOfRepayments", "repaymentEvery", "interestRatePerPeriod", "annualInterestRate", - "repaymentFrequencyType", "transactionProcessingStrategyId", "interestRateFrequencyType", "amortizationType", "interestType", - "interestCalculationPeriodType", "expectedFirstRepaymentOnDate", "graceOnPrincipalPayment", "graceOnInterestPayment", - "graceOnInterestCharged", "interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", "summary", - "repaymentSchedule", "transactions", "charges", "collateral", "guarantors", "meeting", "productOptions", + "loanPurposeName", "loanOfficerId", "loanOfficerName", "currency", "principal", "totalOverpaid", "inArrearsTolerance", + "termFrequency", "termPeriodFrequencyType", "numberOfRepayments", "repaymentEvery", "interestRatePerPeriod", + "annualInterestRate", "repaymentFrequencyType", "transactionProcessingStrategyId", "interestRateFrequencyType", + "amortizationType", "interestType", "interestCalculationPeriodType", "expectedFirstRepaymentOnDate", "graceOnPrincipalPayment", + "graceOnInterestPayment", "graceOnInterestCharged", "interestChargedFromDate", "timeline", "totalFeeChargesAtDisbursement", + "summary", "repaymentSchedule", "transactions", "charges", "collateral", "guarantors", "meeting", "productOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "termFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions", "loanOfficerOptions", "loanPurposeOptions", "loanCollateralOptions", "chargeTemplate", "calendarOptions")); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java index 2add7b5da..f1f9378c9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java @@ -120,6 +120,7 @@ public class LoanAccountData { @Transient private final BigDecimal feeChargesAtDisbursementCharged; + private final BigDecimal totalOverpaid; /** * Used to produce a {@link LoanAccountData} with only collateral options @@ -146,6 +147,7 @@ public class LoanAccountData { final String loanOfficerName = null; final CurrencyData currencyData = null; final BigDecimal principal = null; + final BigDecimal totalOverpaid = null; final BigDecimal inArrearsTolerance = null; final Integer termFrequency = null; final EnumOptionData termPeriodFrequencyType = null; @@ -191,8 +193,8 @@ public class LoanAccountData { return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, - currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, - repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, + currencyData, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, + repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, @@ -225,6 +227,7 @@ public class LoanAccountData { final String loanOfficerName = null; final CurrencyData currencyData = null; final BigDecimal principal = null; + final BigDecimal totalOverpaid = null; final BigDecimal inArrearsTolerance = null; final Integer termFrequency = null; final EnumOptionData termPeriodFrequencyType = null; @@ -271,8 +274,8 @@ public class LoanAccountData { return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, - currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, - repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, + currencyData, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, + repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, @@ -286,9 +289,9 @@ public class LoanAccountData { return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, clientAcc.clientId, clientAcc.clientName, clientAcc.clientOfficeId, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, - acc.principal, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, - acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, - acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, + acc.principal, acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, + acc.numberOfRepayments, acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, + acc.amortizationType, acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, clientAcc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, @@ -323,6 +326,7 @@ public class LoanAccountData { final String loanOfficerName = null; final CurrencyData currencyData = null; final BigDecimal principal = null; + final BigDecimal totalOverpaid = null; final BigDecimal inArrearsTolerance = null; final Integer termFrequency = null; final EnumOptionData termPeriodFrequencyType = null; @@ -369,8 +373,8 @@ public class LoanAccountData { return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, - currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, - repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, + currencyData, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, + repaymentEvery, repaymentFrequencyType, transactionProcessingStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, summary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, @@ -384,16 +388,16 @@ public class LoanAccountData { return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, groupAcc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, - acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, - acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, acc.interestRatePerPeriod, - acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, - acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, - acc.interestChargedFromDate, groupAcc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, - acc.transactions, acc.charges, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, - acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.transactionProcessingStrategyOptions, - acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.interestTypeOptions, - acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.loanOfficerOptions, - acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions); + acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, + acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, + acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, + acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, + acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, groupAcc.timeline, acc.summary, + acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, + acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, + acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, + acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, + acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions); } public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product, @@ -422,6 +426,7 @@ public class LoanAccountData { final String loanOfficerName = null; final CurrencyData currencyData = null; final BigDecimal principal = null; + final BigDecimal totalOverpaid = null; final BigDecimal inArrearsTolerance = null; final Integer numberOfRepayments = null; final Integer repaymentEvery = null; @@ -459,7 +464,7 @@ public class LoanAccountData { return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), loanPurposeId, - loanPurposeName, loanOfficerId, loanOfficerName, product.getCurrency(), product.getPrincipal(), + loanPurposeName, loanOfficerId, loanOfficerName, product.getCurrency(), product.getPrincipal(), totalOverpaid, product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType, product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), product.getTransactionProcessingStrategyId(), product.getAmortizationType(), product.getInterestRatePerPeriod(), product.getInterestRateFrequencyType(), @@ -506,8 +511,8 @@ public class LoanAccountData { return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, acc.group, acc.loanType, product.getId(), product.getName(), product.getDescription(), product.getFundId(), product.getFundName(), acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, - product.getCurrency(), product.getPrincipal(), product.getInArrearsTolerance(), termFrequency, termPeriodFrequencyType, - product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), + product.getCurrency(), product.getPrincipal(), acc.totalOverpaid, product.getInArrearsTolerance(), termFrequency, + termPeriodFrequencyType, product.getNumberOfRepayments(), product.getRepaymentEvery(), product.getRepaymentFrequencyType(), product.getTransactionProcessingStrategyId(), product.getAmortizationType(), product.getInterestRatePerPeriod(), product.getInterestRateFrequencyType(), product.getAnnualInterestRate(), product.getInterestType(), product.getInterestCalculationPeriodType(), acc.expectedFirstRepaymentOnDate, product.getGraceOnPrincipalPayment(), @@ -526,14 +531,15 @@ public class LoanAccountData { final String externalId, final Long clientId, final String clientName, final Long clientOfficeId, final GroupGeneralData group, final EnumOptionData loanType, final Long loanProductId, final String loanProductName, final String loanProductDescription, final Long fundId, final String fundName, final Long loanPurposeId, final String loanPurposeName, final Long loanOfficerId, - final String loanOfficerName, final CurrencyData currencyData, final BigDecimal principal, final BigDecimal inArrearsTolerance, - final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, final Integer numberOfRepayments, - final Integer repaymentEvery, final EnumOptionData repaymentFrequencyType, final Long transactionStrategyId, - final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod, final EnumOptionData interestRateFrequencyType, - final BigDecimal annualInterestRate, final EnumOptionData interestType, final EnumOptionData interestCalculationPeriodType, - final LocalDate expectedFirstRepaymentOnDate, final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, - final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate, final LoanApplicationTimelineData timeline, - final LoanSummaryData loanSummary, final BigDecimal feeChargesDueAtDisbursementCharged) { + final String loanOfficerName, final CurrencyData currencyData, final BigDecimal principal, final BigDecimal totalOverpaid, + final BigDecimal inArrearsTolerance, final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, + final Integer numberOfRepayments, final Integer repaymentEvery, final EnumOptionData repaymentFrequencyType, + final Long transactionStrategyId, final EnumOptionData amortizationType, final BigDecimal interestRatePerPeriod, + final EnumOptionData interestRateFrequencyType, final BigDecimal annualInterestRate, final EnumOptionData interestType, + final EnumOptionData interestCalculationPeriodType, final LocalDate expectedFirstRepaymentOnDate, + final Integer graceOnPrincipalPayment, final Integer graceOnInterestPayment, final Integer graceOnInterestCharged, + final LocalDate interestChargedFromDate, final LoanApplicationTimelineData timeline, final LoanSummaryData loanSummary, + final BigDecimal feeChargesDueAtDisbursementCharged) { final LoanScheduleData repaymentSchedule = null; final Collection transactions = null; @@ -559,10 +565,10 @@ public class LoanAccountData { return new LoanAccountData(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, group, loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, loanOfficerId, loanOfficerName, - currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, repaymentEvery, - repaymentFrequencyType, transactionStrategyId, amortizationType, interestRatePerPeriod, interestRateFrequencyType, - annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, - graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary, + currencyData, principal, totalOverpaid, inArrearsTolerance, termFrequency, termPeriodFrequencyType, numberOfRepayments, + repaymentEvery, repaymentFrequencyType, transactionStrategyId, amortizationType, interestRatePerPeriod, + interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, expectedFirstRepaymentOnDate, + graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, @@ -587,15 +593,15 @@ public class LoanAccountData { return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, acc.group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, - acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, - acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, acc.interestRatePerPeriod, - acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, - acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, - acc.interestChargedFromDate, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, repaymentSchedule, - transactions, charges, collateral, guarantors, calendarData, productOptions, termFrequencyTypeOptions, - repaymentFrequencyTypeOptions, transactionProcessingStrategyOptions, interestRateFrequencyTypeOptions, - amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, - chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions); + acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, + acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, + acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, + acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, + acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, + acc.feeChargesAtDisbursementCharged, repaymentSchedule, transactions, charges, collateral, guarantors, calendarData, + productOptions, termFrequencyTypeOptions, repaymentFrequencyTypeOptions, transactionProcessingStrategyOptions, + interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, + fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions); } public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection productOptions, @@ -611,16 +617,16 @@ public class LoanAccountData { return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientName, acc.clientOfficeId, group, acc.loanType, acc.loanProductId, acc.loanProductName, acc.loanProductDescription, acc.fundId, acc.fundName, acc.loanPurposeId, acc.loanPurposeName, acc.loanOfficerId, acc.loanOfficerName, acc.currency, acc.principal, - acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, acc.repaymentEvery, - acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, acc.interestRatePerPeriod, - acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, acc.interestCalculationPeriodType, - acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, acc.graceOnInterestPayment, acc.graceOnInterestCharged, - acc.interestChargedFromDate, acc.timeline, acc.summary, acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, - acc.transactions, acc.charges, acc.collateral, acc.guarantors, acc.meeting, acc.productOptions, - acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, acc.transactionProcessingStrategyOptions, - acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, acc.interestTypeOptions, - acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, acc.loanOfficerOptions, - acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions); + acc.totalOverpaid, acc.inArrearsTolerance, acc.termFrequency, acc.termPeriodFrequencyType, acc.numberOfRepayments, + acc.repaymentEvery, acc.repaymentFrequencyType, acc.transactionProcessingStrategyId, acc.amortizationType, + acc.interestRatePerPeriod, acc.interestRateFrequencyType, acc.annualInterestRate, acc.interestType, + acc.interestCalculationPeriodType, acc.expectedFirstRepaymentOnDate, acc.graceOnPrincipalPayment, + acc.graceOnInterestPayment, acc.graceOnInterestCharged, acc.interestChargedFromDate, acc.timeline, acc.summary, + acc.feeChargesAtDisbursementCharged, acc.repaymentSchedule, acc.transactions, acc.charges, acc.collateral, acc.guarantors, + acc.meeting, acc.productOptions, acc.termFrequencyTypeOptions, acc.repaymentFrequencyTypeOptions, + acc.transactionProcessingStrategyOptions, acc.interestRateFrequencyTypeOptions, acc.amortizationTypeOptions, + acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null, + acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions); } private LoanAccountData( @@ -644,6 +650,7 @@ public class LoanAccountData { final String loanOfficerName, // final CurrencyData currency, final BigDecimal principal, + final BigDecimal totalOverpaid, final BigDecimal inArrearsTolerance, // final Integer termFrequency, final EnumOptionData termPeriodFrequencyType, // @@ -686,6 +693,7 @@ public class LoanAccountData { this.loanOfficerName = loanOfficerName; this.currency = currency; this.principal = principal; + this.totalOverpaid = totalOverpaid; this.inArrearsTolerance = inArrearsTolerance; this.termFrequency = termFrequency; this.termPeriodFrequencyType = termPeriodFrequencyType; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index d9b828536..509bc5d4f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -224,6 +224,10 @@ public class Loan extends AbstractPersistable { @Column(name = "interest_calculated_from_date") private Date interestChargedFromDate; + @SuppressWarnings("unused") + @Column(name = "total_overpaid_derived", scale = 6, precision = 19) + private BigDecimal totalOverpaid; + @LazyCollection(LazyCollectionOption.FALSE) @OneToMany(cascade = CascadeType.ALL, mappedBy = "loan", orphanRemoval = true) private Set charges = new HashSet(); @@ -766,7 +770,11 @@ public class Loan extends AbstractPersistable { if (isNotDisbursed()) { this.summary.zeroFields(); this.summaryArrearsAging = null; + this.totalOverpaid = null; } else { + final Money overpaidBy = calculateTotalOverpayment(); + this.totalOverpaid = overpaidBy.getAmountDefaultedToNullIfZero(); + final Money principal = this.loanRepaymentScheduleDetail.getPrincipal(); this.summary.updateSummary(loanCurrency(), principal, this.repaymentScheduleInstallments, this.loanSummaryWrapper, isDisbursed()); @@ -1558,12 +1566,9 @@ public class Loan extends AbstractPersistable { private void doPostLoanTransactionChecks(final LocalDate transactionDate, final LoanLifecycleStateMachine loanLifecycleStateMachine) { if (this.isOverPaid()) { + // FIXME - kw - update account balance to negative amount. handleLoanOverpayment(loanLifecycleStateMachine); } else if (this.summary.isRepaidInFull(loanCurrency())) { - // TODO - KW - probably should not close the loan automatically but - // let user decide if loan is closed or not and provide closing - // date. - // - need to dig into loan closure scenarios with MFIs handleLoanRepaymentInFull(transactionDate, loanLifecycleStateMachine); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummary.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummary.java index 59ddad89f..98cdfeaf7 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummary.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanSummary.java @@ -13,9 +13,13 @@ import javax.persistence.Embeddable; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.Money; +import org.mifosplatform.scheduledjobs.UpdateLoanSummariesScheduledJob; /** - * LoanSummary encapsulates all the summary details of a {@link Loan}. + * Encapsulates all the summary details of a {@link Loan}. + * + * {@link LoanSummary} fields are updated through a scheduled job. see - + * {@link UpdateLoanSummariesScheduledJob}. */ @Embeddable public final class LoanSummary { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 424d6dc63..be244bd87 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -436,6 +436,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { + " l.total_waived_derived as totalWaived," + " l.total_writtenoff_derived as totalWrittenOff," + " l.total_outstanding_derived as totalOutstanding," + + " l.total_overpaid_derived as totalOverpaid," + " la.principal_overdue_derived as principalOverdue," + " la.interest_overdue_derived as interestOverdue," + " la.fee_charges_overdue_derived as feeChargesOverdue," @@ -543,6 +544,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { expectedMaturityDate); final BigDecimal principal = rs.getBigDecimal("principal"); + final BigDecimal totalOverpaid = rs.getBigDecimal("totalOverpaid"); final BigDecimal inArrearsTolerance = rs.getBigDecimal("inArrearsTolerance"); final Integer numberOfRepayments = JdbcSupport.getInteger(rs, "numberOfRepayments"); @@ -646,11 +648,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientName, clientOfficeId, groupData, loanType, loanProductId, loanProductName, loanProductDescription, fundId, fundName, loanPurposeId, loanPurposeName, - loanOfficerId, loanOfficerName, currencyData, principal, inArrearsTolerance, termFrequency, termPeriodFrequencyType, - numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionStrategyId, amortizationType, - interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, interestCalculationPeriodType, - expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, - interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged); + loanOfficerId, loanOfficerName, currencyData, principal, totalOverpaid, inArrearsTolerance, termFrequency, + termPeriodFrequencyType, numberOfRepayments, repaymentEvery, repaymentFrequencyType, transactionStrategyId, + amortizationType, interestRatePerPeriod, interestRateFrequencyType, annualInterestRate, interestType, + interestCalculationPeriodType, expectedFirstRepaymentOnDate, graceOnPrincipalPayment, graceOnInterestPayment, + graceOnInterestCharged, interestChargedFromDate, timeline, loanSummary, feeChargesDueAtDisbursementCharged); } }