Getting account sign from accounting via adapter.
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..66d5a4e 100644
--- a/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
+++ b/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
@@ -168,8 +168,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 +180,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 +189,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 +198,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,6 +207,7 @@
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;
}
@@ -211,7 +215,8 @@
final Account ret = new Account();
ret.setIdentifier(CUSTOMERS_DEPOSIT_ACCOUNT);
ret.setLedger(CASH_LEDGER_IDENTIFIER);
- ret.setType(AccountType.ASSET.name());
+ ret.setType(AccountType.LIABILITY.name());
+ ret.setBalance(0.0);
return ret;
}
@@ -219,7 +224,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 +234,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 +243,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 +252,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 +261,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 +269,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 +277,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 +285,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 +293,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 +301,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);
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 ea45306..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
@@ -16,6 +16,7 @@
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;
@@ -55,7 +56,7 @@
.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 {
@@ -68,6 +69,37 @@
}
@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 accountCache.get(accountDesignator).map(Account::getBalance).map(BigDecimal::valueOf);
}
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 57d8f7c..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,39 +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.
- }};
-
- default BigDecimal getAccountSign(String accountDesignator) {
- return ACCOUNT_SIGNS.get(accountDesignator);
- }
+ /**
+ * 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);
@@ -66,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(
@@ -112,7 +99,7 @@
}
default BigDecimal getMaxDebit(final String accountDesignator, final BigDecimal amount) {
- if (getAccountSign(accountDesignator).signum() == -1)
+ if (isAccountNegative(accountDesignator))
return amount;
else
return amount.min(getAvailableBalance(accountDesignator, amount));
@@ -126,7 +113,7 @@
//expense account can achieve a "relative" negative balance, and
// both loss allowance accounts can achieve an "absolute" negative balance.
- if (getAccountSign(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 90a3b6d..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 = getAccountSign(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 3147ac3..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
@@ -201,7 +201,7 @@
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 account;
}