Skip to content
Permalink
Browse files
Merge pull request #21 from markusgeiss/develop
retrofitted teller balance sheet to fit new requirements
  • Loading branch information
markusgeiss committed Oct 9, 2017
2 parents 691a14e + f434dcd commit 785fc1e4b967aa42216c872e70fc74525c615e6e
Showing 10 changed files with 295 additions and 37 deletions.
@@ -25,8 +25,12 @@ public class TellerBalanceSheet {
private String day;
@DecimalMin(value = "0.001")
@DecimalMax(value = "9999999999.99999")
private BigDecimal balance;
private List<TellerEntry> entries;
private BigDecimal cashOnHand;
private BigDecimal cashReceivedTotal;
private BigDecimal cashDisbursedTotal;
private BigDecimal chequesReceivedTotal;
private List<TellerEntry> cashEntries;
private List<TellerEntry> chequeEntries;

public TellerBalanceSheet() {
super();
@@ -40,19 +44,51 @@ public void setDay(final String day) {
this.day = day;
}

public BigDecimal getBalance() {
return this.balance;
public BigDecimal getCashOnHand() {
return this.cashOnHand;
}

public void setBalance(final BigDecimal balance) {
this.balance = balance;
public void setCashOnHand(final BigDecimal cashOnHand) {
this.cashOnHand = cashOnHand;
}

public List<TellerEntry> getEntries() {
return this.entries;
public BigDecimal getCashReceivedTotal() {
return this.cashReceivedTotal;
}

public void setEntries(final List<TellerEntry> entries) {
this.entries = entries;
public void setCashReceivedTotal(final BigDecimal cashReceivedTotal) {
this.cashReceivedTotal = cashReceivedTotal;
}

public BigDecimal getCashDisbursedTotal() {
return this.cashDisbursedTotal;
}

public void setCashDisbursedTotal(final BigDecimal cashDisbursedTotal) {
this.cashDisbursedTotal = cashDisbursedTotal;
}

public BigDecimal getChequesReceivedTotal() {
return this.chequesReceivedTotal;
}

public void setChequesReceivedTotal(final BigDecimal chequesReceivedTotal) {
this.chequesReceivedTotal = chequesReceivedTotal;
}

public List<TellerEntry> getCashEntries() {
return this.cashEntries;
}

public void setCashEntries(final List<TellerEntry> cashEntries) {
this.cashEntries = cashEntries;
}

public List<TellerEntry> getChequeEntries() {
return this.chequeEntries;
}

public void setChequeEntries(final List<TellerEntry> chequeEntries) {
this.chequeEntries = chequeEntries;
}
}
@@ -23,7 +23,8 @@ public class TellerEntry {

public enum Type {
DEBIT,
CREDIT
CREDIT,
CHEQUE
}

private Type type;
@@ -24,6 +24,7 @@
import io.mifos.teller.api.v1.EventConstants;
import io.mifos.teller.api.v1.client.TellerManager;
import io.mifos.teller.service.internal.service.helper.AccountingService;
import io.mifos.teller.service.internal.service.helper.ChequeService;
import io.mifos.teller.service.internal.service.helper.DepositAccountManagementService;
import io.mifos.teller.service.internal.service.helper.OrganizationService;
import io.mifos.teller.service.internal.service.helper.PortfolioService;
@@ -103,6 +104,9 @@ public Logger logger() {
@MockBean
PortfolioService portfolioServiceSpy;

@MockBean
ChequeService chequeServiceSpy;

@Autowired
private ApplicationName applicationName;

@@ -0,0 +1,178 @@
/*
* Copyright 2017 The Mifos Initiative.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.mifos.teller;

import com.google.common.collect.Lists;
import io.mifos.accounting.api.v1.domain.Account;
import io.mifos.accounting.api.v1.domain.AccountEntry;
import io.mifos.accounting.api.v1.domain.AccountEntryPage;
import io.mifos.core.lang.DateConverter;
import io.mifos.teller.api.v1.EventConstants;
import io.mifos.teller.api.v1.domain.Cheque;
import io.mifos.teller.api.v1.domain.MICR;
import io.mifos.teller.api.v1.domain.Teller;
import io.mifos.teller.api.v1.domain.TellerBalanceSheet;
import io.mifos.teller.api.v1.domain.TellerManagementCommand;
import io.mifos.teller.api.v1.domain.TellerTransaction;
import io.mifos.teller.api.v1.domain.TellerTransactionCosts;
import io.mifos.teller.api.v1.domain.UnlockDrawerCommand;
import io.mifos.teller.util.TellerGenerator;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;

import java.math.BigDecimal;
import java.time.Clock;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Optional;

public class TestTellerBalance extends AbstractTellerTest {

@Test
public void shouldCreateTellerBalanceSheet() throws Exception {
final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
final Teller randomTeller = TellerGenerator.createRandomTeller();

Mockito.doAnswer(invocation -> true)
.when(super.organizationServiceSpy).officeExists(Matchers.eq(officeIdentifier));

Mockito.doAnswer(invocation -> Optional.of(new Account()))
.when(super.accountingServiceSpy).findAccount(Matchers.eq(randomTeller.getTellerAccountIdentifier()));

Mockito.doAnswer(invocation -> Optional.of(new Account()))
.when(super.accountingServiceSpy).findAccount(Matchers.eq(randomTeller.getVaultAccountIdentifier()));

super.testSubject.create(officeIdentifier, randomTeller);
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, randomTeller.getCode()));

final TellerManagementCommand command = new TellerManagementCommand();
command.setAction(TellerManagementCommand.Action.OPEN.name());
command.setAdjustment(TellerManagementCommand.Adjustment.NONE.name());
command.setAssignedEmployeeIdentifier(AbstractTellerTest.TEST_USER);

Mockito.doAnswer(invocation -> true)
.when(super.organizationServiceSpy).employeeExists(Matchers.eq(command.getAssignedEmployeeIdentifier()));

super.testSubject.post(officeIdentifier, randomTeller.getCode(), command);
Assert.assertTrue(super.eventRecorder.wait(EventConstants.OPEN_TELLER, randomTeller.getCode()));

final UnlockDrawerCommand unlockDrawerCommand = new UnlockDrawerCommand();
unlockDrawerCommand.setEmployeeIdentifier(AbstractTellerTest.TEST_USER);
unlockDrawerCommand.setPassword(randomTeller.getPassword());
super.testSubject.unlockDrawer(randomTeller.getCode(), unlockDrawerCommand);
Assert.assertTrue(super.eventRecorder.wait(EventConstants.AUTHENTICATE_TELLER, randomTeller.getCode()));

this.prepareCheque(randomTeller);
this.prepareAccountEntryMocks(randomTeller.getTellerAccountIdentifier());

final TellerBalanceSheet tellerBalanceSheet = super.testSubject.getBalance(officeIdentifier, randomTeller.getCode());
Assert.assertTrue(BigDecimal.valueOf(604.00D).compareTo(tellerBalanceSheet.getCashReceivedTotal()) == 0);
Assert.assertTrue(BigDecimal.valueOf(150.00D).compareTo(tellerBalanceSheet.getCashDisbursedTotal()) == 0);
Assert.assertTrue(BigDecimal.valueOf(500.00D).compareTo(tellerBalanceSheet.getChequesReceivedTotal()) == 0);
Assert.assertTrue(BigDecimal.valueOf(454.00D).compareTo(tellerBalanceSheet.getCashOnHand()) == 0);
}

private void prepareCheque(final Teller teller) throws Exception {
final TellerTransaction chequeTransaction = new TellerTransaction();
chequeTransaction.setTransactionType(ServiceConstants.TX_CHEQUE);
chequeTransaction.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
chequeTransaction.setProductIdentifier(RandomStringUtils.randomAlphanumeric(32));
chequeTransaction.setProductCaseIdentifier(RandomStringUtils.randomAlphanumeric(32));
chequeTransaction.setCustomerAccountIdentifier(RandomStringUtils.randomAlphanumeric(32));
chequeTransaction.setCustomerIdentifier(RandomStringUtils.randomAlphanumeric(32));
chequeTransaction.setClerk(AbstractTellerTest.TEST_USER);
chequeTransaction.setAmount(BigDecimal.valueOf(500.00D));

final MICR micr = new MICR();
micr.setChequeNumber("0011");
micr.setBranchSortCode("08154711");
micr.setAccountNumber("4711");

Mockito
.doAnswer(invocation -> Optional.empty())
.when(super.accountingServiceSpy).findAccount(Matchers.eq(micr.getAccountNumber()));

final Cheque cheque = new Cheque();
cheque.setMicr(micr);
cheque.setDrawee("whatever Bank");
cheque.setDrawer("Jane Doe");
cheque.setPayee("John Doe");
cheque.setDateIssued(DateConverter.toIsoString(LocalDate.now(Clock.systemUTC())));
cheque.setAmount(BigDecimal.valueOf(500.00D));
cheque.setOpenCheque(Boolean.FALSE);
chequeTransaction.setCheque(cheque);

Mockito
.doAnswer(invocation -> {
final Account mockedAccount = new Account();
mockedAccount.setState(Account.State.OPEN.name());
return Optional.of(mockedAccount);
})
.when(super.accountingServiceSpy).findAccount(chequeTransaction.getCustomerAccountIdentifier());

final TellerTransactionCosts tellerTransactionCosts = super.testSubject.post(teller.getCode(), chequeTransaction);

super.testSubject.confirm(teller.getCode(), tellerTransactionCosts.getTellerTransactionIdentifier(),"CONFIRM", null);

Assert.assertTrue(
super.eventRecorder.wait(EventConstants.CONFIRM_TRANSACTION,
tellerTransactionCosts.getTellerTransactionIdentifier())
);
}

private void prepareAccountEntryMocks(final String accountIdentifier) {

final AccountEntry firstDeposit = new AccountEntry();
firstDeposit.setType(AccountEntry.Type.DEBIT.name());
firstDeposit.setMessage(ServiceConstants.TX_CASH_DEPOSIT);
firstDeposit.setAmount(200.00D);

final AccountEntry secondDeposit = new AccountEntry();
secondDeposit.setType(AccountEntry.Type.DEBIT.name());
secondDeposit.setMessage(ServiceConstants.TX_CASH_DEPOSIT);
secondDeposit.setAmount(150.00D);

final AccountEntry firstWithdrawal = new AccountEntry();
firstWithdrawal.setType(AccountEntry.Type.CREDIT.name());
firstWithdrawal.setMessage(ServiceConstants.TX_CASH_WITHDRAWAL);
firstWithdrawal.setAmount(50.00D);

final AccountEntry secondWithdrawal = new AccountEntry();
secondWithdrawal.setType(AccountEntry.Type.CREDIT.name());
secondWithdrawal.setMessage(ServiceConstants.TX_CASH_WITHDRAWAL);
secondWithdrawal.setAmount(100.00D);

final AccountEntry loanRepayment = new AccountEntry();
loanRepayment.setType(AccountEntry.Type.DEBIT.name());
loanRepayment.setMessage(ServiceConstants.TX_REPAYMENT);
loanRepayment.setAmount(254.00D);

final AccountEntryPage accountEntryPage = new AccountEntryPage();
accountEntryPage.setAccountEntries(
Lists.newArrayList(firstDeposit, secondDeposit, firstWithdrawal, secondWithdrawal, loanRepayment)
);
accountEntryPage.setTotalPages(1);
accountEntryPage.setTotalElements(Integer.valueOf(accountEntryPage.getAccountEntries().size()).longValue());

Mockito
.doAnswer(invocation -> accountEntryPage)
.when(super.accountingServiceSpy)
.fetchAccountEntries(Matchers.eq(accountIdentifier), Matchers.anyString(), Matchers.eq(0), Matchers.anyInt());
}
}
@@ -616,7 +616,7 @@ public void shouldReturnZeroBalanceTellerNeverOpened() throws Exception {
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));

final TellerBalanceSheet tellerBalanceSheet = super.testSubject.getBalance(officeIdentifier, teller.getCode());
Assert.assertTrue(BigDecimal.ZERO.compareTo(tellerBalanceSheet.getBalance()) == 0);
Assert.assertTrue(BigDecimal.ZERO.compareTo(tellerBalanceSheet.getCashOnHand()) == 0);
}

private void compareTeller(final Teller expected, final Teller actual) {
@@ -28,7 +28,7 @@ private TellerEntryMapper() {

public static TellerEntry map(final AccountEntry accountEntry) {
final TellerEntry tellerEntry = new TellerEntry();
tellerEntry.setType(accountEntry.getType());
tellerEntry.setType(TellerEntry.Type.valueOf(accountEntry.getType()).name());
tellerEntry.setTransactionDate(accountEntry.getTransactionDate());
tellerEntry.setMessage(accountEntry.getMessage());
tellerEntry.setAmount(BigDecimal.valueOf(accountEntry.getAmount()));
@@ -30,7 +30,6 @@
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
@@ -18,6 +18,7 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@@ -29,4 +30,9 @@ public interface TellerTransactionRepository extends JpaRepository<TellerTransac

List<TellerTransactionEntity> findByTellerAndStateOrderByTransactionDateAsc(final TellerEntity teller,
final String state);

List<TellerTransactionEntity> findByTellerAndTransactionTypeAndTransactionDateBetween(final TellerEntity tellerEntity,
final String transactionType,
final LocalDateTime startDate,
final LocalDateTime endDate);
}

0 comments on commit 785fc1e

Please sign in to comment.