* More refactoring to facilitate unit testing.
* Added coverage for core part of interest calculation.
diff --git a/service/src/main/java/io/mifos/individuallending/IndividualLendingPatternFactory.java b/service/src/main/java/io/mifos/individuallending/IndividualLendingPatternFactory.java
index 31bbc67..16ddbe7 100644
--- a/service/src/main/java/io/mifos/individuallending/IndividualLendingPatternFactory.java
+++ b/service/src/main/java/io/mifos/individuallending/IndividualLendingPatternFactory.java
@@ -28,11 +28,13 @@
import io.mifos.individuallending.internal.repository.CaseParametersEntity;
import io.mifos.individuallending.internal.repository.CaseParametersRepository;
import io.mifos.individuallending.internal.repository.CreditWorthinessFactorType;
+import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.individuallending.internal.service.costcomponent.*;
import io.mifos.individuallending.internal.service.DataContextOfAction;
import io.mifos.individuallending.internal.service.DataContextService;
import io.mifos.portfolio.api.v1.domain.*;
import io.mifos.portfolio.service.ServiceConstants;
+import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import io.mifos.products.spi.PatternFactory;
import io.mifos.products.spi.ProductCommandDispatcher;
import org.springframework.beans.factory.annotation.Autowired;
@@ -126,6 +128,7 @@
private final MarkLatePaymentBuilderService markLatePaymentBuilderService;
private final WriteOffPaymentBuilderService writeOffPaymentBuilderService;
private final RecoverPaymentBuilderService recoverPaymentBuilderService;
+ private final AccountingAdapter accountingAdapter;
private final CustomerManager customerManager;
private final IndividualLendingCommandDispatcher individualLendingCommandDispatcher;
private final Gson gson;
@@ -144,7 +147,7 @@
final MarkLatePaymentBuilderService markLatePaymentBuilderService,
final WriteOffPaymentBuilderService writeOffPaymentBuilderService,
final RecoverPaymentBuilderService recoverPaymentBuilderService,
- final CustomerManager customerManager,
+ AccountingAdapter accountingAdapter, final CustomerManager customerManager,
final IndividualLendingCommandDispatcher individualLendingCommandDispatcher,
@Qualifier(ServiceConstants.GSON_NAME) final Gson gson)
{
@@ -160,6 +163,7 @@
this.markLatePaymentBuilderService = markLatePaymentBuilderService;
this.writeOffPaymentBuilderService = writeOffPaymentBuilderService;
this.recoverPaymentBuilderService = recoverPaymentBuilderService;
+ this.accountingAdapter = accountingAdapter;
this.customerManager = customerManager;
this.individualLendingCommandDispatcher = individualLendingCommandDispatcher;
@@ -466,10 +470,17 @@
throw ServiceException.internalError("Invalid action: ''{0}''.", action.name());
}
+ final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
+ = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
final PaymentBuilder paymentBuilder = paymentBuilderService.getPaymentBuilder(
dataContextOfAction,
forPaymentSize,
- forDate);
+ forDate,
+ runningBalances);
return paymentBuilder.buildPayment(action, forAccountDesignators);
}
diff --git a/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java b/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java
index f980983..f5110cb 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/command/handler/IndividualLoanCommandHandler.java
@@ -128,11 +128,14 @@
checkIfTasksAreOutstanding(dataContextOfAction, Action.OPEN);
- final PaymentBuilder paymentBuilder
- = openPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today());
-
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
- = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
+ final PaymentBuilder paymentBuilder
+ = openPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.OPEN, designatorToAccountIdentifierMapper);
@@ -165,11 +168,14 @@
checkIfTasksAreOutstanding(dataContextOfAction, Action.DENY);
- final PaymentBuilder paymentBuilder
- = denyPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today());
-
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
= new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
+ final PaymentBuilder paymentBuilder
+ = denyPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.DENY, designatorToAccountIdentifierMapper);
@@ -247,8 +253,12 @@
);
caseRepository.save(dataContextOfAction.getCustomerCaseEntity());
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
final PaymentBuilder paymentBuilder =
- approvePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today());
+ approvePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.APPROVE, designatorToAccountIdentifierMapper);
@@ -281,11 +291,15 @@
checkIfTasksAreOutstanding(dataContextOfAction, Action.DISBURSE);
final BigDecimal disbursalAmount = Optional.ofNullable(command.getCommand().getPaymentSize()).orElse(BigDecimal.ZERO);
- final PaymentBuilder paymentBuilder =
- disbursePaymentBuilderService.getPaymentBuilder(dataContextOfAction, disbursalAmount, CostComponentService.today());
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
= new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
+ final PaymentBuilder paymentBuilder =
+ disbursePaymentBuilderService.getPaymentBuilder(dataContextOfAction, disbursalAmount, CostComponentService.today(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.DISBURSE, designatorToAccountIdentifierMapper);
@@ -337,11 +351,14 @@
throw ServiceException.internalError(
"End of term not set for active case ''{0}.{1}.''", productIdentifier, caseIdentifier);
- final PaymentBuilder paymentBuilder =
- applyInterestPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today());
-
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
= new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
+ final PaymentBuilder paymentBuilder =
+ applyInterestPaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.APPLY_INTEREST, designatorToAccountIdentifierMapper);
@@ -372,14 +389,18 @@
throw ServiceException.internalError(
"End of term not set for active case ''{0}.{1}.''", productIdentifier, caseIdentifier);
+
+ final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
+ = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
final PaymentBuilder paymentBuilder =
acceptPaymentBuilderService.getPaymentBuilder(
dataContextOfAction,
command.getCommand().getPaymentSize(),
- DateConverter.fromIsoString(command.getCommand().getCreatedOn()).toLocalDate());
-
- final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
- = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ DateConverter.fromIsoString(command.getCommand().getCreatedOn()).toLocalDate(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.ACCEPT_PAYMENT, designatorToAccountIdentifierMapper);
@@ -412,11 +433,15 @@
throw ServiceException.internalError(
"End of term not set for active case ''{0}.{1}.''", productIdentifier, caseIdentifier);
- final PaymentBuilder paymentBuilder =
- markLatePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, DateConverter.fromIsoString(command.getForTime()).toLocalDate());
-
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
= new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
+ final PaymentBuilder paymentBuilder =
+ markLatePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, DateConverter.fromIsoString(command.getForTime()).toLocalDate(),
+ runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.MARK_LATE, designatorToAccountIdentifierMapper);
@@ -464,11 +489,14 @@
checkIfTasksAreOutstanding(dataContextOfAction, Action.CLOSE);
- final PaymentBuilder paymentBuilder =
- closePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today());
-
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
= new DesignatorToAccountIdentifierMapper(dataContextOfAction);
+ final RealRunningBalances runningBalances = new RealRunningBalances(
+ accountingAdapter,
+ designatorToAccountIdentifierMapper);
+
+ final PaymentBuilder paymentBuilder =
+ closePaymentBuilderService.getPaymentBuilder(dataContextOfAction, BigDecimal.ZERO, CostComponentService.today(), runningBalances);
final List<ChargeInstance> charges = paymentBuilder.buildCharges(Action.CLOSE, designatorToAccountIdentifierMapper);
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderService.java
index ef5f34b..3846c37 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderService.java
@@ -19,14 +19,12 @@
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.individuallending.internal.repository.CaseParametersEntity;
import io.mifos.individuallending.internal.service.DataContextOfAction;
-import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.individuallending.internal.service.schedule.ScheduledAction;
import io.mifos.individuallending.internal.service.schedule.ScheduledActionHelpers;
import io.mifos.individuallending.internal.service.schedule.ScheduledCharge;
import io.mifos.individuallending.internal.service.schedule.ScheduledChargesService;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import io.mifos.portfolio.api.v1.domain.CostComponent;
-import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -43,31 +41,17 @@
@Service
public class AcceptPaymentBuilderService implements PaymentBuilderService {
private final ScheduledChargesService scheduledChargesService;
- private final AccountingAdapter accountingAdapter;
@Autowired
public AcceptPaymentBuilderService(
- final ScheduledChargesService scheduledChargesService,
- final AccountingAdapter accountingAdapter) {
+ final ScheduledChargesService scheduledChargesService) {
this.scheduledChargesService = scheduledChargesService;
- this.accountingAdapter = accountingAdapter;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final DataContextOfAction dataContextOfAction,
final BigDecimal requestedLoanPaymentSize,
- final LocalDate forDate)
- {
- final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
- = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
- final RealRunningBalances runningBalances = new RealRunningBalances(accountingAdapter, designatorToAccountIdentifierMapper);
-
- return getPaymentBuilderHelper(dataContextOfAction, requestedLoanPaymentSize, forDate, runningBalances);
- }
-
- PaymentBuilder getPaymentBuilderHelper(
- final DataContextOfAction dataContextOfAction,
- final BigDecimal requestedLoanPaymentSize,
final LocalDate forDate,
final RunningBalances runningBalances) {
final LocalDate startOfTerm = runningBalances.getStartOfTermOrThrow(dataContextOfAction);
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderService.java
index 7d0628b..7fef484 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderService.java
@@ -18,14 +18,12 @@
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.individuallending.internal.repository.CaseParametersEntity;
import io.mifos.individuallending.internal.service.DataContextOfAction;
-import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.individuallending.internal.service.schedule.Period;
import io.mifos.individuallending.internal.service.schedule.ScheduledAction;
import io.mifos.individuallending.internal.service.schedule.ScheduledCharge;
import io.mifos.individuallending.internal.service.schedule.ScheduledChargesService;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import io.mifos.portfolio.api.v1.domain.CostComponent;
-import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -42,25 +40,19 @@
@Service
public class ApplyInterestPaymentBuilderService implements PaymentBuilderService {
private final ScheduledChargesService scheduledChargesService;
- private final AccountingAdapter accountingAdapter;
@Autowired
- public ApplyInterestPaymentBuilderService(
- final ScheduledChargesService scheduledChargesService,
- final AccountingAdapter accountingAdapter) {
+ public ApplyInterestPaymentBuilderService(final ScheduledChargesService scheduledChargesService) {
this.scheduledChargesService = scheduledChargesService;
- this.accountingAdapter = accountingAdapter;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final DataContextOfAction dataContextOfAction,
final BigDecimal ignored,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
- final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
- = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
- final RunningBalances runningBalances = new RealRunningBalances(accountingAdapter, designatorToAccountIdentifierMapper);
-
final LocalDate startOfTerm = runningBalances.getStartOfTermOrThrow(dataContextOfAction);
final CaseParametersEntity caseParameters = dataContextOfAction.getCaseParametersEntity();
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApprovePaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApprovePaymentBuilderService.java
index 3f7566d..61649c7 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApprovePaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ApprovePaymentBuilderService.java
@@ -42,10 +42,12 @@
this.scheduledChargesService = scheduledChargesService;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final DataContextOfAction dataContextOfAction,
final BigDecimal ignored,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
//Charge the approval fee if applicable.
final CaseParametersEntity caseParameters = dataContextOfAction.getCaseParametersEntity();
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ClosePaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ClosePaymentBuilderService.java
index 4118d43..4c5bdfb 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ClosePaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/ClosePaymentBuilderService.java
@@ -20,14 +20,12 @@
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.individuallending.internal.repository.CaseParametersEntity;
import io.mifos.individuallending.internal.service.DataContextOfAction;
-import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.individuallending.internal.service.schedule.Period;
import io.mifos.individuallending.internal.service.schedule.ScheduledAction;
import io.mifos.individuallending.internal.service.schedule.ScheduledCharge;
import io.mifos.individuallending.internal.service.schedule.ScheduledChargesService;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import io.mifos.portfolio.api.v1.domain.CostComponent;
-import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -44,25 +42,20 @@
@Service
public class ClosePaymentBuilderService implements PaymentBuilderService {
private final ScheduledChargesService scheduledChargesService;
- private final AccountingAdapter accountingAdapter;
@Autowired
public ClosePaymentBuilderService(
- final ScheduledChargesService scheduledChargesService,
- final AccountingAdapter accountingAdapter) {
+ final ScheduledChargesService scheduledChargesService) {
this.scheduledChargesService = scheduledChargesService;
- this.accountingAdapter = accountingAdapter;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final DataContextOfAction dataContextOfAction,
final BigDecimal ignored,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
- final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
- = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
- final RealRunningBalances runningBalances = new RealRunningBalances(accountingAdapter, designatorToAccountIdentifierMapper);
-
if (runningBalances.getBalance(AccountDesignators.CUSTOMER_LOAN_GROUP).compareTo(BigDecimal.ZERO) != 0)
throw ServiceException.conflict("Cannot close loan until the balance is zero.");
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DenyPaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DenyPaymentBuilderService.java
index 1912617..99e90c0 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DenyPaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DenyPaymentBuilderService.java
@@ -42,10 +42,12 @@
this.scheduledChargesService = scheduledChargesService;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final DataContextOfAction dataContextOfAction,
final BigDecimal ignored,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
final CaseParametersEntity caseParameters = dataContextOfAction.getCaseParametersEntity();
final String productIdentifier = dataContextOfAction.getProductEntity().getIdentifier();
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DisbursePaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DisbursePaymentBuilderService.java
index 4320807..97a47eb 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DisbursePaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/DisbursePaymentBuilderService.java
@@ -58,15 +58,16 @@
this.accountingAdapter = accountingAdapter;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final @Nonnull DataContextOfAction dataContextOfAction,
final @Nullable BigDecimal requestedDisbursalSize,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
= new DesignatorToAccountIdentifierMapper(dataContextOfAction);
final String customerLoanPrincipalAccountIdentifier = designatorToAccountIdentifierMapper.mapOrThrow(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL);
- final RealRunningBalances runningBalances = new RealRunningBalances(accountingAdapter, designatorToAccountIdentifierMapper);
final BigDecimal currentBalance = runningBalances.getBalance(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL);
if (requestedDisbursalSize != null &&
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/MarkLatePaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/MarkLatePaymentBuilderService.java
index 63a43b5..5b77f93 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/MarkLatePaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/MarkLatePaymentBuilderService.java
@@ -18,13 +18,11 @@
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.individuallending.internal.repository.CaseParametersEntity;
import io.mifos.individuallending.internal.service.DataContextOfAction;
-import io.mifos.individuallending.internal.service.DesignatorToAccountIdentifierMapper;
import io.mifos.individuallending.internal.service.schedule.ScheduledAction;
import io.mifos.individuallending.internal.service.schedule.ScheduledCharge;
import io.mifos.individuallending.internal.service.schedule.ScheduledChargesService;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import io.mifos.portfolio.api.v1.domain.CostComponent;
-import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -43,25 +41,19 @@
@Service
public class MarkLatePaymentBuilderService implements PaymentBuilderService {
private final ScheduledChargesService scheduledChargesService;
- private final AccountingAdapter accountingAdapter;
@Autowired
- public MarkLatePaymentBuilderService(
- final ScheduledChargesService scheduledChargesService,
- final AccountingAdapter accountingAdapter) {
+ public MarkLatePaymentBuilderService(final ScheduledChargesService scheduledChargesService) {
this.scheduledChargesService = scheduledChargesService;
- this.accountingAdapter = accountingAdapter;
}
+ @Override
public PaymentBuilder getPaymentBuilder(
final @Nonnull DataContextOfAction dataContextOfAction,
final @Nullable BigDecimal ignored,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
- final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper
- = new DesignatorToAccountIdentifierMapper(dataContextOfAction);
- final RunningBalances runningBalances = new RealRunningBalances(accountingAdapter, designatorToAccountIdentifierMapper);
-
final LocalDate startOfTerm = runningBalances.getStartOfTermOrThrow(dataContextOfAction);
final CaseParametersEntity caseParameters = dataContextOfAction.getCaseParametersEntity();
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/OpenPaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/OpenPaymentBuilderService.java
index a1e05c6..d4da18c 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/OpenPaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/OpenPaymentBuilderService.java
@@ -45,7 +45,8 @@
public PaymentBuilder getPaymentBuilder(
final DataContextOfAction dataContextOfAction,
final BigDecimal ignored,
- final LocalDate forDate)
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
{
final CaseParametersEntity caseParameters = dataContextOfAction.getCaseParametersEntity();
final String productIdentifier = dataContextOfAction.getProductEntity().getIdentifier();
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderService.java
index e3e44df..b5b1c61 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderService.java
@@ -5,7 +5,6 @@
import io.mifos.portfolio.api.v1.domain.CostComponent;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.time.LocalDate;
@@ -23,6 +22,7 @@
PaymentBuilder getPaymentBuilder(
final @Nonnull DataContextOfAction dataContextOfAction,
- final @Nullable BigDecimal requestedDisbursalSize,
- final LocalDate forDate);
+ final BigDecimal forPaymentSize,
+ final LocalDate forDate,
+ final @Nonnull RunningBalances runningBalances);
}
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java
index a026f4a..05dc2f6 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RealRunningBalances.java
@@ -39,7 +39,7 @@
private final AccountingAdapter accountingAdapter;
private final ExpiringMap<String, BigDecimal> realAccountBalanceCache;
- RealRunningBalances(
+ public RealRunningBalances(
final AccountingAdapter accountingAdapter,
final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper) {
this.accountingAdapter = accountingAdapter;
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RecoverPaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RecoverPaymentBuilderService.java
index e3b01a6..2ca9814 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RecoverPaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RecoverPaymentBuilderService.java
@@ -29,7 +29,11 @@
@Service
public class RecoverPaymentBuilderService implements PaymentBuilderService {
@Override
- public PaymentBuilder getPaymentBuilder(@Nonnull DataContextOfAction dataContextOfAction, @Nullable BigDecimal requestedDisbursalSize, LocalDate forDate) {
+ public PaymentBuilder getPaymentBuilder(
+ final @Nonnull DataContextOfAction dataContextOfAction,
+ final @Nullable BigDecimal requestedDisbursalSize,
+ final LocalDate forDate,
+ final RunningBalances runningBalances) {
return null;
}
}
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/WriteOffPaymentBuilderService.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/WriteOffPaymentBuilderService.java
index 8d392b9..41faf76 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/WriteOffPaymentBuilderService.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/WriteOffPaymentBuilderService.java
@@ -29,7 +29,12 @@
@Service
public class WriteOffPaymentBuilderService implements PaymentBuilderService {
@Override
- public PaymentBuilder getPaymentBuilder(@Nonnull DataContextOfAction dataContextOfAction, @Nullable BigDecimal requestedDisbursalSize, LocalDate forDate) {
+ public PaymentBuilder getPaymentBuilder(
+ final @Nonnull DataContextOfAction dataContextOfAction,
+ final @Nullable BigDecimal ignored,
+ final LocalDate forDate,
+ final RunningBalances runningBalances)
+ {
return null;
}
}
diff --git a/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderServiceTest.java b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderServiceTest.java
index a787475..b3f1424 100644
--- a/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderServiceTest.java
+++ b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/AcceptPaymentBuilderServiceTest.java
@@ -3,25 +3,11 @@
import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
import io.mifos.individuallending.api.v1.domain.product.ChargeIdentifiers;
import io.mifos.individuallending.api.v1.domain.workflow.Action;
-import io.mifos.individuallending.internal.repository.CaseParametersEntity;
-import io.mifos.individuallending.internal.service.DataContextOfAction;
-import io.mifos.individuallending.internal.service.DefaultChargeDefinitionsMocker;
-import io.mifos.individuallending.internal.service.schedule.ScheduledChargesService;
import io.mifos.portfolio.api.v1.domain.CostComponent;
import io.mifos.portfolio.api.v1.domain.Payment;
-import io.mifos.portfolio.service.internal.repository.BalanceSegmentRepository;
-import io.mifos.portfolio.service.internal.repository.CaseEntity;
-import io.mifos.portfolio.service.internal.repository.ProductEntity;
-import io.mifos.portfolio.service.internal.service.ChargeDefinitionService;
-import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import org.junit.Assert;
import org.junit.Test;
-import org.mockito.Mockito;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
@@ -29,51 +15,20 @@
public class AcceptPaymentBuilderServiceTest {
@Test
public void getPaymentBuilder() throws Exception {
- final LocalDate startOfTerm = LocalDate.of(2015, 1, 15);
- final LocalDateTime endOfTerm = LocalDate.of(2015, 8, 15).atStartOfDay();
- final LocalDate forDate = startOfTerm.plusMonths(1);
- final BigDecimal paymentSize = BigDecimal.valueOf(100_00, 2);
- final BigDecimal balance = BigDecimal.valueOf(2000_00, 2);
- final BigDecimal balanceRangeMaximum = BigDecimal.valueOf(1000_00, 2);
- final BigDecimal accruedInterest = BigDecimal.valueOf(10_00, 2);
+ final PaymentBuilderServiceTestCase testCase = new PaymentBuilderServiceTestCase("simple case");
+ testCase.runningBalances.adjustBalance(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, testCase.balance.negate());
+ testCase.runningBalances.adjustBalance(AccountDesignators.INTEREST_ACCRUAL, testCase.accruedInterest);
- final BalanceSegmentRepository balanceSegmentRepository = Mockito.mock(BalanceSegmentRepository.class);
- final ChargeDefinitionService chargeDefinitionService = DefaultChargeDefinitionsMocker.getChargeDefinitionService(Collections.emptyList());
- final ScheduledChargesService scheduledChargesService = new ScheduledChargesService(chargeDefinitionService, balanceSegmentRepository);
- final AccountingAdapter accountingAdapter = Mockito.mock(AccountingAdapter.class);
- final AcceptPaymentBuilderService testSubject = new AcceptPaymentBuilderService(
- scheduledChargesService,
- accountingAdapter);
- final SimulatedRunningBalances runningBalances = new SimulatedRunningBalances(startOfTerm);
- runningBalances.adjustBalance(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, balance.negate());
- runningBalances.adjustBalance(AccountDesignators.INTEREST_ACCRUAL, accruedInterest);
+ final PaymentBuilder paymentBuilder = PaymentBuilderServiceTestHarness.constructCallToPaymentBuilder(
+ AcceptPaymentBuilderService::new, testCase);
-
- final ProductEntity product = new ProductEntity();
- product.setIdentifier("blah");
- product.setMinorCurrencyUnitDigits(2);
- final CaseEntity customerCase = new CaseEntity();
- customerCase.setEndOfTerm(endOfTerm);
- final CaseParametersEntity caseParameters = new CaseParametersEntity();
- caseParameters.setPaymentSize(paymentSize);
- caseParameters.setBalanceRangeMaximum(balanceRangeMaximum);
- caseParameters.setPaymentCyclePeriod(1);
- caseParameters.setPaymentCycleTemporalUnit(ChronoUnit.MONTHS);
- caseParameters.setCreditWorthinessFactors(Collections.emptySet());
-
- final DataContextOfAction dataContextOfAction = new DataContextOfAction(product, customerCase, caseParameters, Collections.emptyList());
- final PaymentBuilder paymentBuilder = testSubject.getPaymentBuilderHelper(
- dataContextOfAction,
- paymentSize,
- forDate,
- runningBalances);
final Payment payment = paymentBuilder.buildPayment(Action.ACCEPT_PAYMENT, Collections.emptySet());
Assert.assertNotNull(payment);
final Map<String, CostComponent> mappedCostComponents = payment.getCostComponents().stream()
.collect(Collectors.toMap(CostComponent::getChargeIdentifier, x -> x));
- Assert.assertEquals(accruedInterest, mappedCostComponents.get(ChargeIdentifiers.INTEREST_ID).getAmount());
- Assert.assertEquals(accruedInterest, mappedCostComponents.get(ChargeIdentifiers.REPAY_INTEREST_ID).getAmount());
- Assert.assertEquals(paymentSize.subtract(accruedInterest), mappedCostComponents.get(ChargeIdentifiers.REPAY_PRINCIPAL_ID).getAmount());
+ Assert.assertEquals(testCase.accruedInterest, mappedCostComponents.get(ChargeIdentifiers.INTEREST_ID).getAmount());
+ Assert.assertEquals(testCase.accruedInterest, mappedCostComponents.get(ChargeIdentifiers.REPAY_INTEREST_ID).getAmount());
+ Assert.assertEquals(testCase.paymentSize.subtract(testCase.accruedInterest), mappedCostComponents.get(ChargeIdentifiers.REPAY_PRINCIPAL_ID).getAmount());
}
}
\ No newline at end of file
diff --git a/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderServiceTest.java b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderServiceTest.java
new file mode 100644
index 0000000..5b56481
--- /dev/null
+++ b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/ApplyInterestPaymentBuilderServiceTest.java
@@ -0,0 +1,32 @@
+package io.mifos.individuallending.internal.service.costcomponent;
+
+import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
+import io.mifos.individuallending.api.v1.domain.product.ChargeIdentifiers;
+import io.mifos.individuallending.api.v1.domain.workflow.Action;
+import io.mifos.portfolio.api.v1.domain.CostComponent;
+import io.mifos.portfolio.api.v1.domain.Payment;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class ApplyInterestPaymentBuilderServiceTest {
+ @Test
+ public void getPaymentBuilder() throws Exception {
+ final PaymentBuilderServiceTestCase testCase = new PaymentBuilderServiceTestCase("simple case");
+ testCase.runningBalances.adjustBalance(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, testCase.balance.negate());
+
+ final PaymentBuilder paymentBuilder = PaymentBuilderServiceTestHarness.constructCallToPaymentBuilder(
+ ApplyInterestPaymentBuilderService::new, testCase);
+
+ final Payment payment = paymentBuilder.buildPayment(Action.APPLY_INTEREST, Collections.emptySet());
+ Assert.assertNotNull(payment);
+ final Map<String, CostComponent> mappedCostComponents = payment.getCostComponents().stream()
+ .collect(Collectors.toMap(CostComponent::getChargeIdentifier, x -> x));
+
+ Assert.assertEquals(BigDecimal.valueOf(27, 2), mappedCostComponents.get(ChargeIdentifiers.INTEREST_ID).getAmount());
+ }
+}
diff --git a/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderServiceTestCase.java b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderServiceTestCase.java
new file mode 100644
index 0000000..acc5ded
--- /dev/null
+++ b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderServiceTestCase.java
@@ -0,0 +1,70 @@
+package io.mifos.individuallending.internal.service.costcomponent;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+class PaymentBuilderServiceTestCase {
+ private final String description;
+ private LocalDate startOfTerm = LocalDate.of(2015, 1, 15);
+ LocalDateTime endOfTerm = LocalDate.of(2015, 8, 15).atStartOfDay();
+ LocalDate forDate = startOfTerm.plusMonths(1);
+ BigDecimal paymentSize = BigDecimal.valueOf(100_00, 2);
+ BigDecimal balance = BigDecimal.valueOf(2000_00, 2);
+ BigDecimal balanceRangeMaximum = BigDecimal.valueOf(1000_00, 2);
+ BigDecimal interestRate = BigDecimal.valueOf(5_00, 2);
+ BigDecimal accruedInterest = BigDecimal.valueOf(10_00, 2);
+ SimulatedRunningBalances runningBalances;
+
+ PaymentBuilderServiceTestCase(final String description) {
+ this.description = description;
+ runningBalances = new SimulatedRunningBalances(startOfTerm);
+ }
+
+ PaymentBuilderServiceTestCase endOfTerm(LocalDateTime endOfTerm) {
+ this.endOfTerm = endOfTerm;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase forDate(LocalDate forDate) {
+ this.forDate = forDate;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase paymentSize(BigDecimal paymentSize) {
+ this.paymentSize = paymentSize;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase balance(BigDecimal balance) {
+ this.balance = balance;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase balanceRangeMaximum(BigDecimal balanceRangeMaximum) {
+ this.balanceRangeMaximum = balanceRangeMaximum;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase interestRate(BigDecimal interestRate) {
+ this.interestRate = interestRate;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase accruedInterest(BigDecimal accruedInterest) {
+ this.accruedInterest = accruedInterest;
+ return this;
+ }
+
+ PaymentBuilderServiceTestCase runningBalances(SimulatedRunningBalances newVal) {
+ this.runningBalances = newVal;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "PaymentBuilderServiceTestCase{" +
+ "description='" + description + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderServiceTestHarness.java b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderServiceTestHarness.java
new file mode 100644
index 0000000..c26126e
--- /dev/null
+++ b/service/src/test/java/io/mifos/individuallending/internal/service/costcomponent/PaymentBuilderServiceTestHarness.java
@@ -0,0 +1,50 @@
+package io.mifos.individuallending.internal.service.costcomponent;
+
+import io.mifos.individuallending.internal.repository.CaseParametersEntity;
+import io.mifos.individuallending.internal.service.DataContextOfAction;
+import io.mifos.individuallending.internal.service.DefaultChargeDefinitionsMocker;
+import io.mifos.individuallending.internal.service.schedule.ScheduledChargesService;
+import io.mifos.portfolio.service.internal.repository.BalanceSegmentRepository;
+import io.mifos.portfolio.service.internal.repository.CaseEntity;
+import io.mifos.portfolio.service.internal.repository.ProductEntity;
+import io.mifos.portfolio.service.internal.service.ChargeDefinitionService;
+import org.mockito.Mockito;
+
+import java.time.temporal.ChronoUnit;
+import java.util.Collections;
+import java.util.function.Function;
+
+class PaymentBuilderServiceTestHarness {
+ static PaymentBuilder constructCallToPaymentBuilder (
+ final Function<ScheduledChargesService, PaymentBuilderService> serviceFactory,
+ final PaymentBuilderServiceTestCase testCase) {
+ final BalanceSegmentRepository balanceSegmentRepository = Mockito.mock(BalanceSegmentRepository.class);
+ final ChargeDefinitionService chargeDefinitionService = DefaultChargeDefinitionsMocker.getChargeDefinitionService(Collections.emptyList());
+ final ScheduledChargesService scheduledChargesService = new ScheduledChargesService(chargeDefinitionService, balanceSegmentRepository);
+ final PaymentBuilderService testSubject = serviceFactory.apply(scheduledChargesService);
+
+ final ProductEntity product = new ProductEntity();
+ product.setIdentifier("blah");
+ product.setMinorCurrencyUnitDigits(2);
+ final CaseEntity customerCase = new CaseEntity();
+ customerCase.setEndOfTerm(testCase.endOfTerm);
+ customerCase.setInterest(testCase.interestRate);
+ final CaseParametersEntity caseParameters = new CaseParametersEntity();
+ caseParameters.setPaymentSize(testCase.paymentSize);
+ caseParameters.setBalanceRangeMaximum(testCase.balanceRangeMaximum);
+ caseParameters.setPaymentCyclePeriod(1);
+ caseParameters.setPaymentCycleTemporalUnit(ChronoUnit.MONTHS);
+ caseParameters.setCreditWorthinessFactors(Collections.emptySet());
+
+ final DataContextOfAction dataContextOfAction = new DataContextOfAction(
+ product,
+ customerCase,
+ caseParameters,
+ Collections.emptyList());
+ return testSubject.getPaymentBuilder(
+ dataContextOfAction,
+ testCase.paymentSize,
+ testCase.forDate,
+ testCase.runningBalances);
+ }
+}
\ No newline at end of file