Merge pull request #24 from myrlen/develop
Loan repayment should not be restricted to current teller balance.
diff --git a/api/src/test/java/io/mifos/portfolio/api/v1/domain/PaymentCycleTest.java b/api/src/test/java/io/mifos/portfolio/api/v1/domain/PaymentCycleTest.java
index 499fb53..1a466f6 100644
--- a/api/src/test/java/io/mifos/portfolio/api/v1/domain/PaymentCycleTest.java
+++ b/api/src/test/java/io/mifos/portfolio/api/v1/domain/PaymentCycleTest.java
@@ -54,7 +54,7 @@
.adjustment(x -> x.setAlignmentDay(null))
.valid(true));
ret.add(new ValidationTestCase<PaymentCycle>("invalidAlignmentWeek")
- .adjustment(x -> x.setAlignmentWeek(3))
+ .adjustment(x -> x.setAlignmentWeek(5))
.valid(false));
ret.add(new ValidationTestCase<PaymentCycle>("nullTemporalUnit")
.adjustment(x -> x.setTemporalUnit(null))
diff --git a/component-test/src/main/java/io/mifos/portfolio/AbstractPortfolioTest.java b/component-test/src/main/java/io/mifos/portfolio/AbstractPortfolioTest.java
index 5337030..8fb45cd 100644
--- a/component-test/src/main/java/io/mifos/portfolio/AbstractPortfolioTest.java
+++ b/component-test/src/main/java/io/mifos/portfolio/AbstractPortfolioTest.java
@@ -312,11 +312,11 @@
new ChargeDefinitionEvent(productIdentifier, feeId)));
}
- AccountAssignment assignEntryToTeller() {
+ List<AccountAssignment> assignEntry(final String accountIdentifier) {
final AccountAssignment entryAccountAssignment = new AccountAssignment();
entryAccountAssignment.setDesignator(AccountDesignators.ENTRY);
- entryAccountAssignment.setAccountIdentifier(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
- return entryAccountAssignment;
+ entryAccountAssignment.setAccountIdentifier(accountIdentifier);
+ return Collections.singletonList(entryAccountAssignment);
}
AccountAssignment assignExpenseToGeneralExpense() {
diff --git a/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java b/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
index 3dd3e79..aeebdb1 100644
--- a/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
+++ b/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
@@ -62,6 +62,7 @@
static final String PROCESSING_FEE_INCOME_ACCOUNT_IDENTIFIER = "1312";
static final String DISBURSEMENT_FEE_INCOME_ACCOUNT_IDENTIFIER = "1313";
static final String CUSTOMERS_DEPOSIT_ACCOUNT = "7352";
+ static final String TELLER_ONE_ACCOUNT = "7354";
static final String LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER = "7810";
static final String CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER = "1103";
static final String LATE_FEE_INCOME_ACCOUNT_IDENTIFIER = "1311";
@@ -168,8 +169,8 @@
private static Ledger accruedIncomeLedger() {
final Ledger ret = new Ledger();
ret.setIdentifier(ACCRUED_INCOME_LEDGER_IDENTIFIER);
- ret.setParentLedgerIdentifier(ASSET_LEDGER_IDENTIFIER);
- ret.setType(AccountType.ASSET.name());
+ ret.setParentLedgerIdentifier(ASSET_LEDGER_IDENTIFIER); //TODO: This is inaccurate for a revenue account.
+ ret.setType(AccountType.REVENUE.name());
ret.setCreatedOn(DateConverter.toIsoString(universalCreationDate));
return ret;
@@ -180,6 +181,7 @@
ret.setIdentifier(LOAN_FUNDS_SOURCE_ACCOUNT_IDENTIFIER);
ret.setLedger(CASH_LEDGER_IDENTIFIER);
ret.setType(AccountType.ASSET.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -188,6 +190,7 @@
ret.setIdentifier(PROCESSING_FEE_INCOME_ACCOUNT_IDENTIFIER);
ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -196,6 +199,7 @@
ret.setIdentifier(LOAN_ORIGINATION_FEES_ACCOUNT_IDENTIFIER);
ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -204,14 +208,25 @@
ret.setIdentifier(DISBURSEMENT_FEE_INCOME_ACCOUNT_IDENTIFIER);
ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
private static Account tellerOneAccount() {
final Account ret = new Account();
- ret.setIdentifier(CUSTOMERS_DEPOSIT_ACCOUNT);
+ ret.setIdentifier(TELLER_ONE_ACCOUNT);
ret.setLedger(CASH_LEDGER_IDENTIFIER);
ret.setType(AccountType.ASSET.name());
+ ret.setBalance(0.0);
+ return ret;
+ }
+
+ private static Account customerDepositAccount() {
+ final Account ret = new Account();
+ ret.setIdentifier(CUSTOMERS_DEPOSIT_ACCOUNT);
+ ret.setLedger(CASH_LEDGER_IDENTIFIER); //TODO: The ledger here is wrong.
+ ret.setType(AccountType.LIABILITY.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -219,7 +234,8 @@
final Account ret = new Account();
ret.setIdentifier(LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER);
ret.setLedger(ACCRUED_INCOME_LEDGER_IDENTIFIER);
- ret.setType(AccountType.ASSET.name());
+ ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -228,6 +244,7 @@
ret.setIdentifier(CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER);
ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER);
ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -236,6 +253,7 @@
ret.setIdentifier(LATE_FEE_INCOME_ACCOUNT_IDENTIFIER);
ret.setLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -244,6 +262,7 @@
ret.setIdentifier(LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER);
ret.setLedger(ACCRUED_INCOME_LEDGER_IDENTIFIER);
ret.setType(AccountType.REVENUE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -252,6 +271,7 @@
ret.setIdentifier(PRODUCT_LOSS_ALLOWANCE_ACCOUNT_IDENTIFIER);
ret.setLedger(CUSTOMER_LOAN_LEDGER_IDENTIFIER);
ret.setType(AccountType.ASSET.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -259,6 +279,7 @@
final Account ret = new Account();
ret.setIdentifier(GENERAL_LOSS_ALLOWANCE_ACCOUNT_IDENTIFIER);
ret.setType(AccountType.EXPENSE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -266,6 +287,7 @@
final Account ret = new Account();
ret.setIdentifier(GENERAL_EXPENSE_ACCOUNT_IDENTIFIER);
ret.setType(AccountType.EXPENSE.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -273,6 +295,7 @@
final Account ret = new Account();
ret.setIdentifier(IMPORTED_CUSTOMER_LOAN_PRINCIPAL_ACCOUNT);
ret.setType(AccountType.ASSET.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -280,6 +303,7 @@
final Account ret = new Account();
ret.setIdentifier(IMPORTED_CUSTOMER_LOAN_INTEREST_ACCOUNT);
ret.setType(AccountType.ASSET.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -287,16 +311,20 @@
final Account ret = new Account();
ret.setIdentifier(IMPORTED_CUSTOMER_LOAN_FEES_ACCOUNT);
ret.setType(AccountType.ASSET.name());
+ ret.setBalance(0.0);
return ret;
}
private static AccountPage customerLoanAccountsPage() {
final Account customerLoanAccount1 = new Account();
customerLoanAccount1.setIdentifier("customerLoanAccount1");
+ customerLoanAccount1.setBalance(0.0);
final Account customerLoanAccount2 = new Account();
customerLoanAccount2.setIdentifier("customerLoanAccount2");
+ customerLoanAccount2.setBalance(0.0);
final Account customerLoanAccount3 = new Account();
customerLoanAccount3.setIdentifier("customerLoanAccount3");
+ customerLoanAccount3.setBalance(0.0);
final AccountPage ret = new AccountPage();
ret.setTotalElements(3L);
@@ -594,6 +622,7 @@
makeAccountResponsive(processingFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(disbursementFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(tellerOneAccount(), universalCreationDate, ledgerManagerMock);
+ makeAccountResponsive(customerDepositAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(loanInterestAccrualAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(consumerLoanInterestAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(lateFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
diff --git a/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java b/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java
index d551dae..d390d79 100644
--- a/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java
+++ b/component-test/src/main/java/io/mifos/portfolio/TestAccountingInteractionInLoanWorkflow.java
@@ -121,7 +121,12 @@
Assert.assertEquals(IMPORTED_NEXT_REPAYMENT_AMOUNT, nextRepaymentAmount);
else
Assert.assertEquals(totalDue, nextRepaymentAmount);
- final Payment payment = step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7), BigDecimal.ZERO);
+ final Payment payment = step7PaybackPartialAmount(
+ nextRepaymentAmount,
+ today.plusDays((week + 1) * 7),
+ BigDecimal.ZERO,
+ nextRepaymentAmount,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
final BigDecimal interestAccrual = payment.getBalanceAdjustments().remove(AccountDesignators.INTEREST_ACCRUAL); //Don't compare these with planned payment.
final BigDecimal customerLoanInterest = payment.getBalanceAdjustments().remove(AccountDesignators.CUSTOMER_LOAN_INTEREST);
Assert.assertEquals("week " + week, interestAccrual.negate(), customerLoanInterest);
@@ -143,10 +148,13 @@
step2CreateCase();
step3IImportCaseWhenAccountsExist(initialDisbursalDate);
+ final BigDecimal payment = expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued);
step7PaybackPartialAmount(
- expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued),
+ payment,
today,
- BigDecimal.ZERO);
+ BigDecimal.ZERO,
+ payment,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step8Close(today);
}
@@ -203,6 +211,10 @@
);
}
+ //TODO: once we've upgraded to junit 5 replace workflowTerminatingInEarlyLoanPayoff,
+ // and workflowDisbursalAndPayoffFromTellerAccount with one test annotated with
+ //@ParameterizedTest
+ //@ValueSource(strings = { AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT, AccountingFixture.TELLER_ONE_ACCOUNT })
@Test
public void workflowTerminatingInEarlyLoanPayoff() throws InterruptedException {
final LocalDateTime today = midnightToday();
@@ -214,12 +226,44 @@
step5Disburse(
BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
+ final BigDecimal payment = expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued);
step7PaybackPartialAmount(
- expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued),
+ payment,
today,
- BigDecimal.ZERO);
+ BigDecimal.ZERO,
+ payment,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
+ step8Close(today);
+ }
+
+ @Test
+ public void workflowDisbursalAndPayoffFromTellerAccount() throws InterruptedException {
+ final LocalDateTime today = midnightToday();
+
+ step1CreateProduct();
+ step2CreateCase();
+ step3OpenCase(today);
+ step4ApproveCase(today);
+ step5Disburse(
+ BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
+ today,
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
+ AccountingFixture.TELLER_ONE_ACCOUNT);
+ step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
+ final BigDecimal payment = expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued);
+ step7PaybackPartialAmount(
+ payment,
+ today,
+ BigDecimal.ZERO,
+ BigDecimal.ZERO, //payback should work even if there's *nothing* in the teller account at initiation.
+ AccountingFixture.TELLER_ONE_ACCOUNT);
step8Close(today);
}
@@ -234,16 +278,25 @@
step5Disburse(
BigDecimal.valueOf(500_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- ChargeIdentifiers.DISBURSEMENT_FEE_ID, BigDecimal.valueOf(10_00, MINOR_CURRENCY_UNIT_DIGITS));
+ ChargeIdentifiers.DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(10_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step5Disburse(
BigDecimal.valueOf(1_500_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(15_00, MINOR_CURRENCY_UNIT_DIGITS));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(15_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
+ final BigDecimal payment = expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued);
step7PaybackPartialAmount(
- expectedCurrentPrincipal.add(nonLateFees).add(interestAccrued),
+ payment,
today,
- BigDecimal.ZERO);
+ BigDecimal.ZERO,
+ payment,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step8Close(today);
}
@@ -258,14 +311,25 @@
step5Disburse(
BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step6CalculateInterestAccrualAndCheckForLateness(midnightToday(), BigDecimal.ZERO);
- final BigDecimal repayment1 = expectedCurrentPrincipal.divide(BigDecimal.valueOf(2), BigDecimal.ROUND_HALF_EVEN);
+ final BigDecimal repayment1 = expectedCurrentPrincipal.divide(BigDecimal.valueOf(2), BigDecimal.ROUND_HALF_EVEN)
+ .setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN);
step7PaybackPartialAmount(
- repayment1.setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN),
+ repayment1,
today,
- BigDecimal.ZERO);
- step7PaybackPartialAmount(expectedCurrentPrincipal, today, BigDecimal.ZERO);
+ BigDecimal.ZERO,
+ repayment1,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
+ step7PaybackPartialAmount(
+ expectedCurrentPrincipal,
+ today,
+ BigDecimal.ZERO,
+ expectedCurrentPrincipal,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
step8Close(today);
}
@@ -278,9 +342,13 @@
step3OpenCase(today);
step4ApproveCase(today);
try {
- step5Disburse(BigDecimal.valueOf(-2).setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN),
+ step5Disburse(
+ BigDecimal.valueOf(-2).setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.ZERO.setScale(MINOR_CURRENCY_UNIT_DIGITS,BigDecimal.ROUND_HALF_EVEN),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
Assert.fail("Expected an IllegalArgumentException.");
}
catch (IllegalArgumentException ignored) { }
@@ -304,7 +372,10 @@
step5Disburse(
BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
int week = 0;
while (expectedCurrentPrincipal.compareTo(BigDecimal.ZERO) > 0) {
@@ -312,7 +383,12 @@
step6CalculateInterestAndCheckForLatenessForWeek(today, week);
final BigDecimal interestAccruedBeforePayment = interestAccrued;
final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(today.plusDays((week+1)*7));
- final Payment payment = step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7), BigDecimal.ZERO);
+ final Payment payment = step7PaybackPartialAmount(
+ nextRepaymentAmount,
+ today.plusDays((week + 1) * 7),
+ BigDecimal.ZERO,
+ nextRepaymentAmount,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
final BigDecimal interestAccrual = payment.getBalanceAdjustments().remove(AccountDesignators.INTEREST_ACCRUAL); //Don't compare these with planned payment.
final BigDecimal customerLoanInterest = payment.getBalanceAdjustments().remove(AccountDesignators.CUSTOMER_LOAN_INTEREST);
Assert.assertEquals("week " + week, interestAccrual.negate(), customerLoanInterest);
@@ -344,7 +420,10 @@
step5Disburse(
BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
int week = 0;
final int weekOfLateRepayment = 3;
@@ -359,12 +438,22 @@
7,
lateFee);
final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(today.plusDays((week + 1) * 7 + 2));
- step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7 + 2), lateFee);
+ step7PaybackPartialAmount(
+ nextRepaymentAmount,
+ today.plusDays((week + 1) * 7 + 2),
+ lateFee,
+ nextRepaymentAmount,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
}
else {
step6CalculateInterestAndCheckForLatenessForWeek(today, week);
final BigDecimal nextRepaymentAmount = findNextRepaymentAmount(today.plusDays((week + 1) * 7));
- final Payment payment = step7PaybackPartialAmount(nextRepaymentAmount, today.plusDays((week + 1) * 7), BigDecimal.ZERO);
+ final Payment payment = step7PaybackPartialAmount(
+ nextRepaymentAmount,
+ today.plusDays((week + 1) * 7),
+ BigDecimal.ZERO,
+ nextRepaymentAmount,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
final BigDecimal interestAccrual = payment.getBalanceAdjustments().remove(AccountDesignators.INTEREST_ACCRUAL); //Don't compare these with planned payment.
final BigDecimal customerLoanInterest = payment.getBalanceAdjustments().remove(AccountDesignators.CUSTOMER_LOAN_INTEREST);
Assert.assertEquals(interestAccrual.negate(), customerLoanInterest);
@@ -388,7 +477,10 @@
step5Disburse(
BigDecimal.valueOf(2_000_00, MINOR_CURRENCY_UNIT_DIGITS),
today,
- UPPER_RANGE_DISBURSEMENT_FEE_ID, BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS));
+ UPPER_RANGE_DISBURSEMENT_FEE_ID,
+ BigDecimal.valueOf(20_00, MINOR_CURRENCY_UNIT_DIGITS),
+ BigDecimal.ZERO,
+ AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT);
final BigDecimal lateFee = BigDecimal.valueOf(15_36, MINOR_CURRENCY_UNIT_DIGITS); //??? TODO: check the late fee value.
step6CalculateInterestAndCheckForLatenessForRangeOfDays(
@@ -514,7 +606,7 @@
customerCase.getIdentifier(),
Action.OPEN,
forDateTime,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
IndividualLoanEventConstants.OPEN_INDIVIDUALLOAN_CASE,
Case.State.PENDING);
checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.APPROVE, Action.DENY);
@@ -689,7 +781,7 @@
customerCase.getIdentifier(),
Action.DENY,
forDateTime,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
IndividualLoanEventConstants.DENY_INDIVIDUALLOAN_CASE,
Case.State.CLOSED);
checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier());
@@ -716,7 +808,7 @@
customerCase.getIdentifier(),
Action.APPROVE,
forDateTime,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
IndividualLoanEventConstants.APPROVE_INDIVIDUALLOAN_CASE,
Case.State.APPROVED);
checkNextActionsCorrect(product.getIdentifier(), customerCase.getIdentifier(), Action.DISBURSE, Action.CLOSE);
@@ -745,9 +837,14 @@
final BigDecimal amount,
final LocalDateTime forDateTime,
final String whichDisbursementFee,
- final BigDecimal disbursementFeeAmount) throws InterruptedException {
+ final BigDecimal disbursementFeeAmount,
+ final BigDecimal balanceInEntryAccount,
+ final String entryAccountIdentifier) throws InterruptedException {
logger.info("step5Disburse '{}'", amount);
final BigDecimal provisionForLosses = amount.multiply(BigDecimal.valueOf(0.01)).setScale(MINOR_CURRENCY_UNIT_DIGITS, BigDecimal.ROUND_HALF_EVEN);
+
+ AccountingFixture.mockBalance(entryAccountIdentifier, balanceInEntryAccount);
+
checkCostComponentForActionCorrect(
product.getIdentifier(),
customerCase.getIdentifier(),
@@ -765,7 +862,7 @@
customerCase.getIdentifier(),
Action.DISBURSE,
forDateTime,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(entryAccountIdentifier),
amount,
IndividualLoanEventConstants.DISBURSE_INDIVIDUALLOAN_CASE,
Case.State.ACTIVE);
@@ -778,7 +875,7 @@
debtors.add(new Debtor(AccountingFixture.GENERAL_LOSS_ALLOWANCE_ACCOUNT_IDENTIFIER, provisionForLosses.toPlainString()));
final Set<Creditor> creditors = new HashSet<>();
- creditors.add(new Creditor(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT, amount.toString()));
+ creditors.add(new Creditor(entryAccountIdentifier, amount.toString()));
creditors.add(new Creditor(AccountingFixture.PROCESSING_FEE_INCOME_ACCOUNT_IDENTIFIER, PROCESSING_FEE_AMOUNT.toPlainString()));
creditors.add(new Creditor(AccountingFixture.DISBURSEMENT_FEE_INCOME_ACCOUNT_IDENTIFIER, disbursementFeeAmount.toPlainString()));
creditors.add(new Creditor(AccountingFixture.LOAN_ORIGINATION_FEES_ACCOUNT_IDENTIFIER, LOAN_ORIGINATION_FEE_AMOUNT.toPlainString()));
@@ -1092,11 +1189,13 @@
private Payment step7PaybackPartialAmount(
final BigDecimal amount,
final LocalDateTime forDateTime,
- final BigDecimal lateFee) throws InterruptedException {
+ final BigDecimal lateFee,
+ final BigDecimal balanceInEntryAccount,
+ final String entryAccountIdentifier) throws InterruptedException {
logger.info("step7PaybackPartialAmount '{}' '{}'", amount, forDateTime);
final BigDecimal principal = amount.subtract(interestAccrued).subtract(lateFee.add(nonLateFees));
- AccountingFixture.mockBalance(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT, amount);
+ AccountingFixture.mockBalance(entryAccountIdentifier, balanceInEntryAccount);
final Payment payment = checkCostComponentForActionCorrect(
product.getIdentifier(),
@@ -1116,7 +1215,7 @@
customerCase.getIdentifier(),
Action.ACCEPT_PAYMENT,
forDateTime,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(entryAccountIdentifier),
amount,
IndividualLoanEventConstants.ACCEPT_PAYMENT_INDIVIDUALLOAN_CASE,
Case.State.ACTIVE); //Close has to be done explicitly.
@@ -1124,18 +1223,18 @@
Action.APPLY_INTEREST, Action.MARK_LATE, Action.ACCEPT_PAYMENT, Action.DISBURSE, Action.MARK_IN_ARREARS, Action.WRITE_OFF, Action.CLOSE);
final Set<Debtor> debtors = new HashSet<>();
- BigDecimal tellerOneDebit = principal;
+ BigDecimal customerDepositAccountDebit = principal;
if (interestAccrued.compareTo(BigDecimal.ZERO) != 0) {
- tellerOneDebit = tellerOneDebit.add(interestAccrued);
+ customerDepositAccountDebit = customerDepositAccountDebit.add(interestAccrued);
debtors.add(new Debtor(AccountingFixture.LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER, interestAccrued.toPlainString()));
}
if (lateFee.add(nonLateFees).compareTo(BigDecimal.ZERO) != 0) {
- tellerOneDebit = tellerOneDebit.add(lateFee.add(nonLateFees));
+ customerDepositAccountDebit = customerDepositAccountDebit.add(lateFee.add(nonLateFees));
}
if (lateFee.compareTo(BigDecimal.ZERO) != 0) {
debtors.add(new Debtor(AccountingFixture.LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER, lateFee.toPlainString()));
}
- debtors.add(new Debtor(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT, tellerOneDebit.toPlainString()));
+ debtors.add(new Debtor(entryAccountIdentifier, customerDepositAccountDebit.toPlainString()));
final Set<Creditor> creditors = new HashSet<>();
creditors.add(new Creditor(customerLoanPrincipalIdentifier, principal.toPlainString()));
@@ -1180,7 +1279,7 @@
customerCase.getIdentifier(),
Action.CLOSE,
forDateTime,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
IndividualLoanEventConstants.CLOSE_INDIVIDUALLOAN_CASE,
Case.State.CLOSED); //Close has to be done explicitly.
diff --git a/component-test/src/main/java/io/mifos/portfolio/TestCases.java b/component-test/src/main/java/io/mifos/portfolio/TestCases.java
index 63f8b0b..79f5d70 100644
--- a/component-test/src/main/java/io/mifos/portfolio/TestCases.java
+++ b/component-test/src/main/java/io/mifos/portfolio/TestCases.java
@@ -68,7 +68,7 @@
final Case caseInstance = Fixture.getTestCase(product.getIdentifier());
final CaseParameters caseParameters = Fixture.getTestCaseParameters();
- caseParameters.getPaymentCycle().setAlignmentWeek(4);
+ caseParameters.getPaymentCycle().setAlignmentWeek(5);
final Gson gson = new Gson();
caseInstance.setParameters(gson.toJson(caseParameters));
diff --git a/component-test/src/main/java/io/mifos/portfolio/TestCommands.java b/component-test/src/main/java/io/mifos/portfolio/TestCommands.java
index e6a2828..9f2856f 100644
--- a/component-test/src/main/java/io/mifos/portfolio/TestCommands.java
+++ b/component-test/src/main/java/io/mifos/portfolio/TestCommands.java
@@ -22,7 +22,6 @@
import java.time.Clock;
import java.time.LocalDateTime;
-import java.util.Collections;
import static io.mifos.individuallending.api.v1.events.IndividualLoanEventConstants.*;
@@ -43,7 +42,7 @@
product.getIdentifier(),
customerCase.getIdentifier(),
Action.APPROVE,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
APPROVE_INDIVIDUALLOAN_CASE,
Case.State.CREATED);
}
@@ -58,7 +57,7 @@
customerCase.getIdentifier(),
Action.OPEN,
LocalDateTime.now(Clock.systemUTC()),
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
OPEN_INDIVIDUALLOAN_CASE,
Case.State.PENDING);
@@ -66,7 +65,7 @@
product.getIdentifier(),
customerCase.getIdentifier(),
Action.DISBURSE,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
DISBURSE_INDIVIDUALLOAN_CASE,
Case.State.PENDING);
}
diff --git a/component-test/src/main/java/io/mifos/portfolio/TestTaskInstances.java b/component-test/src/main/java/io/mifos/portfolio/TestTaskInstances.java
index 5aa6e7a..f67f7be 100644
--- a/component-test/src/main/java/io/mifos/portfolio/TestTaskInstances.java
+++ b/component-test/src/main/java/io/mifos/portfolio/TestTaskInstances.java
@@ -35,7 +35,6 @@
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -194,7 +193,7 @@
product.getIdentifier(),
customerCase.getIdentifier(),
Action.OPEN,
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
IndividualLoanEventConstants.OPEN_INDIVIDUALLOAN_CASE,
Case.State.CREATED);
}
@@ -207,7 +206,7 @@
customerCase.getIdentifier(),
Action.OPEN,
LocalDateTime.now(Clock.systemUTC()),
- Collections.singletonList(assignEntryToTeller()),
+ assignEntry(AccountingFixture.CUSTOMERS_DEPOSIT_ACCOUNT),
IndividualLoanEventConstants.OPEN_INDIVIDUALLOAN_CASE,
Case.State.PENDING);
}
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java
index 046106a..b97c124 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/AvailableRunningBalancesWithLimits.java
@@ -39,6 +39,12 @@
upperLimits.put(designator, limit);
}
+
+ @Override
+ public BigDecimal getAccountSign(final String accountDesignator) {
+ return decoratedRunningBalances.getAccountSign(accountDesignator);
+ }
+
@Override
public BigDecimal getAvailableBalance(final String designator, final BigDecimal requestedAmount) {
final BigDecimal balance = getBalance(designator).orElse(requestedAmount);
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 a394f2c..5dbd64c 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
@@ -15,6 +15,8 @@
*/
package io.mifos.individuallending.internal.service.costcomponent;
+import io.mifos.accounting.api.v1.domain.Account;
+import io.mifos.accounting.api.v1.domain.AccountType;
import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
import io.mifos.individuallending.api.v1.domain.workflow.Action;
import io.mifos.individuallending.internal.service.DataContextOfAction;
@@ -37,7 +39,7 @@
private final AccountingAdapter accountingAdapter;
private final DesignatorToAccountIdentifierMapper designatorToAccountIdentifierMapper;
private final DataContextOfAction dataContextOfAction;
- private final ExpiringMap<String, Optional<BigDecimal>> realAccountBalanceCache;
+ private final ExpiringMap<String, Optional<Account>> accountCache;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private Optional<LocalDateTime> startOfTerm;
@@ -48,27 +50,58 @@
this.designatorToAccountIdentifierMapper =
new DesignatorToAccountIdentifierMapper(dataContextOfAction);
this.dataContextOfAction = dataContextOfAction;
- this.realAccountBalanceCache = ExpiringMap.builder()
- .maxSize(20)
+ this.accountCache = ExpiringMap.builder()
+ .maxSize(40)
.expirationPolicy(ExpirationPolicy.CREATED)
- .expiration(30,TimeUnit.SECONDS)
+ .expiration(60,TimeUnit.SECONDS)
.entryLoader((String accountDesignator) -> {
final Optional<String> accountIdentifier;
- if (accountDesignator.equals(AccountDesignators.ENTRY)) {
+ if (accountDesignator.equals(AccountDesignators.ENTRY) || accountDesignator.equals(AccountDesignators.EXPENSE)) {
accountIdentifier = designatorToAccountIdentifierMapper.map(accountDesignator);
}
else {
accountIdentifier = Optional.of(designatorToAccountIdentifierMapper.mapOrThrow(accountDesignator));
}
- return accountIdentifier.map(accountingAdapter::getCurrentAccountBalance);
+ return accountIdentifier.map(accountingAdapter::getAccount);
})
.build();
this.startOfTerm = Optional.empty();
}
@Override
+ public BigDecimal getAccountSign(final String accountDesignator) {
+ return accountCache.get(accountDesignator)
+ .map(Account::getType)
+ .map(AccountType::valueOf)
+ .flatMap(x -> {
+ switch (x)
+ {
+ case LIABILITY:
+ case REVENUE:
+ case EQUITY:
+ return Optional.of(POSITIVE);
+
+ default:
+ case ASSET:
+ case EXPENSE:
+ return Optional.of(NEGATIVE);
+ }
+ })
+ .orElseGet(() -> {
+ switch (accountDesignator) {
+ case AccountDesignators.EXPENSE:
+ return NEGATIVE;
+ case AccountDesignators.ENTRY:
+ return POSITIVE;
+ default:
+ return NEGATIVE;
+ }}
+ );
+ }
+
+ @Override
public Optional<BigDecimal> getAccountBalance(final String accountDesignator) {
- return realAccountBalanceCache.get(accountDesignator);
+ return accountCache.get(accountDesignator).map(Account::getBalance).map(BigDecimal::valueOf);
}
@Override
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java
index b18edaf..0f2706d 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/RunningBalances.java
@@ -25,35 +25,21 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Optional;
/**
* @author Myrle Krantz
*/
public interface RunningBalances {
- Map<String, BigDecimal> ACCOUNT_SIGNS = new HashMap<String, BigDecimal>() {{
- final BigDecimal negative = BigDecimal.valueOf(-1);
- final BigDecimal positive = BigDecimal.valueOf(1);
+ BigDecimal NEGATIVE = BigDecimal.valueOf(-1);
+ BigDecimal POSITIVE = BigDecimal.valueOf(1);
- this.put(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, negative);
- this.put(AccountDesignators.CUSTOMER_LOAN_FEES, negative);
- this.put(AccountDesignators.CUSTOMER_LOAN_INTEREST, negative);
- this.put(AccountDesignators.LOAN_FUNDS_SOURCE, negative);
- this.put(AccountDesignators.PROCESSING_FEE_INCOME, positive);
- this.put(AccountDesignators.ORIGINATION_FEE_INCOME, positive);
- this.put(AccountDesignators.DISBURSEMENT_FEE_INCOME, positive);
- this.put(AccountDesignators.INTEREST_INCOME, positive);
- this.put(AccountDesignators.INTEREST_ACCRUAL, positive);
- this.put(AccountDesignators.LATE_FEE_INCOME, positive);
- this.put(AccountDesignators.LATE_FEE_ACCRUAL, positive);
- this.put(AccountDesignators.PRODUCT_LOSS_ALLOWANCE, negative);
- this.put(AccountDesignators.GENERAL_LOSS_ALLOWANCE, negative);
- this.put(AccountDesignators.EXPENSE, negative);
- this.put(AccountDesignators.ENTRY, positive);
- //TODO: derive signs from IndividualLendingPatternFactory.individualLendingRequiredAccounts instead.
- }};
+ /**
+ * Most accounts assignments have a required type, but some (entry for example) can change from request to request.
+ *
+ * @return NEGATIVE or POSITIVE constant as defined above depending on the type of the underlying account.
+ */
+ BigDecimal getAccountSign(final String accountDesignator);
Optional<BigDecimal> getAccountBalance(final String accountDesignator);
@@ -62,6 +48,11 @@
Optional<LocalDateTime> getStartOfTerm();
+ default boolean isAccountNegative(final String accountDesignator) {
+ return getAccountSign(accountDesignator).signum() == -1;
+ }
+
+
default LocalDateTime getStartOfTermOrThrow(final DataContextOfAction dataContextOfAction) {
return this.getStartOfTerm()
.orElseThrow(() -> ServiceException.internalError(
@@ -108,7 +99,7 @@
}
default BigDecimal getMaxDebit(final String accountDesignator, final BigDecimal amount) {
- if (ACCOUNT_SIGNS.get(accountDesignator).signum() == -1)
+ if (isAccountNegative(accountDesignator))
return amount;
else
return amount.min(getAvailableBalance(accountDesignator, amount));
@@ -122,7 +113,7 @@
//expense account can achieve a "relative" negative balance, and
// both loss allowance accounts can achieve an "absolute" negative balance.
- if (ACCOUNT_SIGNS.get(accountDesignator).signum() != -1)
+ if (!isAccountNegative(accountDesignator))
return amount;
else
return amount.min(getAvailableBalance(accountDesignator, amount));
diff --git a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java
index 05505fa..f2a28ee 100644
--- a/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java
+++ b/service/src/main/java/io/mifos/individuallending/internal/service/costcomponent/SimulatedRunningBalances.java
@@ -16,6 +16,7 @@
package io.mifos.individuallending.internal.service.costcomponent;
+import io.mifos.individuallending.api.v1.domain.product.AccountDesignators;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
import java.math.BigDecimal;
@@ -29,6 +30,24 @@
* @author Myrle Krantz
*/
public class SimulatedRunningBalances implements RunningBalances {
+ private final static Map<String, BigDecimal> ACCOUNT_SIGNS = new HashMap<String, BigDecimal>() {{
+ this.put(AccountDesignators.CUSTOMER_LOAN_PRINCIPAL, NEGATIVE);
+ this.put(AccountDesignators.CUSTOMER_LOAN_FEES, NEGATIVE);
+ this.put(AccountDesignators.CUSTOMER_LOAN_INTEREST, NEGATIVE);
+ this.put(AccountDesignators.LOAN_FUNDS_SOURCE, NEGATIVE);
+ this.put(AccountDesignators.PROCESSING_FEE_INCOME, POSITIVE);
+ this.put(AccountDesignators.ORIGINATION_FEE_INCOME, POSITIVE);
+ this.put(AccountDesignators.DISBURSEMENT_FEE_INCOME, POSITIVE);
+ this.put(AccountDesignators.INTEREST_INCOME, POSITIVE);
+ this.put(AccountDesignators.INTEREST_ACCRUAL, POSITIVE);
+ this.put(AccountDesignators.LATE_FEE_INCOME, POSITIVE);
+ this.put(AccountDesignators.LATE_FEE_ACCRUAL, POSITIVE);
+ this.put(AccountDesignators.PRODUCT_LOSS_ALLOWANCE, NEGATIVE);
+ this.put(AccountDesignators.GENERAL_LOSS_ALLOWANCE, NEGATIVE);
+ this.put(AccountDesignators.EXPENSE, NEGATIVE);
+ this.put(AccountDesignators.ENTRY, POSITIVE);
+ //TODO: derive signs from IndividualLendingPatternFactory.individualLendingRequiredAccounts instead.
+ }};
final private Map<String, BigDecimal> balances = new HashMap<>();
private final LocalDateTime startOfTerm;
@@ -41,6 +60,11 @@
}
@Override
+ public BigDecimal getAccountSign(final String accountDesignator) {
+ return ACCOUNT_SIGNS.get(accountDesignator);
+ }
+
+ @Override
public Optional<BigDecimal> getAccountBalance(final String accountDesignator) {
return Optional.ofNullable(balances.get(accountDesignator));
}
@@ -57,11 +81,11 @@
return Optional.ofNullable(startOfTerm);
}
- public void adjustBalance(final String key, final BigDecimal amount) {
- final BigDecimal sign = ACCOUNT_SIGNS.get(key);
- final BigDecimal currentValue = balances.getOrDefault(key, BigDecimal.ZERO);
- final BigDecimal newValue = currentValue.add(amount.multiply(sign));
- balances.put(key, newValue);
+ public void adjustBalance(final String accountDesignator, final BigDecimal amount) {
+ final BigDecimal currentValue = balances.getOrDefault(accountDesignator, BigDecimal.ZERO);
+ final BigDecimal newValue = isAccountNegative(accountDesignator) ? currentValue.add(amount.negate())
+ : currentValue.add(amount);
+ balances.put(accountDesignator, newValue);
}
Map<String, BigDecimal> snapshot() {
diff --git a/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java b/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
index 9a0afd6..14bc95e 100644
--- a/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
+++ b/service/src/main/java/io/mifos/portfolio/service/internal/util/AccountingAdapter.java
@@ -198,12 +198,12 @@
.map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add);
}
- public BigDecimal getCurrentAccountBalance(final String accountIdentifier) {
+ public Account getAccount(final String accountIdentifier) {
try {
final Account account = ledgerManager.findAccount(accountIdentifier);
- if (account == null || account.getBalance() == null)
+ if (account == null || account.getBalance() == null || account.getType() == null)
throw ServiceException.internalError("Could not find the account with identifier ''{0}''", accountIdentifier);
- return BigDecimal.valueOf(account.getBalance());
+ return account;
}
catch (final AccountNotFoundException e) {
throw ServiceException.internalError("Could not find the account with identifier ''{0}''", accountIdentifier);