MIFOSX-172: WIP - update validation and api around loan charges.
This commit is contained in:
@@ -732,7 +732,10 @@ DROP TABLE IF EXISTS `m_group`;
|
||||
CREATE TABLE `m_group` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`office_id` bigint(20) NOT NULL,
|
||||
`loan_officer_id` bigint(20) DEFAULT NULL,
|
||||
`level_Id` int(11) NOT NULL,
|
||||
`parent_id` bigint(20) DEFAULT NULL,
|
||||
`hierarchy` varchar(100) DEFAULT NULL,
|
||||
`staff_id` bigint(20) DEFAULT NULL,
|
||||
`name` varchar(100) DEFAULT NULL,
|
||||
`external_id` varchar(100) DEFAULT NULL,
|
||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||
@@ -740,9 +743,13 @@ CREATE TABLE `m_group` (
|
||||
UNIQUE KEY `name` (`name`),
|
||||
UNIQUE KEY `external_id` (`external_id`),
|
||||
KEY `office_id` (`office_id`),
|
||||
KEY `loan_officer_id` (`loan_officer_id`),
|
||||
KEY `loan_officer_id` (`staff_id`),
|
||||
KEY `Parent_Id_reference` (`parent_id`),
|
||||
KEY `FK_m_group_level` (`level_Id`),
|
||||
CONSTRAINT `FK_m_group_level` FOREIGN KEY (`level_Id`) REFERENCES `m_group_level` (`id`),
|
||||
CONSTRAINT `FK_m_group_m_staff` FOREIGN KEY (`staff_id`) REFERENCES `m_staff` (`id`),
|
||||
CONSTRAINT `m_group_ibfk_1` FOREIGN KEY (`office_id`) REFERENCES `m_office` (`id`),
|
||||
CONSTRAINT `FK_m_group_m_staff` FOREIGN KEY (`loan_officer_id`) REFERENCES `m_staff` (`id`)
|
||||
CONSTRAINT `Parent_Id_reference` FOREIGN KEY (`parent_id`) REFERENCES `m_group` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -781,6 +788,35 @@ LOCK TABLES `m_group_client` WRITE;
|
||||
/*!40000 ALTER TABLE `m_group_client` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `m_group_level`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `m_group_level`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `m_group_level` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`level_name` varchar(100) NOT NULL,
|
||||
`recursable` tinyint(1) NOT NULL,
|
||||
`can_have_clients` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `Parent_levelId_reference` (`parent_id`),
|
||||
CONSTRAINT `Parent_levelId_reference` FOREIGN KEY (`parent_id`) REFERENCES `m_group_level` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `m_group_level`
|
||||
--
|
||||
|
||||
LOCK TABLES `m_group_level` WRITE;
|
||||
/*!40000 ALTER TABLE `m_group_level` DISABLE KEYS */;
|
||||
INSERT INTO `m_group_level` VALUES (1,NULL,'Center',1,0),(2,NULL,'Group',0,1);
|
||||
/*!40000 ALTER TABLE `m_group_level` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `m_guarantor`
|
||||
--
|
||||
@@ -1933,4 +1969,4 @@ UNLOCK TABLES;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2013-02-19 0:44:13
|
||||
-- Dump completed on 2013-02-20 9:57:08
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.portfolio.charge.domain;
|
||||
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeIsNotActiveException;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Wrapper for {@link ChargeRepository} that is responsible for checking if
|
||||
* {@link Charge} is returned when using <code>findOne</code> repository method
|
||||
* and throwing an appropriate not found exception.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This is to avoid need for checking and throwing in multiple areas of code
|
||||
* base where {@link ChargeRepository} is required.
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class ChargeRepositoryWrapper {
|
||||
|
||||
private final ChargeRepository repository;
|
||||
|
||||
@Autowired
|
||||
public ChargeRepositoryWrapper(final ChargeRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public Charge findOneWithNotFoundDetection(final Long id) {
|
||||
|
||||
final Charge chargeDefinition = this.repository.findOne(id);
|
||||
if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(id); }
|
||||
if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(id, chargeDefinition.getName()); }
|
||||
|
||||
return chargeDefinition;
|
||||
}
|
||||
}
|
||||
+6
-22
@@ -6,16 +6,12 @@
|
||||
package org.mifosplatform.portfolio.loanaccount.command;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
||||
|
||||
/**
|
||||
* Immutable command for creating and updating loan charges.
|
||||
* Java object representation of {@link LoanCharge} API JSON.
|
||||
*/
|
||||
public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
||||
|
||||
@@ -23,10 +19,12 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
||||
private final Long id;
|
||||
private final Long chargeId;
|
||||
private final BigDecimal amount;
|
||||
@SuppressWarnings("unused")
|
||||
private final Integer chargeTimeType;
|
||||
@SuppressWarnings("unused")
|
||||
private final Integer chargeCalculationType;
|
||||
@SuppressWarnings("unused")
|
||||
private final LocalDate specifiedDueDate;
|
||||
private final LocalDate dueDate;
|
||||
|
||||
public LoanChargeCommand(final Long id, final Long chargeId, final BigDecimal amount, final Integer chargeTimeType,
|
||||
final Integer chargeCalculationType, final LocalDate specifiedDueDate) {
|
||||
@@ -35,7 +33,7 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
||||
this.amount = amount;
|
||||
this.chargeTimeType = chargeTimeType;
|
||||
this.chargeCalculationType = chargeCalculationType;
|
||||
this.specifiedDueDate = specifiedDueDate;
|
||||
this.dueDate = specifiedDueDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,18 +44,4 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
||||
}
|
||||
return comparison;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void validateForUpdate() {
|
||||
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
|
||||
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge");
|
||||
|
||||
baseDataValidator.reset().parameter("amount").value(this.amount).ignoreIfNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType).ignoreIfNull().inMinMaxRange(1, 2);
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculationType).ignoreIfNull().inMinMaxRange(1, 4);
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
|
||||
"Validation errors exist.", dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -31,7 +31,7 @@ public class LoanChargeData {
|
||||
private final EnumOptionData chargeTimeType;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final LocalDate dueAsOfDate;
|
||||
private final LocalDate dueDate;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final EnumOptionData chargeCalculationType;
|
||||
@@ -81,7 +81,7 @@ public class LoanChargeData {
|
||||
|
||||
public LoanChargeData(final Long id, final Long chargeId, final String name, final CurrencyData currency, final BigDecimal amount,
|
||||
final BigDecimal amountPaid, final BigDecimal amountWaived, final BigDecimal amountWrittenOff,
|
||||
final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType, final LocalDate dueAsOfDate,
|
||||
final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType, final LocalDate dueDate,
|
||||
final EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo,
|
||||
final boolean penalty) {
|
||||
this.id = id;
|
||||
@@ -94,7 +94,7 @@ public class LoanChargeData {
|
||||
this.amountWrittenOff = amountWrittenOff;
|
||||
this.amountOutstanding = amountOutstanding;
|
||||
this.chargeTimeType = chargeTimeType;
|
||||
this.dueAsOfDate = dueAsOfDate;
|
||||
this.dueDate = dueDate;
|
||||
this.chargeCalculationType = chargeCalculationType;
|
||||
this.percentage = percentage;
|
||||
this.amountPercentageAppliedTo = amountPercentageAppliedTo;
|
||||
@@ -122,7 +122,7 @@ public class LoanChargeData {
|
||||
this.amountWrittenOff = BigDecimal.ZERO;
|
||||
this.amountOutstanding = amount;
|
||||
this.chargeTimeType = chargeTimeType;
|
||||
this.dueAsOfDate = null;
|
||||
this.dueDate = null;
|
||||
this.chargeCalculationType = chargeCalculationType;
|
||||
this.percentage = null;
|
||||
this.amountPercentageAppliedTo = null;
|
||||
|
||||
+1
-1
@@ -150,7 +150,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
for (LoanCharge loanCharge : charges) {
|
||||
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
||||
if (earliestUnpaidCharge == null
|
||||
|| loanCharge.getDueForCollectionAsOfLocalDate().isBefore(earliestUnpaidCharge.getDueForCollectionAsOfLocalDate())) {
|
||||
|| loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
||||
earliestUnpaidCharge = loanCharge;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-49
@@ -322,7 +322,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
Money chargesDue = Money.of(getCurrency(), BigDecimal.ZERO);
|
||||
|
||||
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
|
||||
for (LoanCharge charge : setOfLoanCharges()) {
|
||||
if (charge.isDueAtDisbursement()) {
|
||||
chargesDue = chargesDue.plus(charge.amount());
|
||||
}
|
||||
@@ -362,7 +362,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
validateLoanIsNotClosed(loanCharge);
|
||||
|
||||
if (isDisbursed() && loanCharge.isDueAtDisbursement()) {
|
||||
// Note: added this constraint to restrict adding charges to a loan
|
||||
// Note: added this constraint to restrict adding disbursement
|
||||
// charges to a loan
|
||||
// after it is disbursed
|
||||
// if the loan charge payment type is 'Disbursement'.
|
||||
// To undo this constraint would mean resolving how charges due are
|
||||
@@ -380,7 +381,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||
|
||||
loanCharge.update(this);
|
||||
getNullPointerSafeLoanCharges().add(loanCharge);
|
||||
setOfLoanCharges().add(loanCharge);
|
||||
|
||||
updateTotalChargesDueAtDisbursement();
|
||||
|
||||
@@ -390,11 +391,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
if (!loanCharge.isDueAtDisbursement()) {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
} else {
|
||||
// just reprocess the loan schedule only for now.
|
||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +436,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
// if you want ability to remove loan charges that are waived.
|
||||
validateLoanChargeIsNotWaived(loanCharge);
|
||||
|
||||
boolean removed = getNullPointerSafeLoanCharges().remove(loanCharge);
|
||||
boolean removed = setOfLoanCharges().remove(loanCharge);
|
||||
if (removed) {
|
||||
updateTotalChargesDueAtDisbursement();
|
||||
}
|
||||
@@ -447,7 +448,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +485,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
validateLoanIsNotClosed(loanCharge);
|
||||
|
||||
if (getNullPointerSafeLoanCharges().contains(loanCharge)) {
|
||||
if (setOfLoanCharges().contains(loanCharge)) {
|
||||
final Map<String, Object> loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount());
|
||||
actualChanges.putAll(loanChargeChanges);
|
||||
updateTotalChargesDueAtDisbursement();
|
||||
@@ -495,11 +496,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
if (!loanCharge.isDueAtDisbursement()) {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
} else {
|
||||
// reprocess loan schedule based on charge been waived.
|
||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
@@ -523,7 +524,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
LocalDate transactionDate = getDisbursementDate();
|
||||
if (loanCharge.isSpecifiedDueDate()) {
|
||||
transactionDate = loanCharge.getDueForCollectionAsOfLocalDate();
|
||||
transactionDate = loanCharge.getDueLocalDate();
|
||||
}
|
||||
|
||||
updateTotalChargesDueAtDisbursement();
|
||||
@@ -538,11 +539,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
} else {
|
||||
// reprocess loan schedule based on charge been waived.
|
||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
|
||||
doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||
@@ -595,8 +596,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
}
|
||||
|
||||
public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
|
||||
getNullPointerSafeLoanCharges().clear();
|
||||
getNullPointerSafeLoanCharges().addAll(associateChargesWithThisLoan(loanCharges));
|
||||
setOfLoanCharges().clear();
|
||||
setOfLoanCharges().addAll(associateChargesWithThisLoan(loanCharges));
|
||||
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
|
||||
}
|
||||
|
||||
@@ -630,7 +631,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), repaymentsOrWaivers, getCurrency(),
|
||||
this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
|
||||
public void updateLoanScheduleDependentDerivedFields() {
|
||||
@@ -785,7 +786,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
final String chargesParamName = "charges";
|
||||
if (command.parameterExists(chargesParamName)) {
|
||||
|
||||
final Set<LoanCharge> existingLoanCharges = getNullPointerSafeLoanCharges();
|
||||
final Set<LoanCharge> existingLoanCharges = setOfLoanCharges();
|
||||
|
||||
if (!possiblyModifedLoanCharges.equals(existingLoanCharges)) {
|
||||
actualChanges.put(chargesParamName, getLoanCharges(possiblyModifedLoanCharges));
|
||||
@@ -797,20 +798,6 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||
}
|
||||
}
|
||||
|
||||
// final ImmutableSet<LoanCharge> difference =
|
||||
// Sets.symmetricDifference(existingLoanCharges,
|
||||
// possiblyModifedLoanCharges)
|
||||
// .immutableCopy();
|
||||
// if (!difference.isEmpty()) {
|
||||
// actualChanges.put(chargesParamName, getLoanCharges(difference));
|
||||
// actualChanges.put("recalculateLoanSchedule", true);
|
||||
//
|
||||
// for (LoanCharge loanCharge : possiblyModifedLoanCharges) {
|
||||
// validateChargeHasValidSpecifiedDateIfApplicable(loanCharge,
|
||||
// getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
final String collateralParamName = "collateral";
|
||||
@@ -819,22 +806,12 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
if (!possiblyModifedLoanCollateralItems.equals(this.collateral)) {
|
||||
actualChanges.put(collateralParamName, listOfLoanCollateralData(possiblyModifedLoanCollateralItems));
|
||||
}
|
||||
|
||||
//
|
||||
// final ImmutableSet<LoanCollateral> difference =
|
||||
// Sets.symmetricDifference(this.collateral,
|
||||
// possiblyModifedLoanCollateralItems)
|
||||
// .immutableCopy();
|
||||
// if (!difference.isEmpty()) {
|
||||
// actualChanges.put(collateralParamName,
|
||||
// listOfLoanCollateralData(difference));
|
||||
// }
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private Set<LoanCharge> getNullPointerSafeLoanCharges() {
|
||||
private Set<LoanCharge> setOfLoanCharges() {
|
||||
Set<LoanCharge> loanCharges = this.charges;
|
||||
if (this.charges == null) {
|
||||
loanCharges = new HashSet<LoanCharge>();
|
||||
@@ -933,7 +910,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
}
|
||||
|
||||
// charges are optional
|
||||
for (LoanCharge loanCharge : getNullPointerSafeLoanCharges()) {
|
||||
for (LoanCharge loanCharge : setOfLoanCharges()) {
|
||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||
}
|
||||
}
|
||||
@@ -1190,7 +1167,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, interestRatePerPeriod,
|
||||
interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod,
|
||||
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency,
|
||||
loanTermPeriodFrequencyType, getNullPointerSafeLoanCharges(), this.getDisbursementDate(),
|
||||
loanTermPeriodFrequencyType, setOfLoanCharges(), this.getDisbursementDate(),
|
||||
this.getExpectedFirstRepaymentOnDate(), this.getInterestChargedFromDate(), inArrearsTolerance);
|
||||
|
||||
final LoanScheduleData generatedData = loanSchedule.generate();
|
||||
@@ -1215,7 +1192,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
chargesPayment.updateLoan(this);
|
||||
this.loanTransactions.add(chargesPayment);
|
||||
|
||||
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
|
||||
for (LoanCharge charge : setOfLoanCharges()) {
|
||||
if (charge.isDueAtDisbursement()) {
|
||||
charge.markAsFullyPaid();
|
||||
}
|
||||
@@ -1281,7 +1258,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
private void updateLoanToPreDisbursalState() {
|
||||
this.actualDisbursementDate = null;
|
||||
|
||||
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
|
||||
for (LoanCharge charge : setOfLoanCharges()) {
|
||||
charge.resetToOriginal(loanCurrency());
|
||||
}
|
||||
|
||||
@@ -1290,7 +1267,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
}
|
||||
|
||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
|
||||
public LoanTransaction waiveInterest(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||
@@ -1370,11 +1347,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
||||
.determineProcessor(this.transactionProcessingStrategy);
|
||||
if (isTransactionChronologicallyLatest && adjustedTransaction == null) {
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments,
|
||||
getNullPointerSafeLoanCharges());
|
||||
setOfLoanCharges());
|
||||
} else {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
||||
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||
}
|
||||
|
||||
doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||
|
||||
+54
-45
@@ -50,7 +50,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "due_for_collection_as_of_date")
|
||||
private Date dueForCollectionAsOfDate;
|
||||
private Date dueDate;
|
||||
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
@@ -85,29 +85,32 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeDefinition, final JsonCommand command) {
|
||||
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||
final Integer chargeTimeType = command.integerValueOfParameterNamed("chargeTimeType");
|
||||
final Integer chargeCalculationType = command.integerValueOfParameterNamed("chargeCalculationType");
|
||||
final LocalDate specifiedDueDate = command.localDateValueOfParameterNamed("specifiedDueDate");
|
||||
// final Integer chargeTimeType =
|
||||
// command.integerValueOfParameterNamed("chargeTimeType");
|
||||
// final Integer chargeCalculationType =
|
||||
// command.integerValueOfParameterNamed("chargeCalculationType");
|
||||
final LocalDate dueDate = command.localDateValueOfParameterNamed("dueDate");
|
||||
|
||||
ChargeTimeType chargeTime = null;
|
||||
if (chargeTimeType != null) {
|
||||
chargeTime = ChargeTimeType.fromInt(chargeTimeType);
|
||||
}
|
||||
// if (chargeTimeType != null) {
|
||||
// chargeTime = ChargeTimeType.fromInt(chargeTimeType);
|
||||
// }
|
||||
ChargeCalculationType chargeCalculation = null;
|
||||
if (chargeCalculationType != null) {
|
||||
chargeCalculation = ChargeCalculationType.fromInt(chargeCalculationType);
|
||||
}
|
||||
// if (chargeCalculationType != null) {
|
||||
// chargeCalculation =
|
||||
// ChargeCalculationType.fromInt(chargeCalculationType);
|
||||
// }
|
||||
|
||||
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation,
|
||||
specifiedDueDate);
|
||||
dueDate);
|
||||
}
|
||||
|
||||
/*
|
||||
* loanPrincipal is required for charges that are percentage based
|
||||
*/
|
||||
public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate specifiedDueDate) {
|
||||
return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, specifiedDueDate);
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate) {
|
||||
return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, dueDate);
|
||||
}
|
||||
|
||||
protected LoanCharge() {
|
||||
@@ -115,7 +118,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public LoanCharge(final Loan loan, final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate specifiedDueDate) {
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate dueDate) {
|
||||
this.loan = loan;
|
||||
this.charge = chargeDefinition;
|
||||
this.penaltyCharge = chargeDefinition.isPenalty();
|
||||
@@ -127,15 +130,15 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
if (ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE)) {
|
||||
|
||||
if (specifiedDueDate == null) {
|
||||
final String defaultUserMessage = "Loan charge is missing specified due date";
|
||||
throw new LoanChargeWithoutMandatoryFieldException("loancharge", "specifiedDueDate", defaultUserMessage,
|
||||
if (dueDate == null) {
|
||||
final String defaultUserMessage = "Loan charge is missing due date.";
|
||||
throw new LoanChargeWithoutMandatoryFieldException("loanCharge", "dueDate", defaultUserMessage,
|
||||
chargeDefinition.getId(), chargeDefinition.getName());
|
||||
}
|
||||
|
||||
this.dueForCollectionAsOfDate = specifiedDueDate.toDate();
|
||||
this.dueDate = dueDate.toDate();
|
||||
} else {
|
||||
this.dueForCollectionAsOfDate = null;
|
||||
this.dueDate = null;
|
||||
}
|
||||
|
||||
this.chargeCalculation = chargeDefinition.getChargeCalculation();
|
||||
@@ -240,7 +243,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
public void update(final BigDecimal amount, final LocalDate specifiedDueDate, final BigDecimal loanPrincipal) {
|
||||
if (specifiedDueDate != null) {
|
||||
this.dueForCollectionAsOfDate = specifiedDueDate.toDate();
|
||||
this.dueDate = specifiedDueDate.toDate();
|
||||
}
|
||||
|
||||
if (amount != null) {
|
||||
@@ -279,31 +282,37 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
final String dateFormatAsInput = command.dateFormat();
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
final String chargeTimeParamName = "chargeTime";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, this.chargeTime)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeTimeParamName);
|
||||
actualChanges.put(chargeTimeParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.chargeTime = ChargeTimeType.fromInt(newValue).getValue();
|
||||
}
|
||||
// final String chargeTimeParamName = "chargeTime";
|
||||
// if (command.isChangeInIntegerParameterNamed(chargeTimeParamName,
|
||||
// this.chargeTime)) {
|
||||
// final Integer newValue =
|
||||
// command.integerValueOfParameterNamed(chargeTimeParamName);
|
||||
// actualChanges.put(chargeTimeParamName, newValue);
|
||||
// actualChanges.put("locale", localeAsInput);
|
||||
// this.chargeTime = ChargeTimeType.fromInt(newValue).getValue();
|
||||
// }
|
||||
//
|
||||
// final String chargeCalculationParamName = "chargeCalculation";
|
||||
// if
|
||||
// (command.isChangeInIntegerParameterNamed(chargeCalculationParamName,
|
||||
// this.chargeCalculation)) {
|
||||
// final Integer newValue =
|
||||
// command.integerValueOfParameterNamed(chargeCalculationParamName);
|
||||
// actualChanges.put(chargeCalculationParamName, newValue);
|
||||
// actualChanges.put("locale", localeAsInput);
|
||||
// this.chargeCalculation =
|
||||
// ChargeCalculationType.fromInt(newValue).getValue();
|
||||
// }
|
||||
|
||||
final String chargeCalculationParamName = "chargeCalculation";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, this.chargeCalculation)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeCalculationParamName);
|
||||
actualChanges.put(chargeCalculationParamName, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.chargeCalculation = ChargeCalculationType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
final String specifiedDueDateParamName = "specifiedDueDate";
|
||||
if (command.isChangeInLocalDateParameterNamed(specifiedDueDateParamName, getDueForCollectionAsOfLocalDate())) {
|
||||
final String specifiedDueDateParamName = "dueDate";
|
||||
if (command.isChangeInLocalDateParameterNamed(specifiedDueDateParamName, getDueLocalDate())) {
|
||||
final String valueAsInput = command.stringValueOfParameterNamed(specifiedDueDateParamName);
|
||||
actualChanges.put(specifiedDueDateParamName, valueAsInput);
|
||||
actualChanges.put("dateFormat", dateFormatAsInput);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
|
||||
final LocalDate newValue = command.localDateValueOfParameterNamed(specifiedDueDateParamName);
|
||||
this.dueForCollectionAsOfDate = newValue.toDate();
|
||||
this.dueDate = newValue.toDate();
|
||||
}
|
||||
|
||||
final String amountParamName = "amount";
|
||||
@@ -355,13 +364,13 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
|
||||
public LoanChargeCommand toCommand() {
|
||||
return new LoanChargeCommand(this.getId(), this.charge.getId(), this.amount, this.chargeTime, this.chargeCalculation,
|
||||
getDueForCollectionAsOfLocalDate());
|
||||
getDueLocalDate());
|
||||
}
|
||||
|
||||
public LocalDate getDueForCollectionAsOfLocalDate() {
|
||||
public LocalDate getDueLocalDate() {
|
||||
LocalDate specifiedDueDate = null;
|
||||
if (this.dueForCollectionAsOfDate != null) {
|
||||
specifiedDueDate = new LocalDate(this.dueForCollectionAsOfDate);
|
||||
if (this.dueDate != null) {
|
||||
specifiedDueDate = new LocalDate(this.dueDate);
|
||||
}
|
||||
return specifiedDueDate;
|
||||
}
|
||||
@@ -418,7 +427,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
}
|
||||
|
||||
public boolean isDueForCollectionFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
||||
final LocalDate specifiedDueDate = getDueForCollectionAsOfLocalDate();
|
||||
final LocalDate specifiedDueDate = getDueLocalDate();
|
||||
return occursOnDayFromAndUpToAndIncluding(fromNotInclusive, upToAndInclusive, specifiedDueDate);
|
||||
}
|
||||
|
||||
@@ -508,7 +517,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
.append(this.getId(), rhs.getId()) //
|
||||
.append(this.charge.getId(), rhs.charge.getId()) //
|
||||
.append(this.amount, rhs.amount) //
|
||||
.append(this.getDueForCollectionAsOfLocalDate(), rhs.getDueForCollectionAsOfLocalDate()) //
|
||||
.append(this.getDueLocalDate(), rhs.getDueLocalDate()) //
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@@ -517,7 +526,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
||||
return new HashCodeBuilder(3, 5) //
|
||||
.append(this.getId()) //
|
||||
.append(this.charge.getId()) //
|
||||
.append(this.amount).append(this.getDueForCollectionAsOfLocalDate()) //
|
||||
.append(this.amount).append(this.getDueLocalDate()) //
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.portfolio.loanaccount.serialization;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* Implementation of {@link FromApiJsonDeserializer} for
|
||||
* {@link LoanChargeCommand}'s.
|
||||
*/
|
||||
@Component
|
||||
public final class LoanChargeCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<LoanChargeCommand> {
|
||||
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("id", "chargeId", "amount", "chargeTimeType",
|
||||
"chargeCalculationType", "specifiedDueDate", "locale", "dateFormat"));
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public LoanChargeCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanChargeCommand commandFromApiJson(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
final Long id = fromApiJsonHelper.extractLongNamed("id", element);
|
||||
final Long chargeId = fromApiJsonHelper.extractLongNamed("chargeId", element);
|
||||
final BigDecimal amount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element);
|
||||
final Integer chargeTimeType = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeTimeType", element);
|
||||
final Integer chargeCalculationType = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeCalculationType", element);
|
||||
final LocalDate dueAsOfDate = fromApiJsonHelper.extractLocalDateNamed("specifiedDueDate", element);
|
||||
|
||||
return new LoanChargeCommand(id, chargeId, amount, chargeTimeType, chargeCalculationType, dueAsOfDate);
|
||||
}
|
||||
}
|
||||
+49
@@ -111,4 +111,53 @@ public final class LoanEventApiJsonValidator {
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateAddLoanCharge(final String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("chargeId", "amount", "dueDate", "locale",
|
||||
"dateFormat"));
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanCharge");
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
final Long chargeId = fromApiJsonHelper.extractLongNamed("chargeId", element);
|
||||
baseDataValidator.reset().parameter("chargeId").value(chargeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final BigDecimal amount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element);
|
||||
baseDataValidator.reset().parameter("amount").value(amount).notNull().positiveAmount();
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("dueDate", element)) {
|
||||
fromApiJsonHelper.extractLocalDateNamed("dueDate", element);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateUpdateOfLoanCharge(final String json) {
|
||||
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
|
||||
|
||||
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("amount", "dueDate", "locale", "dateFormat"));
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanCharge");
|
||||
|
||||
final JsonElement element = fromApiJsonHelper.parse(json);
|
||||
|
||||
final BigDecimal amount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element);
|
||||
baseDataValidator.reset().parameter("amount").value(amount).notNull().positiveAmount();
|
||||
|
||||
if (fromApiJsonHelper.parameterExists("dueDate", element)) {
|
||||
fromApiJsonHelper.extractLocalDateNamed("dueDate", element);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
+4
-9
@@ -14,10 +14,8 @@ import org.joda.time.LocalDate;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeTimeType;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeIsNotActiveException;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException;
|
||||
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanChargeRepository;
|
||||
@@ -32,11 +30,11 @@ import com.google.gson.JsonObject;
|
||||
public class LoanChargeAssembler {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final ChargeRepository chargeRepository;
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
private final LoanChargeRepository loanChargeRepository;
|
||||
|
||||
@Autowired
|
||||
public LoanChargeAssembler(final FromJsonHelper fromApiJsonHelper, final ChargeRepository chargeRepository,
|
||||
public LoanChargeAssembler(final FromJsonHelper fromApiJsonHelper, final ChargeRepositoryWrapper chargeRepository,
|
||||
final LoanChargeRepository loanChargeRepository) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.chargeRepository = chargeRepository;
|
||||
@@ -69,10 +67,7 @@ public class LoanChargeAssembler {
|
||||
dateFormat, locale);
|
||||
|
||||
if (id == null) {
|
||||
final Charge chargeDefinition = this.chargeRepository.findOne(chargeId);
|
||||
if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(chargeId); }
|
||||
|
||||
if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(chargeId, chargeDefinition.getName()); }
|
||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeId);
|
||||
ChargeTimeType chargeTime = null;
|
||||
if (chargeTimeType != null) {
|
||||
ChargeTimeType.fromInt(chargeTimeType);
|
||||
|
||||
+10
-29
@@ -23,13 +23,10 @@ import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepository;
|
||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeIsNotActiveException;
|
||||
import org.mifosplatform.portfolio.charge.exception.ChargeNotFoundException;
|
||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
|
||||
import org.mifosplatform.portfolio.client.domain.Note;
|
||||
import org.mifosplatform.portfolio.client.domain.NoteRepository;
|
||||
import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand;
|
||||
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
||||
@@ -44,7 +41,6 @@ import org.mifosplatform.portfolio.loanaccount.exception.LoanNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentException;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
|
||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanChargeCommandFromApiJsonDeserializer;
|
||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanEventApiJsonValidator;
|
||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
|
||||
import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||
@@ -58,13 +54,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final LoanEventApiJsonValidator loanEventApiJsonValidator;
|
||||
private final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer;
|
||||
private final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer;
|
||||
private final LoanRepository loanRepository;
|
||||
private final NoteRepository noteRepository;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanAssembler loanAssembler;
|
||||
private final ChargeRepository chargeRepository;
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
private final LoanChargeRepository loanChargeRepository;
|
||||
private final ApplicationCurrencyRepository applicationCurrencyRepository;
|
||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||
@@ -72,15 +67,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Autowired
|
||||
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
final LoanEventApiJsonValidator loanEventApiJsonValidator,
|
||||
final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer,
|
||||
final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer, final LoanAssembler loanAssembler,
|
||||
final LoanRepository loanRepository, final LoanTransactionRepository loanTransactionRepository,
|
||||
final NoteRepository noteRepository, final ChargeRepository chargeRepository, final LoanChargeRepository loanChargeRepository,
|
||||
final NoteRepository noteRepository, final ChargeRepositoryWrapper chargeRepository,
|
||||
final LoanChargeRepository loanChargeRepository,
|
||||
final ApplicationCurrencyRepository applicationCurrencyRepository,
|
||||
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
||||
this.context = context;
|
||||
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
|
||||
this.loanChargeCommandFromApiJsonDeserializer = loanChargeCommandFromApiJsonDeserializer;
|
||||
this.loanAssembler = loanAssembler;
|
||||
this.loanRepository = loanRepository;
|
||||
this.loanTransactionRepository = loanTransactionRepository;
|
||||
@@ -472,24 +466,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult addLoanCharge(final Long loanId, final JsonCommand command) {
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
// FIXME - KW - update loan charge api validation
|
||||
final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
|
||||
// loanChargeCommand.validateForCreate();
|
||||
this.loanEventApiJsonValidator.validateAddLoanCharge(command.json());
|
||||
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
|
||||
final Long chargeDefinitionId = command.longValueOfParameterNamed("chargeId");
|
||||
final Charge chargeDefinition = this.chargeRepository.findOne(chargeDefinitionId);
|
||||
if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(chargeDefinitionId); }
|
||||
if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(chargeDefinition.getId(), chargeDefinition.getName()); }
|
||||
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
|
||||
|
||||
final LoanCharge loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command);
|
||||
|
||||
if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())) {
|
||||
String errorMessage = "Charge and Loan must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage);
|
||||
final String errorMessage = "Charge and Loan must have the same currency.";
|
||||
throw new InvalidCurrencyException("loanCharge", "attach.to.loan", errorMessage);
|
||||
}
|
||||
|
||||
this.loanChargeRepository.save(loanCharge);
|
||||
@@ -513,8 +504,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
|
||||
loanChargeCommand.validateForUpdate();
|
||||
this.loanEventApiJsonValidator.validateUpdateOfLoanCharge(command.json());
|
||||
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||
@@ -540,9 +530,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
|
||||
loanChargeCommand.validateForUpdate();
|
||||
|
||||
final Loan loan = retrieveLoanBy(loanId);
|
||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||
|
||||
@@ -553,12 +540,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
||||
this.loanTransactionRepository.save(waiveTransaction);
|
||||
this.loanRepository.save(loan);
|
||||
|
||||
final String noteText = ""; // command.getNote();
|
||||
if (StringUtils.isNotBlank(noteText)) {
|
||||
final Note note = Note.loanTransactionNote(loan, waiveTransaction, noteText);
|
||||
this.noteRepository.save(note);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withCommandId(command.commandId()) //
|
||||
.withEntityId(loanChargeId) //
|
||||
|
||||
+51
-45
@@ -187,10 +187,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
if (interestCompoundingAllowed) {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenureInMonths,
|
||||
maturityInterestRate, interestCompoundedEvery, interestCompoundedFrequencyPeriodType);
|
||||
maturityInterestRate, interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||
tenureInMonths, maturityInterestRate, interestCompoundedEvery, interestCompoundedFrequencyPeriodType);
|
||||
tenureInMonths, maturityInterestRate, interestCompoundedEvery);
|
||||
}
|
||||
|
||||
DepositAccountStatus from = null;
|
||||
@@ -278,11 +278,12 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.externalId = this.getId() + "_" + this.externalId;
|
||||
}
|
||||
|
||||
public Map<String, Object> approve(final LocalDate actualCommencementDate, final DepositLifecycleStateMachine depositLifecycleStateMachine,
|
||||
final JsonCommand command, final FixedTermDepositInterestCalculator calculator) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(20);
|
||||
final String localeAsInput = command.locale();
|
||||
public Map<String, Object> approve(final LocalDate actualCommencementDate,
|
||||
final DepositLifecycleStateMachine depositLifecycleStateMachine, final JsonCommand command,
|
||||
final FixedTermDepositInterestCalculator calculator) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(20);
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_APPROVED,
|
||||
DepositAccountStatus.fromInt(this.depositStatus));
|
||||
@@ -295,7 +296,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.tenureInMonths = newValue;
|
||||
}
|
||||
|
||||
|
||||
final String maturityInterestRateParamName = "maturityInterestRate";
|
||||
if (command.isChangeInBigDecimalParameterNamed(maturityInterestRateParamName, this.interestRate)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maturityInterestRateParamName);
|
||||
@@ -313,7 +314,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.depositAmount = newValue;
|
||||
}
|
||||
this.product.validateDepositInRange(this.depositAmount);
|
||||
|
||||
|
||||
final String interestCompoundedEveryParamName = "interestCompoundedEvery";
|
||||
if (command.isChangeInIntegerParameterNamed(interestCompoundedEveryParamName, this.interestCompoundedEvery)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(interestCompoundedEveryParamName);
|
||||
@@ -337,15 +338,16 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
if (this.interestCompoundingAllowed) {
|
||||
futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths, this.interestRate,
|
||||
this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
|
||||
this.interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = calculator.calculateInterestOnMaturityForSimpleInterest(getDeposit(), this.tenureInMonths,
|
||||
this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
|
||||
this.interestRate, this.interestCompoundedEvery);
|
||||
}
|
||||
this.interestAccrued = futureValueOnMaturity.minus(getDeposit()).getAmount();
|
||||
this.total = futureValueOnMaturity.getAmount();
|
||||
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.deposit(getDeposit(), getActualCommencementDate(), null);
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.deposit(getDeposit(), getActualCommencementDate(),
|
||||
null);
|
||||
depositaccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||
|
||||
@@ -368,7 +370,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
throw new InvalidDepositStateTransitionException("approval", "cannot.be.a.future.date", errorMessage,
|
||||
getActualCommencementDate());
|
||||
}
|
||||
return actualChanges;
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public LocalDate getActualCommencementDate() {
|
||||
@@ -592,8 +594,11 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
preClosureInterestRate);
|
||||
this.interestAccrued = this.interestAccrued.add(accuredInterestAfterMaturityToTillDate.getAmount());
|
||||
this.availableInterest = this.availableInterest.add(accuredInterestAfterMaturityToTillDate.getAmount());
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate,Money.of(currency, this.availableInterest),getDeposit().getAmount().add(this.availableInterest));
|
||||
//DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate, getAccuredInterest());
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate,
|
||||
Money.of(currency, this.availableInterest), getDeposit().getAmount().add(this.availableInterest));
|
||||
// DepositAccountTransaction depositaccountTransaction =
|
||||
// DepositAccountTransaction.withdraw(getDeposit(), eventDate,
|
||||
// getAccuredInterest());
|
||||
depositaccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||
|
||||
@@ -651,8 +656,11 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
@SuppressWarnings("unused")
|
||||
boolean statustest = isActive();
|
||||
if (isActive()) {
|
||||
//DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest);
|
||||
DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest,getDeposit().getAmount().add(this.availableInterest).subtract(interest.getAmount()));
|
||||
// DepositAccountTransaction depositAccountTransaction =
|
||||
// DepositAccountTransaction.withdraw(null, new LocalDate(),
|
||||
// interest);
|
||||
DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest,
|
||||
getDeposit().getAmount().add(this.availableInterest).subtract(interest.getAmount()));
|
||||
depositAccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositAccountTransaction);
|
||||
this.interstPaid = this.interstPaid.add(interest.getAmount());
|
||||
@@ -667,9 +675,13 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
DepositAccountStatus.fromInt(this.depositStatus));
|
||||
this.depositStatus = statusEnumForClose.getValue();
|
||||
|
||||
//DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit()));
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit()),
|
||||
getDeposit().plus(Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit())).getAmount());
|
||||
// DepositAccountTransaction depositaccountTransaction =
|
||||
// DepositAccountTransaction.withdraw(getDeposit(), new
|
||||
// LocalDate(),Money.of(getDeposit().getCurrency(),
|
||||
// getTotal()).minus(getDeposit()));
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),
|
||||
Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit()),
|
||||
getDeposit().plus(Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit())).getAmount());
|
||||
depositaccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||
|
||||
@@ -687,10 +699,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
if (isInterestCompoundingAllowed) {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenureInMonths,
|
||||
maturityInterestRate, interestCompoundedEvery, compoundingInterestFrequency);
|
||||
maturityInterestRate, interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||
tenureInMonths, maturityInterestRate, interestCompoundedEvery, compoundingInterestFrequency);
|
||||
tenureInMonths, maturityInterestRate, interestCompoundedEvery);
|
||||
}
|
||||
|
||||
setExternalId(externalId);
|
||||
@@ -747,18 +759,17 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
if (lastInterestPostedDate.isBefore(getMaturityDate())) {
|
||||
if (nextInterestPostingDate.isAfter(getMaturityDate())) {
|
||||
Integer noofRemainMonthsAfterMaturity = Months.monthsBetween(getMaturityDate(), nextInterestPostingDate).getMonths();
|
||||
Integer noOfMonthsBeforeMaturity = Months.monthsBetween(lastInterestPostedDate, getMaturityDate().plusDays(1)).getMonths();
|
||||
Money futureValueOnMaturity = null;
|
||||
Integer noOfMonthsBeforeMaturity = Months.monthsBetween(lastInterestPostedDate, getMaturityDate().plusDays(1))
|
||||
.getMonths();
|
||||
Money futureValueOnMaturity = Money.zero(this.currency);
|
||||
if (noOfMonthsBeforeMaturity > 0) {
|
||||
|
||||
if (this.interestCompoundingAllowed) {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||
noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(
|
||||
deposit, noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
deposit, noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery);
|
||||
}
|
||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
@@ -770,12 +781,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
|
||||
if (this.interestCompoundingAllowed) {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||
noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(
|
||||
deposit, noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
deposit, noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||
}
|
||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
@@ -784,8 +793,8 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
}
|
||||
|
||||
// add transaction entry for each interest posting
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,futureValueOnMaturity.minus(deposit),deposit.getAmount().add(this.availableInterest));
|
||||
//DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate, futureValueOnMaturity.minus(deposit));
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null,
|
||||
nextInterestPostingDate, futureValueOnMaturity.minus(deposit), deposit.getAmount().add(this.availableInterest));
|
||||
|
||||
depositaccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||
@@ -793,12 +802,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
Money futureValueOnMaturity = null;
|
||||
if (this.interestCompoundingAllowed) {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery);
|
||||
}
|
||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
@@ -806,8 +813,8 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
|
||||
|
||||
// add transaction entry for each interest posting
|
||||
// DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate, futureValueOnMaturity.minus(deposit));
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,futureValueOnMaturity.minus(deposit),deposit.getAmount().add(this.availableInterest));
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null,
|
||||
nextInterestPostingDate, futureValueOnMaturity.minus(deposit), deposit.getAmount().add(this.availableInterest));
|
||||
depositaccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||
}
|
||||
@@ -815,12 +822,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
Money futureValueOnMaturity = null;
|
||||
if (this.interestCompoundingAllowed) {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||
} else {
|
||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery,
|
||||
getInterestCompoundedFrequencyType());
|
||||
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||
}
|
||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||
@@ -828,7 +833,8 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
||||
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
|
||||
|
||||
// add transaction entry for each interest posting
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate, futureValueOnMaturity.minus(deposit),deposit.getAmount().add(this.availableInterest));
|
||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,
|
||||
futureValueOnMaturity.minus(deposit), deposit.getAmount().add(this.availableInterest));
|
||||
depositaccountTransaction.updateAccount(this);
|
||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||
}
|
||||
|
||||
+3
-14
@@ -10,25 +10,14 @@ import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class FixedTermDepositInterestCalculator {
|
||||
|
||||
// FIXME - HUGO - Are the unused field here needed?
|
||||
public Money calculateInterestOnMaturityFor(final Money deposit, final Integer tenureInMonths, final BigDecimal maturityInterestRate,
|
||||
final Integer interestCompoundedEvery, final PeriodFrequencyType interestCompoundedFrequencyPeriodType) {
|
||||
final Integer interestCompoundedEvery) {
|
||||
|
||||
// TODO - HUGO - Can change 'interest compounding' fields into something
|
||||
// simpler like interestCompoundedFrequency {None (Simple Interest),
|
||||
// Monthly, Quarterly, Half-Yearly, Annually}
|
||||
// - the 'interestCompoundedEvery' would then be inferred form the
|
||||
// selected type.
|
||||
// - the special case of 'simple interest' or 'no compounding' would use
|
||||
// simple formula rather than 'future value' function.
|
||||
|
||||
// FIXME - HUGO - assuming only monthly compounding period for now
|
||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||
Integer monthsInYear = 12;
|
||||
|
||||
@@ -72,8 +61,8 @@ public class FixedTermDepositInterestCalculator {
|
||||
return retval;
|
||||
}
|
||||
|
||||
public Money calculateInterestOnMaturityForSimpleInterest(final Money deposit, final Integer tenureInMonths, final BigDecimal maturityInterestRate,
|
||||
final Integer interestCompoundedEvery, final PeriodFrequencyType interestCompoundedFrequencyPeriodType) {
|
||||
public Money calculateInterestOnMaturityForSimpleInterest(final Money deposit, final Integer tenureInMonths,
|
||||
final BigDecimal maturityInterestRate, final Integer interestCompoundedEvery) {
|
||||
|
||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||
Integer monthsInYear = 12;
|
||||
|
||||
Reference in New Issue
Block a user