Merge pull request #40 from myrle-krantz/develop
Fixing account creation to deal with a conflict exception.
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 2fd1429..cf92e9d 100644
--- a/component-test/src/main/java/io/mifos/portfolio/AbstractPortfolioTest.java
+++ b/component-test/src/main/java/io/mifos/portfolio/AbstractPortfolioTest.java
@@ -29,11 +29,9 @@
import io.mifos.portfolio.api.v1.domain.*;
import io.mifos.portfolio.api.v1.events.*;
import io.mifos.portfolio.service.config.PortfolioServiceConfiguration;
-import io.mifos.portfolio.service.internal.util.AccountingAdapter;
import io.mifos.portfolio.service.internal.util.RhythmAdapter;
import org.junit.*;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -57,9 +55,6 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
-
/**
* @author Myrle Krantz
*/
@@ -86,14 +81,6 @@
public Logger logger() {
return LoggerFactory.getLogger(LOGGER_NAME);
}
- @Bean()
- public AccountingAdapter accountingAdapter(@SuppressWarnings("SpringJavaAutowiringInspection")
- final LedgerManager ledgerManager)
- {
- final AccountingAdapter spy = Mockito.spy(new AccountingAdapter(ledgerManager));
- doReturn(true).when(spy).accountAssignmentRepresentsRealAccount(any());
- return spy;
- }
}
static final String TEST_USER = "setau";
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 593a999..dffbe9f 100644
--- a/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
+++ b/component-test/src/main/java/io/mifos/portfolio/AccountingFixture.java
@@ -17,6 +17,7 @@
import io.mifos.accounting.api.v1.client.LedgerManager;
import io.mifos.accounting.api.v1.domain.*;
+import io.mifos.core.api.util.NotFoundException;
import io.mifos.core.lang.DateConverter;
import org.hamcrest.Description;
import org.mockito.AdditionalMatchers;
@@ -59,6 +60,9 @@
static final String LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER = "7810";
static final String CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER = "1103";
static final String LOANS_PAYABLE_ACCOUNT_IDENTIFIER ="missingInChartOfAccounts";
+ static final String LATE_FEE_INCOME_ACCOUNT_IDENTIFIER = "001-008"; //TODO: ??
+ static final String LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER = "001-009"; //TODO: ??
+ static final String ARREARS_ALLOWANCE_ACCOUNT_IDENTIFIER = "001-010"; //TODO: ??
static final Map<String, AccountData> accountMap = new HashMap<>();
@@ -88,8 +92,8 @@
final AccountData accountData = new AccountData(account);
accountMap.put(account.getIdentifier(), accountData);
Mockito.doAnswer(new AccountEntriesStreamAnswer(accountData))
- .when(ledgerManagerMock)
- .fetchAccountEntriesStream(Mockito.eq(account.getIdentifier()), Matchers.anyString(), Matchers.anyString(), Matchers.eq("ASC"));
+ .when(ledgerManagerMock)
+ .fetchAccountEntriesStream(Mockito.eq(account.getIdentifier()), Matchers.anyString(), Matchers.anyString(), Matchers.eq("ASC"));
}
@@ -221,6 +225,30 @@
return ret;
}
+ private static Account lateFeeIncomeAccount() {
+ final Account ret = new Account();
+ ret.setIdentifier(LATE_FEE_INCOME_ACCOUNT_IDENTIFIER);
+ //ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER); //TODO: ??
+ ret.setType(AccountType.LIABILITY.name()); //TODO: ??
+ return ret;
+ }
+
+ private static Account lateFeeAccrualAccount() {
+ final Account ret = new Account();
+ ret.setIdentifier(LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER);
+ //ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER); //TODO: ??
+ ret.setType(AccountType.LIABILITY.name()); //TODO: ??
+ return ret;
+ }
+
+ private static Account arrearsAllowanceAccount() {
+ final Account ret = new Account();
+ ret.setIdentifier(ARREARS_ALLOWANCE_ACCOUNT_IDENTIFIER);
+ //ret.setLedger(LOAN_INCOME_LEDGER_IDENTIFIER); //TODO: ??
+ ret.setType(AccountType.LIABILITY.name()); //TODO: ??
+ return ret;
+ }
+
private static AccountPage customerLoanAccountsPage() {
final Account customerLoanAccount1 = new Account();
customerLoanAccount1.setIdentifier("customerLoanAccount1");
@@ -363,7 +391,11 @@
@Override
public Account answer(final InvocationOnMock invocation) throws Throwable {
final String identifier = invocation.getArgumentAt(0, String.class);
- return accountMap.get(identifier).account;
+ final AccountData ret = accountMap.get(identifier);
+ if (ret != null)
+ return ret.account;
+ else
+ throw new NotFoundException("Account '" + identifier + "' not found.");
}
}
@@ -402,6 +434,9 @@
makeAccountResponsive(loanInterestAccrualAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(consumerLoanInterestAccount(), universalCreationDate, ledgerManagerMock);
makeAccountResponsive(loansPayableAccount(), universalCreationDate, ledgerManagerMock);
+ makeAccountResponsive(lateFeeIncomeAccount(), universalCreationDate, ledgerManagerMock);
+ makeAccountResponsive(lateFeeAccrualAccount(), universalCreationDate, ledgerManagerMock);
+ makeAccountResponsive(arrearsAllowanceAccount(), universalCreationDate, ledgerManagerMock);
Mockito.doReturn(incomeLedger()).when(ledgerManagerMock).findLedger(INCOME_LEDGER_IDENTIFIER);
Mockito.doReturn(feesAndChargesLedger()).when(ledgerManagerMock).findLedger(FEES_AND_CHARGES_LEDGER_IDENTIFIER);
diff --git a/component-test/src/main/java/io/mifos/portfolio/Fixture.java b/component-test/src/main/java/io/mifos/portfolio/Fixture.java
index 5910a20..777a327 100644
--- a/component-test/src/main/java/io/mifos/portfolio/Fixture.java
+++ b/component-test/src/main/java/io/mifos/portfolio/Fixture.java
@@ -69,9 +69,9 @@
accountAssignments.add(new AccountAssignment(INTEREST_INCOME, CONSUMER_LOAN_INTEREST_ACCOUNT_IDENTIFIER));
accountAssignments.add(new AccountAssignment(INTEREST_ACCRUAL, LOAN_INTEREST_ACCRUAL_ACCOUNT_IDENTIFIER));
accountAssignments.add(new AccountAssignment(LOANS_PAYABLE, LOANS_PAYABLE_ACCOUNT_IDENTIFIER));
- accountAssignments.add(new AccountAssignment(LATE_FEE_INCOME, "001-008"));
- accountAssignments.add(new AccountAssignment(LATE_FEE_ACCRUAL, "001-009"));
- accountAssignments.add(new AccountAssignment(ARREARS_ALLOWANCE, "001-010"));
+ accountAssignments.add(new AccountAssignment(LATE_FEE_INCOME, LATE_FEE_INCOME_ACCOUNT_IDENTIFIER));
+ accountAssignments.add(new AccountAssignment(LATE_FEE_ACCRUAL, LATE_FEE_ACCRUAL_ACCOUNT_IDENTIFIER));
+ accountAssignments.add(new AccountAssignment(ARREARS_ALLOWANCE, ARREARS_ALLOWANCE_ACCOUNT_IDENTIFIER));
//accountAssignments.add(new AccountAssignment(ENTRY, ...));
// Don't assign entry account in test since it usually will not be assigned IRL.
accountAssignments.add(new AccountAssignment(LOAN_FUNDS_SOURCE, LOAN_FUNDS_SOURCE_ACCOUNT_IDENTIFIER));
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 ad6a55d..341d2d7 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
@@ -15,6 +15,7 @@
*/
package io.mifos.portfolio.service.internal.util;
+import io.mifos.accounting.api.v1.client.AccountAlreadyExistsException;
import io.mifos.accounting.api.v1.client.AccountNotFoundException;
import io.mifos.accounting.api.v1.client.LedgerManager;
import io.mifos.accounting.api.v1.client.LedgerNotFoundException;
@@ -25,8 +26,11 @@
import io.mifos.core.lang.ServiceException;
import io.mifos.portfolio.api.v1.domain.AccountAssignment;
import io.mifos.portfolio.api.v1.domain.ChargeDefinition;
+import io.mifos.portfolio.service.ServiceConstants;
import org.apache.commons.lang.RandomStringUtils;
+import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
@@ -48,10 +52,13 @@
public enum IdentifierType {LEDGER, ACCOUNT}
private final LedgerManager ledgerManager;
+ private final Logger logger;
@Autowired
- public AccountingAdapter(@SuppressWarnings("SpringJavaAutowiringInspection") final LedgerManager ledgerManager) {
+ public AccountingAdapter(@SuppressWarnings("SpringJavaAutowiringInspection") final LedgerManager ledgerManager,
+ @Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
this.ledgerManager = ledgerManager;
+ this.logger = logger;
}
public void bookCharges(final List<ChargeInstance> costComponents,
@@ -155,14 +162,33 @@
generatedAccount.setBalance(0.0);
generatedAccount.setType(ledger.getType());
generatedAccount.setState(Account.State.OPEN.name());
- final String accountNumber = customerIdentifier + "." + ledgerAssignment.getDesignator()
- + "." + String.format("%05d", accountsOfLedger.getTotalElements() + 1);
- generatedAccount.setIdentifier(accountNumber);
+ long guestimatedAccountIndex = accountsOfLedger.getTotalElements() + 1;
generatedAccount.setLedger(ledger.getIdentifier());
- generatedAccount.setName(accountNumber);
- ledgerManager.createAccount(generatedAccount);
+ final Optional<String> createdAccountNumber =
+ Stream.iterate(guestimatedAccountIndex, i -> i + 1).limit(99999 - guestimatedAccountIndex)
+ .map(i -> {
+ final String accountNumber = createAccountNumber(customerIdentifier, ledgerAssignment.getDesignator(), i);
+ generatedAccount.setIdentifier(accountNumber);
+ generatedAccount.setName(accountNumber);
+ try {
+ ledgerManager.createAccount(generatedAccount);
+ return Optional.of(accountNumber);
+ } catch (final AccountAlreadyExistsException e) {
+ logger.error("Account '{}' could not be created because it already exists.", accountNumber);
+ return Optional.<String>empty();
+ }
+ })
+ .filter(Optional::isPresent).map(Optional::get)
+ .findFirst();
- return accountNumber;
+ return createdAccountNumber.orElseThrow(() ->
+ ServiceException.conflict("Failed to create an account for customer ''{0}'' and ''{1}'', in ledger ''{2}''.",
+ customerIdentifier, ledgerAssignment.getDesignator(), ledgerAssignment.getLedgerIdentifier()));
+ }
+
+ private String createAccountNumber(final String customerIdentifier, final String designator, final long accountIndex) {
+ return customerIdentifier + "." + designator
+ + "." + String.format("%05d", accountIndex);
}