Skip to content
Permalink
Browse files
added account state validation before any transaction
added ability to include charges in cash received
  • Loading branch information
mgeiss committed Jul 6, 2017
1 parent bc87486 commit 4da5eddb976af4c75d69b9acee772e8f80e02643
Show file tree
Hide file tree
Showing 8 changed files with 396 additions and 248 deletions.
@@ -169,7 +169,8 @@ TellerTransactionCosts post(@PathVariable("tellerCode") final String tellerCode,
})
void confirm(@PathVariable("tellerCode") final String tellerCode,
@PathVariable("identifier") final String tellerTransactionIdentifier,
@RequestParam(value = "command", required = true) final String command);
@RequestParam(value = "command", required = true) final String command,
@RequestParam(value = "charges", required = false, defaultValue = "excluded") final String charges);

@RequestMapping(
value = "/teller/{tellerCode}/transactions",
@@ -16,14 +16,19 @@
package io.mifos.teller;

import io.mifos.accounting.api.v1.domain.Account;
import io.mifos.core.api.context.AutoUserContext;
import io.mifos.core.lang.DateConverter;
import io.mifos.deposit.api.v1.definition.domain.ProductDefinition;
import io.mifos.deposit.api.v1.instance.domain.ProductInstance;
import io.mifos.teller.api.v1.EventConstants;
import io.mifos.teller.api.v1.client.TellerNotFoundException;
import io.mifos.teller.api.v1.client.TellerTransactionValidationException;
import io.mifos.teller.api.v1.client.TellerValidationException;
import io.mifos.teller.api.v1.client.TransactionProcessingException;
import io.mifos.teller.api.v1.domain.Teller;
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;
@@ -39,6 +44,8 @@

public class TestTellerOperation extends AbstractTellerTest {

private static Teller tellerUnderTest = null;

public TestTellerOperation() {
super();
}
@@ -94,13 +101,6 @@ public void shouldPauseTeller() throws Exception {
Assert.assertTrue(super.eventRecorder.wait(EventConstants.PAUSE_TELLER, teller.getCode()));
}

@Test(expected = TellerValidationException.class)
public void shouldNotPauseTellerNotAuthenticated() throws Exception {
final Teller teller = this.prepareTeller();

super.testSubject.post(teller.getCode(), "PAUSE");
}

@Test
public void shouldOpenAccount() throws Exception {
final Teller teller = this.prepareTeller();
@@ -331,37 +331,49 @@ public void shouldNotWithdrawExceedsCashDrawLimit() throws Exception {
super.testSubject.post(teller.getCode(), tellerTransaction);
}


private Teller prepareTeller() throws Exception {
final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
final Teller teller = TellerGenerator.createRandomTeller();
if (TestTellerOperation.tellerUnderTest == null) {
final String officeIdentifier = RandomStringUtils.randomAlphabetic(32);
TestTellerOperation.tellerUnderTest = TellerGenerator.createRandomTeller();

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

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

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

super.testSubject.create(officeIdentifier, teller);
super.testSubject.create(officeIdentifier, TestTellerOperation.tellerUnderTest);

Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, teller.getCode()));
Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_TELLER, TestTellerOperation.tellerUnderTest.getCode()));

final TellerManagementCommand command = new TellerManagementCommand();
command.setAction(TellerManagementCommand.Action.OPEN.name());
command.setAdjustment(TellerManagementCommand.Adjustment.NONE.name());
command.setAssignedEmployeeIdentifier(AbstractTellerTest.TEST_USER);
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()));
Mockito.doAnswer(invocation -> true)
.when(super.organizationServiceSpy).employeeExists(Matchers.eq(command.getAssignedEmployeeIdentifier()));

super.testSubject.post(officeIdentifier, TestTellerOperation.tellerUnderTest.getCode(), command);

super.testSubject.post(officeIdentifier, teller.getCode(), command);
Assert.assertTrue(super.eventRecorder.wait(EventConstants.OPEN_TELLER, TestTellerOperation.tellerUnderTest.getCode()));
}

Assert.assertTrue(super.eventRecorder.wait(EventConstants.OPEN_TELLER, teller.getCode()));
final ProductInstance productInstance = new ProductInstance();
productInstance.setProductIdentifier(RandomStringUtils.randomAlphanumeric(32));
productInstance.setBalance(0.00D);
Mockito.doAnswer(invocation -> productInstance)
.when(super.depositAccountManagementServiceSpy).findProductInstance(Matchers.anyString());

return teller;
final ProductDefinition productDefinition = new ProductDefinition();
productDefinition.setMinimumBalance(0.00D);
Mockito.doAnswer(invocation -> productDefinition)
.when(super.depositAccountManagementServiceSpy).findProductDefinition(Matchers.eq(productInstance.getProductIdentifier()));

return TestTellerOperation.tellerUnderTest;
}

@Test(expected = TellerNotFoundException.class)
@@ -388,4 +400,67 @@ public void shouldNotUnlockTellerClosed() throws Exception {

super.testSubject.unlockDrawer(teller.getCode(), unlockDrawerCommand);
}

