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` (
|
CREATE TABLE `m_group` (
|
||||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
`office_id` bigint(20) NOT NULL,
|
`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,
|
`name` varchar(100) DEFAULT NULL,
|
||||||
`external_id` varchar(100) DEFAULT NULL,
|
`external_id` varchar(100) DEFAULT NULL,
|
||||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
|
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
|
||||||
@@ -740,9 +743,13 @@ CREATE TABLE `m_group` (
|
|||||||
UNIQUE KEY `name` (`name`),
|
UNIQUE KEY `name` (`name`),
|
||||||
UNIQUE KEY `external_id` (`external_id`),
|
UNIQUE KEY `external_id` (`external_id`),
|
||||||
KEY `office_id` (`office_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 `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;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!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 */;
|
/*!40000 ALTER TABLE `m_group_client` ENABLE KEYS */;
|
||||||
UNLOCK TABLES;
|
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`
|
-- Table structure for table `m_guarantor`
|
||||||
--
|
--
|
||||||
@@ -1933,4 +1969,4 @@ UNLOCK TABLES;
|
|||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!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;
|
package org.mifosplatform.portfolio.loanaccount.command;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable command for creating and updating loan charges.
|
* Java object representation of {@link LoanCharge} API JSON.
|
||||||
*/
|
*/
|
||||||
public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
||||||
|
|
||||||
@@ -23,10 +19,12 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
|||||||
private final Long id;
|
private final Long id;
|
||||||
private final Long chargeId;
|
private final Long chargeId;
|
||||||
private final BigDecimal amount;
|
private final BigDecimal amount;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final Integer chargeTimeType;
|
private final Integer chargeTimeType;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private final Integer chargeCalculationType;
|
private final Integer chargeCalculationType;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final LocalDate specifiedDueDate;
|
private final LocalDate dueDate;
|
||||||
|
|
||||||
public LoanChargeCommand(final Long id, final Long chargeId, final BigDecimal amount, final Integer chargeTimeType,
|
public LoanChargeCommand(final Long id, final Long chargeId, final BigDecimal amount, final Integer chargeTimeType,
|
||||||
final Integer chargeCalculationType, final LocalDate specifiedDueDate) {
|
final Integer chargeCalculationType, final LocalDate specifiedDueDate) {
|
||||||
@@ -35,7 +33,7 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
|||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.chargeTimeType = chargeTimeType;
|
this.chargeTimeType = chargeTimeType;
|
||||||
this.chargeCalculationType = chargeCalculationType;
|
this.chargeCalculationType = chargeCalculationType;
|
||||||
this.specifiedDueDate = specifiedDueDate;
|
this.dueDate = specifiedDueDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -46,18 +44,4 @@ public class LoanChargeCommand implements Comparable<LoanChargeCommand> {
|
|||||||
}
|
}
|
||||||
return comparison;
|
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;
|
private final EnumOptionData chargeTimeType;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final LocalDate dueAsOfDate;
|
private final LocalDate dueDate;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final EnumOptionData chargeCalculationType;
|
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,
|
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 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 EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo,
|
||||||
final boolean penalty) {
|
final boolean penalty) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@@ -94,7 +94,7 @@ public class LoanChargeData {
|
|||||||
this.amountWrittenOff = amountWrittenOff;
|
this.amountWrittenOff = amountWrittenOff;
|
||||||
this.amountOutstanding = amountOutstanding;
|
this.amountOutstanding = amountOutstanding;
|
||||||
this.chargeTimeType = chargeTimeType;
|
this.chargeTimeType = chargeTimeType;
|
||||||
this.dueAsOfDate = dueAsOfDate;
|
this.dueDate = dueDate;
|
||||||
this.chargeCalculationType = chargeCalculationType;
|
this.chargeCalculationType = chargeCalculationType;
|
||||||
this.percentage = percentage;
|
this.percentage = percentage;
|
||||||
this.amountPercentageAppliedTo = amountPercentageAppliedTo;
|
this.amountPercentageAppliedTo = amountPercentageAppliedTo;
|
||||||
@@ -122,7 +122,7 @@ public class LoanChargeData {
|
|||||||
this.amountWrittenOff = BigDecimal.ZERO;
|
this.amountWrittenOff = BigDecimal.ZERO;
|
||||||
this.amountOutstanding = amount;
|
this.amountOutstanding = amount;
|
||||||
this.chargeTimeType = chargeTimeType;
|
this.chargeTimeType = chargeTimeType;
|
||||||
this.dueAsOfDate = null;
|
this.dueDate = null;
|
||||||
this.chargeCalculationType = chargeCalculationType;
|
this.chargeCalculationType = chargeCalculationType;
|
||||||
this.percentage = null;
|
this.percentage = null;
|
||||||
this.amountPercentageAppliedTo = null;
|
this.amountPercentageAppliedTo = null;
|
||||||
|
|||||||
+1
-1
@@ -150,7 +150,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
for (LoanCharge loanCharge : charges) {
|
for (LoanCharge loanCharge : charges) {
|
||||||
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
if (loanCharge.isNotFullyPaid() && !loanCharge.isDueAtDisbursement()) {
|
||||||
if (earliestUnpaidCharge == null
|
if (earliestUnpaidCharge == null
|
||||||
|| loanCharge.getDueForCollectionAsOfLocalDate().isBefore(earliestUnpaidCharge.getDueForCollectionAsOfLocalDate())) {
|
|| loanCharge.getDueLocalDate().isBefore(earliestUnpaidCharge.getDueLocalDate())) {
|
||||||
earliestUnpaidCharge = loanCharge;
|
earliestUnpaidCharge = loanCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-49
@@ -322,7 +322,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
Money chargesDue = Money.of(getCurrency(), BigDecimal.ZERO);
|
Money chargesDue = Money.of(getCurrency(), BigDecimal.ZERO);
|
||||||
|
|
||||||
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
|
for (LoanCharge charge : setOfLoanCharges()) {
|
||||||
if (charge.isDueAtDisbursement()) {
|
if (charge.isDueAtDisbursement()) {
|
||||||
chargesDue = chargesDue.plus(charge.amount());
|
chargesDue = chargesDue.plus(charge.amount());
|
||||||
}
|
}
|
||||||
@@ -362,7 +362,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
validateLoanIsNotClosed(loanCharge);
|
validateLoanIsNotClosed(loanCharge);
|
||||||
|
|
||||||
if (isDisbursed() && loanCharge.isDueAtDisbursement()) {
|
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
|
// after it is disbursed
|
||||||
// if the loan charge payment type is 'Disbursement'.
|
// if the loan charge payment type is 'Disbursement'.
|
||||||
// To undo this constraint would mean resolving how charges due are
|
// 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());
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||||
|
|
||||||
loanCharge.update(this);
|
loanCharge.update(this);
|
||||||
getNullPointerSafeLoanCharges().add(loanCharge);
|
setOfLoanCharges().add(loanCharge);
|
||||||
|
|
||||||
updateTotalChargesDueAtDisbursement();
|
updateTotalChargesDueAtDisbursement();
|
||||||
|
|
||||||
@@ -390,11 +391,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (!loanCharge.isDueAtDisbursement()) {
|
if (!loanCharge.isDueAtDisbursement()) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
} else {
|
} else {
|
||||||
// just reprocess the loan schedule only for now.
|
// just reprocess the loan schedule only for now.
|
||||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
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.
|
// if you want ability to remove loan charges that are waived.
|
||||||
validateLoanChargeIsNotWaived(loanCharge);
|
validateLoanChargeIsNotWaived(loanCharge);
|
||||||
|
|
||||||
boolean removed = getNullPointerSafeLoanCharges().remove(loanCharge);
|
boolean removed = setOfLoanCharges().remove(loanCharge);
|
||||||
if (removed) {
|
if (removed) {
|
||||||
updateTotalChargesDueAtDisbursement();
|
updateTotalChargesDueAtDisbursement();
|
||||||
}
|
}
|
||||||
@@ -447,7 +448,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
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);
|
validateLoanIsNotClosed(loanCharge);
|
||||||
|
|
||||||
if (getNullPointerSafeLoanCharges().contains(loanCharge)) {
|
if (setOfLoanCharges().contains(loanCharge)) {
|
||||||
final Map<String, Object> loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount());
|
final Map<String, Object> loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount());
|
||||||
actualChanges.putAll(loanChargeChanges);
|
actualChanges.putAll(loanChargeChanges);
|
||||||
updateTotalChargesDueAtDisbursement();
|
updateTotalChargesDueAtDisbursement();
|
||||||
@@ -495,11 +496,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (!loanCharge.isDueAtDisbursement()) {
|
if (!loanCharge.isDueAtDisbursement()) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
} else {
|
} else {
|
||||||
// reprocess loan schedule based on charge been waived.
|
// reprocess loan schedule based on charge been waived.
|
||||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
||||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
}
|
}
|
||||||
|
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
@@ -523,7 +524,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
LocalDate transactionDate = getDisbursementDate();
|
LocalDate transactionDate = getDisbursementDate();
|
||||||
if (loanCharge.isSpecifiedDueDate()) {
|
if (loanCharge.isSpecifiedDueDate()) {
|
||||||
transactionDate = loanCharge.getDueForCollectionAsOfLocalDate();
|
transactionDate = loanCharge.getDueLocalDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTotalChargesDueAtDisbursement();
|
updateTotalChargesDueAtDisbursement();
|
||||||
@@ -538,11 +539,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loanCurrency())) {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
} else {
|
} else {
|
||||||
// reprocess loan schedule based on charge been waived.
|
// reprocess loan schedule based on charge been waived.
|
||||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
||||||
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
}
|
}
|
||||||
|
|
||||||
doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
doPostLoanTransactionChecks(waiveLoanChargeTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
@@ -595,8 +596,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
|
public void updateLoanCharges(final Set<LoanCharge> loanCharges) {
|
||||||
getNullPointerSafeLoanCharges().clear();
|
setOfLoanCharges().clear();
|
||||||
getNullPointerSafeLoanCharges().addAll(associateChargesWithThisLoan(loanCharges));
|
setOfLoanCharges().addAll(associateChargesWithThisLoan(loanCharges));
|
||||||
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
|
this.totalChargesDueAtDisbursement = deriveSumTotalOfChargesDueAtDisbursement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,7 +631,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor
|
||||||
.determineProcessor(this.transactionProcessingStrategy);
|
.determineProcessor(this.transactionProcessingStrategy);
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), repaymentsOrWaivers, getCurrency(),
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), repaymentsOrWaivers, getCurrency(),
|
||||||
this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLoanScheduleDependentDerivedFields() {
|
public void updateLoanScheduleDependentDerivedFields() {
|
||||||
@@ -785,7 +786,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
final String chargesParamName = "charges";
|
final String chargesParamName = "charges";
|
||||||
if (command.parameterExists(chargesParamName)) {
|
if (command.parameterExists(chargesParamName)) {
|
||||||
|
|
||||||
final Set<LoanCharge> existingLoanCharges = getNullPointerSafeLoanCharges();
|
final Set<LoanCharge> existingLoanCharges = setOfLoanCharges();
|
||||||
|
|
||||||
if (!possiblyModifedLoanCharges.equals(existingLoanCharges)) {
|
if (!possiblyModifedLoanCharges.equals(existingLoanCharges)) {
|
||||||
actualChanges.put(chargesParamName, getLoanCharges(possiblyModifedLoanCharges));
|
actualChanges.put(chargesParamName, getLoanCharges(possiblyModifedLoanCharges));
|
||||||
@@ -797,20 +798,6 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
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";
|
final String collateralParamName = "collateral";
|
||||||
@@ -819,22 +806,12 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (!possiblyModifedLoanCollateralItems.equals(this.collateral)) {
|
if (!possiblyModifedLoanCollateralItems.equals(this.collateral)) {
|
||||||
actualChanges.put(collateralParamName, listOfLoanCollateralData(possiblyModifedLoanCollateralItems));
|
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;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<LoanCharge> getNullPointerSafeLoanCharges() {
|
private Set<LoanCharge> setOfLoanCharges() {
|
||||||
Set<LoanCharge> loanCharges = this.charges;
|
Set<LoanCharge> loanCharges = this.charges;
|
||||||
if (this.charges == null) {
|
if (this.charges == null) {
|
||||||
loanCharges = new HashSet<LoanCharge>();
|
loanCharges = new HashSet<LoanCharge>();
|
||||||
@@ -933,7 +910,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// charges are optional
|
// charges are optional
|
||||||
for (LoanCharge loanCharge : getNullPointerSafeLoanCharges()) {
|
for (LoanCharge loanCharge : setOfLoanCharges()) {
|
||||||
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
validateChargeHasValidSpecifiedDateIfApplicable(loanCharge, getDisbursementDate(), getLastRepaymentPeriodDueDate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1190,7 +1167,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, interestRatePerPeriod,
|
final LoanSchedule loanSchedule = new LoanSchedule(loanScheduleGenerator, applicationCurrency, principal, interestRatePerPeriod,
|
||||||
interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod,
|
interestRatePeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod,
|
||||||
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency,
|
repaymentEvery, repaymentPeriodFrequencyType, numberOfRepayments, amortizationMethod, loanTermFrequency,
|
||||||
loanTermPeriodFrequencyType, getNullPointerSafeLoanCharges(), this.getDisbursementDate(),
|
loanTermPeriodFrequencyType, setOfLoanCharges(), this.getDisbursementDate(),
|
||||||
this.getExpectedFirstRepaymentOnDate(), this.getInterestChargedFromDate(), inArrearsTolerance);
|
this.getExpectedFirstRepaymentOnDate(), this.getInterestChargedFromDate(), inArrearsTolerance);
|
||||||
|
|
||||||
final LoanScheduleData generatedData = loanSchedule.generate();
|
final LoanScheduleData generatedData = loanSchedule.generate();
|
||||||
@@ -1215,7 +1192,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
chargesPayment.updateLoan(this);
|
chargesPayment.updateLoan(this);
|
||||||
this.loanTransactions.add(chargesPayment);
|
this.loanTransactions.add(chargesPayment);
|
||||||
|
|
||||||
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
|
for (LoanCharge charge : setOfLoanCharges()) {
|
||||||
if (charge.isDueAtDisbursement()) {
|
if (charge.isDueAtDisbursement()) {
|
||||||
charge.markAsFullyPaid();
|
charge.markAsFullyPaid();
|
||||||
}
|
}
|
||||||
@@ -1281,7 +1258,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
private void updateLoanToPreDisbursalState() {
|
private void updateLoanToPreDisbursalState() {
|
||||||
this.actualDisbursementDate = null;
|
this.actualDisbursementDate = null;
|
||||||
|
|
||||||
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
|
for (LoanCharge charge : setOfLoanCharges()) {
|
||||||
charge.resetToOriginal(loanCurrency());
|
charge.resetToOriginal(loanCurrency());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1290,7 +1267,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoanScheduleWrapper wrapper = new LoanScheduleWrapper();
|
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) {
|
public LoanTransaction waiveInterest(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
@@ -1370,11 +1347,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
.determineProcessor(this.transactionProcessingStrategy);
|
.determineProcessor(this.transactionProcessingStrategy);
|
||||||
if (isTransactionChronologicallyLatest && adjustedTransaction == null) {
|
if (isTransactionChronologicallyLatest && adjustedTransaction == null) {
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments,
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(loanTransaction, getCurrency(), this.repaymentScheduleInstallments,
|
||||||
getNullPointerSafeLoanCharges());
|
setOfLoanCharges());
|
||||||
} else {
|
} else {
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
|
||||||
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
|
||||||
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
|
getCurrency(), this.repaymentScheduleInstallments, setOfLoanCharges());
|
||||||
}
|
}
|
||||||
|
|
||||||
doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
|
|||||||
+54
-45
@@ -50,7 +50,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
@Temporal(TemporalType.DATE)
|
@Temporal(TemporalType.DATE)
|
||||||
@Column(name = "due_for_collection_as_of_date")
|
@Column(name = "due_for_collection_as_of_date")
|
||||||
private Date dueForCollectionAsOfDate;
|
private Date dueDate;
|
||||||
|
|
||||||
@Column(name = "charge_calculation_enum")
|
@Column(name = "charge_calculation_enum")
|
||||||
private Integer chargeCalculation;
|
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) {
|
public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeDefinition, final JsonCommand command) {
|
||||||
|
|
||||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||||
final Integer chargeTimeType = command.integerValueOfParameterNamed("chargeTimeType");
|
// final Integer chargeTimeType =
|
||||||
final Integer chargeCalculationType = command.integerValueOfParameterNamed("chargeCalculationType");
|
// command.integerValueOfParameterNamed("chargeTimeType");
|
||||||
final LocalDate specifiedDueDate = command.localDateValueOfParameterNamed("specifiedDueDate");
|
// final Integer chargeCalculationType =
|
||||||
|
// command.integerValueOfParameterNamed("chargeCalculationType");
|
||||||
|
final LocalDate dueDate = command.localDateValueOfParameterNamed("dueDate");
|
||||||
|
|
||||||
ChargeTimeType chargeTime = null;
|
ChargeTimeType chargeTime = null;
|
||||||
if (chargeTimeType != null) {
|
// if (chargeTimeType != null) {
|
||||||
chargeTime = ChargeTimeType.fromInt(chargeTimeType);
|
// chargeTime = ChargeTimeType.fromInt(chargeTimeType);
|
||||||
}
|
// }
|
||||||
ChargeCalculationType chargeCalculation = null;
|
ChargeCalculationType chargeCalculation = null;
|
||||||
if (chargeCalculationType != null) {
|
// if (chargeCalculationType != null) {
|
||||||
chargeCalculation = ChargeCalculationType.fromInt(chargeCalculationType);
|
// chargeCalculation =
|
||||||
}
|
// ChargeCalculationType.fromInt(chargeCalculationType);
|
||||||
|
// }
|
||||||
|
|
||||||
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation,
|
return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation,
|
||||||
specifiedDueDate);
|
dueDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* loanPrincipal is required for charges that are percentage based
|
* loanPrincipal is required for charges that are percentage based
|
||||||
*/
|
*/
|
||||||
public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount,
|
public static LoanCharge createNewWithoutLoan(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) {
|
||||||
return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, specifiedDueDate);
|
return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, dueDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LoanCharge() {
|
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,
|
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.loan = loan;
|
||||||
this.charge = chargeDefinition;
|
this.charge = chargeDefinition;
|
||||||
this.penaltyCharge = chargeDefinition.isPenalty();
|
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 (ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE)) {
|
||||||
|
|
||||||
if (specifiedDueDate == null) {
|
if (dueDate == null) {
|
||||||
final String defaultUserMessage = "Loan charge is missing specified due date";
|
final String defaultUserMessage = "Loan charge is missing due date.";
|
||||||
throw new LoanChargeWithoutMandatoryFieldException("loancharge", "specifiedDueDate", defaultUserMessage,
|
throw new LoanChargeWithoutMandatoryFieldException("loanCharge", "dueDate", defaultUserMessage,
|
||||||
chargeDefinition.getId(), chargeDefinition.getName());
|
chargeDefinition.getId(), chargeDefinition.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dueForCollectionAsOfDate = specifiedDueDate.toDate();
|
this.dueDate = dueDate.toDate();
|
||||||
} else {
|
} else {
|
||||||
this.dueForCollectionAsOfDate = null;
|
this.dueDate = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.chargeCalculation = chargeDefinition.getChargeCalculation();
|
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) {
|
public void update(final BigDecimal amount, final LocalDate specifiedDueDate, final BigDecimal loanPrincipal) {
|
||||||
if (specifiedDueDate != null) {
|
if (specifiedDueDate != null) {
|
||||||
this.dueForCollectionAsOfDate = specifiedDueDate.toDate();
|
this.dueDate = specifiedDueDate.toDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount != null) {
|
if (amount != null) {
|
||||||
@@ -279,31 +282,37 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
final String dateFormatAsInput = command.dateFormat();
|
final String dateFormatAsInput = command.dateFormat();
|
||||||
final String localeAsInput = command.locale();
|
final String localeAsInput = command.locale();
|
||||||
|
|
||||||
final String chargeTimeParamName = "chargeTime";
|
// final String chargeTimeParamName = "chargeTime";
|
||||||
if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, this.chargeTime)) {
|
// if (command.isChangeInIntegerParameterNamed(chargeTimeParamName,
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(chargeTimeParamName);
|
// this.chargeTime)) {
|
||||||
actualChanges.put(chargeTimeParamName, newValue);
|
// final Integer newValue =
|
||||||
actualChanges.put("locale", localeAsInput);
|
// command.integerValueOfParameterNamed(chargeTimeParamName);
|
||||||
this.chargeTime = ChargeTimeType.fromInt(newValue).getValue();
|
// 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";
|
final String specifiedDueDateParamName = "dueDate";
|
||||||
if (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, this.chargeCalculation)) {
|
if (command.isChangeInLocalDateParameterNamed(specifiedDueDateParamName, getDueLocalDate())) {
|
||||||
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 valueAsInput = command.stringValueOfParameterNamed(specifiedDueDateParamName);
|
final String valueAsInput = command.stringValueOfParameterNamed(specifiedDueDateParamName);
|
||||||
actualChanges.put(specifiedDueDateParamName, valueAsInput);
|
actualChanges.put(specifiedDueDateParamName, valueAsInput);
|
||||||
actualChanges.put("dateFormat", dateFormatAsInput);
|
actualChanges.put("dateFormat", dateFormatAsInput);
|
||||||
actualChanges.put("locale", localeAsInput);
|
actualChanges.put("locale", localeAsInput);
|
||||||
|
|
||||||
final LocalDate newValue = command.localDateValueOfParameterNamed(specifiedDueDateParamName);
|
final LocalDate newValue = command.localDateValueOfParameterNamed(specifiedDueDateParamName);
|
||||||
this.dueForCollectionAsOfDate = newValue.toDate();
|
this.dueDate = newValue.toDate();
|
||||||
}
|
}
|
||||||
|
|
||||||
final String amountParamName = "amount";
|
final String amountParamName = "amount";
|
||||||
@@ -355,13 +364,13 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
|
|
||||||
public LoanChargeCommand toCommand() {
|
public LoanChargeCommand toCommand() {
|
||||||
return new LoanChargeCommand(this.getId(), this.charge.getId(), this.amount, this.chargeTime, this.chargeCalculation,
|
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;
|
LocalDate specifiedDueDate = null;
|
||||||
if (this.dueForCollectionAsOfDate != null) {
|
if (this.dueDate != null) {
|
||||||
specifiedDueDate = new LocalDate(this.dueForCollectionAsOfDate);
|
specifiedDueDate = new LocalDate(this.dueDate);
|
||||||
}
|
}
|
||||||
return specifiedDueDate;
|
return specifiedDueDate;
|
||||||
}
|
}
|
||||||
@@ -418,7 +427,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDueForCollectionFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
public boolean isDueForCollectionFromAndUpToAndIncluding(final LocalDate fromNotInclusive, final LocalDate upToAndInclusive) {
|
||||||
final LocalDate specifiedDueDate = getDueForCollectionAsOfLocalDate();
|
final LocalDate specifiedDueDate = getDueLocalDate();
|
||||||
return occursOnDayFromAndUpToAndIncluding(fromNotInclusive, upToAndInclusive, specifiedDueDate);
|
return occursOnDayFromAndUpToAndIncluding(fromNotInclusive, upToAndInclusive, specifiedDueDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +517,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
.append(this.getId(), rhs.getId()) //
|
.append(this.getId(), rhs.getId()) //
|
||||||
.append(this.charge.getId(), rhs.charge.getId()) //
|
.append(this.charge.getId(), rhs.charge.getId()) //
|
||||||
.append(this.amount, rhs.amount) //
|
.append(this.amount, rhs.amount) //
|
||||||
.append(this.getDueForCollectionAsOfLocalDate(), rhs.getDueForCollectionAsOfLocalDate()) //
|
.append(this.getDueLocalDate(), rhs.getDueLocalDate()) //
|
||||||
.isEquals();
|
.isEquals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,7 +526,7 @@ public class LoanCharge extends AbstractPersistable<Long> {
|
|||||||
return new HashCodeBuilder(3, 5) //
|
return new HashCodeBuilder(3, 5) //
|
||||||
.append(this.getId()) //
|
.append(this.getId()) //
|
||||||
.append(this.charge.getId()) //
|
.append(this.charge.getId()) //
|
||||||
.append(this.amount).append(this.getDueForCollectionAsOfLocalDate()) //
|
.append(this.amount).append(this.getDueLocalDate()) //
|
||||||
.toHashCode();
|
.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);
|
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.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||||
import org.mifosplatform.portfolio.charge.domain.ChargeCalculationType;
|
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.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.charge.exception.LoanChargeNotFoundException;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.LoanChargeRepository;
|
import org.mifosplatform.portfolio.loanaccount.domain.LoanChargeRepository;
|
||||||
@@ -32,11 +30,11 @@ import com.google.gson.JsonObject;
|
|||||||
public class LoanChargeAssembler {
|
public class LoanChargeAssembler {
|
||||||
|
|
||||||
private final FromJsonHelper fromApiJsonHelper;
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
private final ChargeRepository chargeRepository;
|
private final ChargeRepositoryWrapper chargeRepository;
|
||||||
private final LoanChargeRepository loanChargeRepository;
|
private final LoanChargeRepository loanChargeRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public LoanChargeAssembler(final FromJsonHelper fromApiJsonHelper, final ChargeRepository chargeRepository,
|
public LoanChargeAssembler(final FromJsonHelper fromApiJsonHelper, final ChargeRepositoryWrapper chargeRepository,
|
||||||
final LoanChargeRepository loanChargeRepository) {
|
final LoanChargeRepository loanChargeRepository) {
|
||||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
this.chargeRepository = chargeRepository;
|
this.chargeRepository = chargeRepository;
|
||||||
@@ -69,10 +67,7 @@ public class LoanChargeAssembler {
|
|||||||
dateFormat, locale);
|
dateFormat, locale);
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
final Charge chargeDefinition = this.chargeRepository.findOne(chargeId);
|
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeId);
|
||||||
if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(chargeId); }
|
|
||||||
|
|
||||||
if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(chargeId, chargeDefinition.getName()); }
|
|
||||||
ChargeTimeType chargeTime = null;
|
ChargeTimeType chargeTime = null;
|
||||||
if (chargeTimeType != null) {
|
if (chargeTimeType != null) {
|
||||||
ChargeTimeType.fromInt(chargeTimeType);
|
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.monetary.domain.ApplicationCurrencyRepository;
|
||||||
import org.mifosplatform.organisation.staff.domain.Staff;
|
import org.mifosplatform.organisation.staff.domain.Staff;
|
||||||
import org.mifosplatform.portfolio.charge.domain.Charge;
|
import org.mifosplatform.portfolio.charge.domain.Charge;
|
||||||
import org.mifosplatform.portfolio.charge.domain.ChargeRepository;
|
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||||
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.charge.exception.LoanChargeNotFoundException;
|
||||||
import org.mifosplatform.portfolio.client.domain.Note;
|
import org.mifosplatform.portfolio.client.domain.Note;
|
||||||
import org.mifosplatform.portfolio.client.domain.NoteRepository;
|
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.command.LoanUpdateCommand;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
|
||||||
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
|
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.LoanOfficerAssignmentException;
|
||||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
|
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
|
||||||
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
|
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.LoanEventApiJsonValidator;
|
||||||
import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
|
import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
|
||||||
import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException;
|
import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException;
|
||||||
@@ -58,13 +54,12 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
private final PlatformSecurityContext context;
|
private final PlatformSecurityContext context;
|
||||||
private final LoanEventApiJsonValidator loanEventApiJsonValidator;
|
private final LoanEventApiJsonValidator loanEventApiJsonValidator;
|
||||||
private final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer;
|
|
||||||
private final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer;
|
private final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer;
|
||||||
private final LoanRepository loanRepository;
|
private final LoanRepository loanRepository;
|
||||||
private final NoteRepository noteRepository;
|
private final NoteRepository noteRepository;
|
||||||
private final LoanTransactionRepository loanTransactionRepository;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
private final LoanAssembler loanAssembler;
|
private final LoanAssembler loanAssembler;
|
||||||
private final ChargeRepository chargeRepository;
|
private final ChargeRepositoryWrapper chargeRepository;
|
||||||
private final LoanChargeRepository loanChargeRepository;
|
private final LoanChargeRepository loanChargeRepository;
|
||||||
private final ApplicationCurrencyRepository applicationCurrencyRepository;
|
private final ApplicationCurrencyRepository applicationCurrencyRepository;
|
||||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||||
@@ -72,15 +67,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
@Autowired
|
@Autowired
|
||||||
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||||
final LoanEventApiJsonValidator loanEventApiJsonValidator,
|
final LoanEventApiJsonValidator loanEventApiJsonValidator,
|
||||||
final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer,
|
|
||||||
final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer, final LoanAssembler loanAssembler,
|
final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer, final LoanAssembler loanAssembler,
|
||||||
final LoanRepository loanRepository, final LoanTransactionRepository loanTransactionRepository,
|
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 ApplicationCurrencyRepository applicationCurrencyRepository,
|
||||||
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
|
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
|
||||||
this.loanChargeCommandFromApiJsonDeserializer = loanChargeCommandFromApiJsonDeserializer;
|
|
||||||
this.loanAssembler = loanAssembler;
|
this.loanAssembler = loanAssembler;
|
||||||
this.loanRepository = loanRepository;
|
this.loanRepository = loanRepository;
|
||||||
this.loanTransactionRepository = loanTransactionRepository;
|
this.loanTransactionRepository = loanTransactionRepository;
|
||||||
@@ -472,24 +466,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public CommandProcessingResult addLoanCharge(final Long loanId, final JsonCommand command) {
|
public CommandProcessingResult addLoanCharge(final Long loanId, final JsonCommand command) {
|
||||||
|
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
// FIXME - KW - update loan charge api validation
|
this.loanEventApiJsonValidator.validateAddLoanCharge(command.json());
|
||||||
final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
|
|
||||||
// loanChargeCommand.validateForCreate();
|
|
||||||
|
|
||||||
final Loan loan = retrieveLoanBy(loanId);
|
final Loan loan = retrieveLoanBy(loanId);
|
||||||
|
|
||||||
final Long chargeDefinitionId = command.longValueOfParameterNamed("chargeId");
|
final Long chargeDefinitionId = command.longValueOfParameterNamed("chargeId");
|
||||||
final Charge chargeDefinition = this.chargeRepository.findOne(chargeDefinitionId);
|
final Charge chargeDefinition = this.chargeRepository.findOneWithNotFoundDetection(chargeDefinitionId);
|
||||||
if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(chargeDefinitionId); }
|
|
||||||
if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(chargeDefinition.getId(), chargeDefinition.getName()); }
|
|
||||||
|
|
||||||
final LoanCharge loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command);
|
final LoanCharge loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command);
|
||||||
|
|
||||||
if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())) {
|
if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())) {
|
||||||
String errorMessage = "Charge and Loan must have the same currency.";
|
final String errorMessage = "Charge and Loan must have the same currency.";
|
||||||
throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage);
|
throw new InvalidCurrencyException("loanCharge", "attach.to.loan", errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loanChargeRepository.save(loanCharge);
|
this.loanChargeRepository.save(loanCharge);
|
||||||
@@ -513,8 +504,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
|
this.loanEventApiJsonValidator.validateUpdateOfLoanCharge(command.json());
|
||||||
loanChargeCommand.validateForUpdate();
|
|
||||||
|
|
||||||
final Loan loan = retrieveLoanBy(loanId);
|
final Loan loan = retrieveLoanBy(loanId);
|
||||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||||
@@ -540,9 +530,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
this.context.authenticatedUser();
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json());
|
|
||||||
loanChargeCommand.validateForUpdate();
|
|
||||||
|
|
||||||
final Loan loan = retrieveLoanBy(loanId);
|
final Loan loan = retrieveLoanBy(loanId);
|
||||||
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);
|
||||||
|
|
||||||
@@ -553,12 +540,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
this.loanTransactionRepository.save(waiveTransaction);
|
this.loanTransactionRepository.save(waiveTransaction);
|
||||||
this.loanRepository.save(loan);
|
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() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withCommandId(command.commandId()) //
|
.withCommandId(command.commandId()) //
|
||||||
.withEntityId(loanChargeId) //
|
.withEntityId(loanChargeId) //
|
||||||
|
|||||||
+51
-45
@@ -187,10 +187,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
if (interestCompoundingAllowed) {
|
if (interestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenureInMonths,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenureInMonths,
|
||||||
maturityInterestRate, interestCompoundedEvery, interestCompoundedFrequencyPeriodType);
|
maturityInterestRate, interestCompoundedEvery);
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||||
tenureInMonths, maturityInterestRate, interestCompoundedEvery, interestCompoundedFrequencyPeriodType);
|
tenureInMonths, maturityInterestRate, interestCompoundedEvery);
|
||||||
}
|
}
|
||||||
|
|
||||||
DepositAccountStatus from = null;
|
DepositAccountStatus from = null;
|
||||||
@@ -278,11 +278,12 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.externalId = this.getId() + "_" + this.externalId;
|
this.externalId = this.getId() + "_" + this.externalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> approve(final LocalDate actualCommencementDate, final DepositLifecycleStateMachine depositLifecycleStateMachine,
|
public Map<String, Object> approve(final LocalDate actualCommencementDate,
|
||||||
final JsonCommand command, final FixedTermDepositInterestCalculator calculator) {
|
final DepositLifecycleStateMachine depositLifecycleStateMachine, final JsonCommand command,
|
||||||
|
final FixedTermDepositInterestCalculator calculator) {
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(20);
|
|
||||||
final String localeAsInput = command.locale();
|
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(20);
|
||||||
|
final String localeAsInput = command.locale();
|
||||||
|
|
||||||
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_APPROVED,
|
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_APPROVED,
|
||||||
DepositAccountStatus.fromInt(this.depositStatus));
|
DepositAccountStatus.fromInt(this.depositStatus));
|
||||||
@@ -295,7 +296,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
actualChanges.put("locale", localeAsInput);
|
actualChanges.put("locale", localeAsInput);
|
||||||
this.tenureInMonths = newValue;
|
this.tenureInMonths = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String maturityInterestRateParamName = "maturityInterestRate";
|
final String maturityInterestRateParamName = "maturityInterestRate";
|
||||||
if (command.isChangeInBigDecimalParameterNamed(maturityInterestRateParamName, this.interestRate)) {
|
if (command.isChangeInBigDecimalParameterNamed(maturityInterestRateParamName, this.interestRate)) {
|
||||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maturityInterestRateParamName);
|
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maturityInterestRateParamName);
|
||||||
@@ -313,7 +314,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
this.depositAmount = newValue;
|
this.depositAmount = newValue;
|
||||||
}
|
}
|
||||||
this.product.validateDepositInRange(this.depositAmount);
|
this.product.validateDepositInRange(this.depositAmount);
|
||||||
|
|
||||||
final String interestCompoundedEveryParamName = "interestCompoundedEvery";
|
final String interestCompoundedEveryParamName = "interestCompoundedEvery";
|
||||||
if (command.isChangeInIntegerParameterNamed(interestCompoundedEveryParamName, this.interestCompoundedEvery)) {
|
if (command.isChangeInIntegerParameterNamed(interestCompoundedEveryParamName, this.interestCompoundedEvery)) {
|
||||||
final Integer newValue = command.integerValueOfParameterNamed(interestCompoundedEveryParamName);
|
final Integer newValue = command.integerValueOfParameterNamed(interestCompoundedEveryParamName);
|
||||||
@@ -337,15 +338,16 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
if (this.interestCompoundingAllowed) {
|
if (this.interestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths, this.interestRate,
|
futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths, this.interestRate,
|
||||||
this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
|
this.interestCompoundedEvery);
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = calculator.calculateInterestOnMaturityForSimpleInterest(getDeposit(), this.tenureInMonths,
|
futureValueOnMaturity = calculator.calculateInterestOnMaturityForSimpleInterest(getDeposit(), this.tenureInMonths,
|
||||||
this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
|
this.interestRate, this.interestCompoundedEvery);
|
||||||
}
|
}
|
||||||
this.interestAccrued = futureValueOnMaturity.minus(getDeposit()).getAmount();
|
this.interestAccrued = futureValueOnMaturity.minus(getDeposit()).getAmount();
|
||||||
this.total = futureValueOnMaturity.getAmount();
|
this.total = futureValueOnMaturity.getAmount();
|
||||||
|
|
||||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.deposit(getDeposit(), getActualCommencementDate(), null);
|
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.deposit(getDeposit(), getActualCommencementDate(),
|
||||||
|
null);
|
||||||
depositaccountTransaction.updateAccount(this);
|
depositaccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
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,
|
throw new InvalidDepositStateTransitionException("approval", "cannot.be.a.future.date", errorMessage,
|
||||||
getActualCommencementDate());
|
getActualCommencementDate());
|
||||||
}
|
}
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDate getActualCommencementDate() {
|
public LocalDate getActualCommencementDate() {
|
||||||
@@ -592,8 +594,11 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
preClosureInterestRate);
|
preClosureInterestRate);
|
||||||
this.interestAccrued = this.interestAccrued.add(accuredInterestAfterMaturityToTillDate.getAmount());
|
this.interestAccrued = this.interestAccrued.add(accuredInterestAfterMaturityToTillDate.getAmount());
|
||||||
this.availableInterest = this.availableInterest.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,
|
||||||
//DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate, getAccuredInterest());
|
Money.of(currency, this.availableInterest), getDeposit().getAmount().add(this.availableInterest));
|
||||||
|
// DepositAccountTransaction depositaccountTransaction =
|
||||||
|
// DepositAccountTransaction.withdraw(getDeposit(), eventDate,
|
||||||
|
// getAccuredInterest());
|
||||||
depositaccountTransaction.updateAccount(this);
|
depositaccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||||
|
|
||||||
@@ -651,8 +656,11 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
boolean statustest = isActive();
|
boolean statustest = isActive();
|
||||||
if (isActive()) {
|
if (isActive()) {
|
||||||
//DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest);
|
// DepositAccountTransaction depositAccountTransaction =
|
||||||
DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest,getDeposit().getAmount().add(this.availableInterest).subtract(interest.getAmount()));
|
// 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);
|
depositAccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositAccountTransaction);
|
this.depositaccountTransactions.add(depositAccountTransaction);
|
||||||
this.interstPaid = this.interstPaid.add(interest.getAmount());
|
this.interstPaid = this.interstPaid.add(interest.getAmount());
|
||||||
@@ -667,9 +675,13 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
DepositAccountStatus.fromInt(this.depositStatus));
|
DepositAccountStatus.fromInt(this.depositStatus));
|
||||||
this.depositStatus = statusEnumForClose.getValue();
|
this.depositStatus = statusEnumForClose.getValue();
|
||||||
|
|
||||||
//DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit()));
|
// DepositAccountTransaction depositaccountTransaction =
|
||||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit()),
|
// DepositAccountTransaction.withdraw(getDeposit(), new
|
||||||
getDeposit().plus(Money.of(getDeposit().getCurrency(), getTotal()).minus(getDeposit())).getAmount());
|
// 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);
|
depositaccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||||
|
|
||||||
@@ -687,10 +699,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
if (isInterestCompoundingAllowed) {
|
if (isInterestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenureInMonths,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenureInMonths,
|
||||||
maturityInterestRate, interestCompoundedEvery, compoundingInterestFrequency);
|
maturityInterestRate, interestCompoundedEvery);
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||||
tenureInMonths, maturityInterestRate, interestCompoundedEvery, compoundingInterestFrequency);
|
tenureInMonths, maturityInterestRate, interestCompoundedEvery);
|
||||||
}
|
}
|
||||||
|
|
||||||
setExternalId(externalId);
|
setExternalId(externalId);
|
||||||
@@ -747,18 +759,17 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
if (lastInterestPostedDate.isBefore(getMaturityDate())) {
|
if (lastInterestPostedDate.isBefore(getMaturityDate())) {
|
||||||
if (nextInterestPostingDate.isAfter(getMaturityDate())) {
|
if (nextInterestPostingDate.isAfter(getMaturityDate())) {
|
||||||
Integer noofRemainMonthsAfterMaturity = Months.monthsBetween(getMaturityDate(), nextInterestPostingDate).getMonths();
|
Integer noofRemainMonthsAfterMaturity = Months.monthsBetween(getMaturityDate(), nextInterestPostingDate).getMonths();
|
||||||
Integer noOfMonthsBeforeMaturity = Months.monthsBetween(lastInterestPostedDate, getMaturityDate().plusDays(1)).getMonths();
|
Integer noOfMonthsBeforeMaturity = Months.monthsBetween(lastInterestPostedDate, getMaturityDate().plusDays(1))
|
||||||
Money futureValueOnMaturity = null;
|
.getMonths();
|
||||||
|
Money futureValueOnMaturity = Money.zero(this.currency);
|
||||||
if (noOfMonthsBeforeMaturity > 0) {
|
if (noOfMonthsBeforeMaturity > 0) {
|
||||||
|
|
||||||
if (this.interestCompoundingAllowed) {
|
if (this.interestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||||
noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery,
|
noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(
|
||||||
deposit, noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery,
|
deposit, noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
}
|
}
|
||||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||||
this.availableInterest = this.availableInterest.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) {
|
if (this.interestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||||
noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery,
|
noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(
|
||||||
deposit, noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery,
|
deposit, noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
}
|
}
|
||||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||||
this.availableInterest = this.availableInterest.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
|
// 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,
|
||||||
//DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate, futureValueOnMaturity.minus(deposit));
|
nextInterestPostingDate, futureValueOnMaturity.minus(deposit), deposit.getAmount().add(this.availableInterest));
|
||||||
|
|
||||||
depositaccountTransaction.updateAccount(this);
|
depositaccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||||
@@ -793,12 +802,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
Money futureValueOnMaturity = null;
|
Money futureValueOnMaturity = null;
|
||||||
if (this.interestCompoundingAllowed) {
|
if (this.interestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||||
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery,
|
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||||
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery,
|
this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
}
|
}
|
||||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||||
this.availableInterest = this.availableInterest.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();
|
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
|
||||||
|
|
||||||
// add transaction entry for each interest posting
|
// add transaction entry for each interest posting
|
||||||
// DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate, futureValueOnMaturity.minus(deposit));
|
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null,
|
||||||
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,futureValueOnMaturity.minus(deposit),deposit.getAmount().add(this.availableInterest));
|
nextInterestPostingDate, futureValueOnMaturity.minus(deposit), deposit.getAmount().add(this.availableInterest));
|
||||||
depositaccountTransaction.updateAccount(this);
|
depositaccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||||
}
|
}
|
||||||
@@ -815,12 +822,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
Money futureValueOnMaturity = null;
|
Money futureValueOnMaturity = null;
|
||||||
if (this.interestCompoundingAllowed) {
|
if (this.interestCompoundingAllowed) {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit,
|
||||||
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery,
|
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
} else {
|
} else {
|
||||||
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit,
|
||||||
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery,
|
this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery);
|
||||||
getInterestCompoundedFrequencyType());
|
|
||||||
}
|
}
|
||||||
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
|
||||||
this.availableInterest = this.availableInterest.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();
|
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
|
||||||
|
|
||||||
// add transaction entry for each interest posting
|
// 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);
|
depositaccountTransaction.updateAccount(this);
|
||||||
this.depositaccountTransactions.add(depositaccountTransaction);
|
this.depositaccountTransactions.add(depositaccountTransaction);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-14
@@ -10,25 +10,14 @@ import java.math.MathContext;
|
|||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||||
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class FixedTermDepositInterestCalculator {
|
public class FixedTermDepositInterestCalculator {
|
||||||
|
|
||||||
// FIXME - HUGO - Are the unused field here needed?
|
|
||||||
public Money calculateInterestOnMaturityFor(final Money deposit, final Integer tenureInMonths, final BigDecimal maturityInterestRate,
|
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);
|
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||||
Integer monthsInYear = 12;
|
Integer monthsInYear = 12;
|
||||||
|
|
||||||
@@ -72,8 +61,8 @@ public class FixedTermDepositInterestCalculator {
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money calculateInterestOnMaturityForSimpleInterest(final Money deposit, final Integer tenureInMonths, final BigDecimal maturityInterestRate,
|
public Money calculateInterestOnMaturityForSimpleInterest(final Money deposit, final Integer tenureInMonths,
|
||||||
final Integer interestCompoundedEvery, final PeriodFrequencyType interestCompoundedFrequencyPeriodType) {
|
final BigDecimal maturityInterestRate, final Integer interestCompoundedEvery) {
|
||||||
|
|
||||||
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
|
||||||
Integer monthsInYear = 12;
|
Integer monthsInYear = 12;
|
||||||
|
|||||||
Reference in New Issue
Block a user