@Test(expected = TellerTransactionValidationException.class)
public void shouldNotReopenAccountClosed() throws Exception {
final Teller teller = this.prepareTeller();

final UnlockDrawerCommand unlockDrawerCommand = new UnlockDrawerCommand();
unlockDrawerCommand.setEmployeeIdentifier(AbstractTellerTest.TEST_USER);
unlockDrawerCommand.setPassword(teller.getPassword());

super.testSubject.unlockDrawer(teller.getCode(), unlockDrawerCommand);

super.eventRecorder.wait(EventConstants.AUTHENTICATE_TELLER, teller.getCode());

final TellerTransaction openAccountTransaction = new TellerTransaction();
openAccountTransaction.setTransactionType(ServiceConstants.TX_OPEN_ACCOUNT);
openAccountTransaction.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
openAccountTransaction.setProductIdentifier(RandomStringUtils.randomAlphanumeric(32));
openAccountTransaction.setCustomerAccountIdentifier(RandomStringUtils.randomAlphanumeric(32));
openAccountTransaction.setCustomerIdentifier(RandomStringUtils.randomAlphanumeric(32));
openAccountTransaction.setClerk(AbstractTellerTest.TEST_USER);
openAccountTransaction.setAmount(1234.56D);

Mockito.doAnswer(invocation -> Optional.of(new Account()))
.when(super.accountingServiceSpy).findAccount(openAccountTransaction.getCustomerAccountIdentifier());
Mockito.doAnswer(invocation -> Collections.emptyList())
.when(super.depositAccountManagementServiceSpy).getCharges(Matchers.eq(openAccountTransaction));
Mockito.doAnswer(invocation -> Collections.emptyList())
.when(super.depositAccountManagementServiceSpy).fetchProductInstances(openAccountTransaction.getCustomerIdentifier());

final TellerTransactionCosts openingCosts = super.testSubject.post(teller.getCode(), openAccountTransaction);
super.testSubject.confirm(teller.getCode(), openingCosts.getTellerTransactionIdentifier(), "CONFIRM", "excluded");
super.eventRecorder.wait(EventConstants.CONFIRM_TRANSACTION, openingCosts.getTellerTransactionIdentifier());

final TellerTransaction closeAccountTransaction = new TellerTransaction();
closeAccountTransaction.setTransactionType(ServiceConstants.TX_CLOSE_ACCOUNT);
closeAccountTransaction.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
closeAccountTransaction.setProductIdentifier(openAccountTransaction.getProductIdentifier());
closeAccountTransaction.setCustomerAccountIdentifier(openAccountTransaction.getCustomerAccountIdentifier());
closeAccountTransaction.setCustomerIdentifier(openAccountTransaction.getCustomerIdentifier());
closeAccountTransaction.setClerk(AbstractTellerTest.TEST_USER);
closeAccountTransaction.setAmount(1234.56D);

final Account account = new Account();
account.setBalance(1234.56D);

Mockito.doAnswer(invocation -> Optional.of(account))
.when(super.accountingServiceSpy).findAccount(openAccountTransaction.getCustomerAccountIdentifier());

final TellerTransactionCosts closingCosts = super.testSubject.post(teller.getCode(), closeAccountTransaction);
super.testSubject.confirm(teller.getCode(), closingCosts.getTellerTransactionIdentifier(), "CONFIRM", "excluded");
super.eventRecorder.wait(EventConstants.CONFIRM_TRANSACTION, closingCosts.getTellerTransactionIdentifier());

final TellerTransaction reopenAccountTransaction = new TellerTransaction();
reopenAccountTransaction.setTransactionType(ServiceConstants.TX_OPEN_ACCOUNT);
reopenAccountTransaction.setTransactionDate(DateConverter.toIsoString(LocalDateTime.now(Clock.systemUTC())));
reopenAccountTransaction.setProductIdentifier(openAccountTransaction.getProductIdentifier());
reopenAccountTransaction.setCustomerAccountIdentifier(openAccountTransaction.getCustomerAccountIdentifier());
reopenAccountTransaction.setCustomerIdentifier(openAccountTransaction.getCustomerIdentifier());
reopenAccountTransaction.setClerk(AbstractTellerTest.TEST_USER);
reopenAccountTransaction.setAmount(1234.56D);

super.testSubject.post(teller.getCode(), reopenAccountTransaction);
}
}
@@ -103,4 +103,15 @@ public void onPause(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenan
this.logger.debug("Teller {} created.", payload);
this.eventRecorder.event(tenant, EventConstants.PAUSE_TELLER, payload, String.class);
}

@JmsListener(
destination = EventConstants.DESTINATION,
selector = EventConstants.SELECTOR_CONFIRM_TRANSACTION,
subscription = EventConstants.DESTINATION
)
public void confirmTransaction(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
final String payload) {
this.logger.debug("Teller {} created.", payload);
this.eventRecorder.event(tenant, EventConstants.CONFIRM_TRANSACTION, payload, String.class);
}
}
@@ -17,13 +17,19 @@

public class ConfirmTellerTransactionCommand {
private final String tellerTransactionIdentifier;
private final boolean chargesIncluded;

public ConfirmTellerTransactionCommand(final String tellerTransactionIdentifier) {
public ConfirmTellerTransactionCommand(final String tellerTransactionIdentifier, final String charges) {
super();
this.tellerTransactionIdentifier = tellerTransactionIdentifier;
this.chargesIncluded = charges.equalsIgnoreCase("included");
}

public String tellerTransactionIdentifier() {
return this.tellerTransactionIdentifier;
}

public boolean chargesIncluded() {
return this.chargesIncluded;
}
}
@@ -91,7 +91,8 @@ public String process(final ConfirmTellerTransactionCommand confirmTellerTransac
final TellerTransactionEntity tellerTransactionEntity = optionalTellerTransaction.get();

this.tellerTransactionProcessor.process(tellerTransactionEntity.getTeller().getIdentifier(),
TellerTransactionMapper.map(tellerTransactionEntity));
TellerTransactionMapper.map(tellerTransactionEntity),
confirmTellerTransactionCommand.chargesIncluded());

tellerTransactionEntity.setState(TellerTransaction.State.CONFIRMED.name());
this.tellerTransactionRepository.save(tellerTransactionEntity);

0 comments on commit 4da5edd

Please sign in to comment.