You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by my...@apache.org on 2018/01/22 15:32:22 UTC
[fineract-cn-teller] 24/30: added account state validation before
any transaction added ability to include charges in cash received
This is an automated email from the ASF dual-hosted git repository.
myrle pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-teller.git
commit 4da5eddb976af4c75d69b9acee772e8f80e02643
Author: mgeiss <mg...@mifos.org>
AuthorDate: Thu Jul 6 11:06:22 2017 +0200
added account state validation before any transaction
added ability to include charges in cash received
---
.../mifos/teller/api/v1/client/TellerManager.java | 3 +-
.../java/io/mifos/teller/TestTellerOperation.java | 129 +++++++++---
.../mifos/teller/listener/TellerEventListener.java | 11 +
.../command/ConfirmTellerTransactionCommand.java | 8 +-
.../handler/TellerTransactionAggregate.java | 3 +-
...ocessor.java => DepositTransactionHandler.java} | 146 ++++++--------
.../processor/TellerTransactionProcessor.java | 224 +--------------------
.../rest/TellerOperationRestController.java | 15 +-
8 files changed, 204 insertions(+), 335 deletions(-)
diff --git a/api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java b/api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java
index 82529b3..b31001e 100644
--- a/api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java
+++ b/api/src/main/java/io/mifos/teller/api/v1/client/TellerManager.java
@@ -169,7 +169,8 @@ public interface TellerManager {
})
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",
diff --git a/component-test/src/main/java/io/mifos/teller/TestTellerOperation.java b/component-test/src/main/java/io/mifos/teller/TestTellerOperation.java
index 1f58971..98cbfbc 100644
--- a/component-test/src/main/java/io/mifos/teller/TestTellerOperation.java
+++ b/component-test/src/main/java/io/mifos/teller/TestTellerOperation.java
@@ -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 @@ import java.util.Optional;
public class TestTellerOperation extends AbstractTellerTest {
+ private static Teller tellerUnderTest = null;
+
public TestTellerOperation() {
super();
}
@@ -94,13 +101,6 @@ public class TestTellerOperation extends AbstractTellerTest {
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 class TestTellerOperation extends AbstractTellerTest {
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 class TestTellerOperation extends AbstractTellerTest {
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);
+ }
}
diff --git a/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java b/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java
index 0ad678a..a334311 100644
--- a/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java
+++ b/component-test/src/main/java/io/mifos/teller/listener/TellerEventListener.java
@@ -103,4 +103,15 @@ public class TellerEventListener {
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);
+ }
}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/command/ConfirmTellerTransactionCommand.java b/service/src/main/java/io/mifos/teller/service/internal/command/ConfirmTellerTransactionCommand.java
index 1da91da..32b156e 100644
--- a/service/src/main/java/io/mifos/teller/service/internal/command/ConfirmTellerTransactionCommand.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/ConfirmTellerTransactionCommand.java
@@ -17,13 +17,19 @@ package io.mifos.teller.service.internal.command;
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;
+ }
}
diff --git a/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerTransactionAggregate.java b/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerTransactionAggregate.java
index 5d59db4..224056c 100644
--- a/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerTransactionAggregate.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/command/handler/TellerTransactionAggregate.java
@@ -91,7 +91,8 @@ public class TellerTransactionAggregate {
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);
diff --git a/service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java b/service/src/main/java/io/mifos/teller/service/internal/processor/DepositTransactionHandler.java
similarity index 67%
copy from service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java
copy to service/src/main/java/io/mifos/teller/service/internal/processor/DepositTransactionHandler.java
index c03adff..ae78300 100644
--- a/service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/processor/DepositTransactionHandler.java
@@ -41,7 +41,7 @@ import java.util.Set;
import java.util.stream.Collectors;
@Component
-public class TellerTransactionProcessor {
+public class DepositTransactionHandler {
private final Logger logger;
private final AccountingService accountingService;
@@ -49,10 +49,10 @@ public class TellerTransactionProcessor {
private final TellerRepository tellerRepository;
@Autowired
- public TellerTransactionProcessor(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
- final AccountingService accountingService,
- final DepositAccountManagementService depositAccountManagementService,
- final TellerRepository tellerRepository) {
+ public DepositTransactionHandler(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+ final AccountingService accountingService,
+ final DepositAccountManagementService depositAccountManagementService,
+ final TellerRepository tellerRepository) {
super();
this.logger = logger;
this.accountingService = accountingService;
@@ -60,42 +60,22 @@ public class TellerTransactionProcessor {
this.tellerRepository = tellerRepository;
}
- public void process(final String tellerCode, final TellerTransaction tellerTransaction) {
- switch (tellerTransaction.getTransactionType()) {
- case ServiceConstants.TX_OPEN_ACCOUNT:
- this.processDepositAccountOpening(tellerCode, tellerTransaction);
- break;
- case ServiceConstants.TX_CLOSE_ACCOUNT:
- this.processDepositAccountClosing(tellerCode, tellerTransaction);
- break;
- case ServiceConstants.TX_ACCOUNT_TRANSFER:
- this.processTransfer(tellerTransaction);
- break;
- case ServiceConstants.TX_CASH_DEPOSIT:
- this.processCashDeposit(tellerCode, tellerTransaction);
- break;
- case ServiceConstants.TX_CASH_WITHDRAWAL:
- this.processCashWithdrawal(tellerCode, tellerTransaction);
- break;
- default:
- throw new IllegalArgumentException("Unsupported TX type " + tellerTransaction.getTransactionType());
- }
- }
+ public TellerTransactionCosts getDepositTransactionCosts(final TellerTransaction tellerTransaction) {
+ final List<Charge> charges = this.depositAccountManagementService.getCharges(tellerTransaction);
- public TellerTransactionCosts getCosts(final TellerTransaction tellerTransaction) {
- switch (tellerTransaction.getTransactionType()) {
- case ServiceConstants.TX_OPEN_ACCOUNT:
- case ServiceConstants.TX_CLOSE_ACCOUNT:
- case ServiceConstants.TX_ACCOUNT_TRANSFER:
- case ServiceConstants.TX_CASH_DEPOSIT:
- case ServiceConstants.TX_CASH_WITHDRAWAL:
- return this.getDepositTransactionCosts(tellerTransaction);
- default:
- throw new IllegalArgumentException("Unsupported TX type " + tellerTransaction.getTransactionType());
- }
+ final TellerTransactionCosts tellerTransactionCosts = new TellerTransactionCosts();
+ tellerTransactionCosts.setCharges(charges);
+ tellerTransactionCosts.setTellerTransactionIdentifier(tellerTransaction.getIdentifier());
+ tellerTransactionCosts.setTotalAmount(
+ tellerTransaction.getAmount() + charges.stream().mapToDouble(Charge::getAmount).sum()
+ );
+
+ return tellerTransactionCosts;
}
- private void processTransfer(final TellerTransaction tellerTransaction) {
+ public void processTransfer(final String tellerCode, final TellerTransaction tellerTransaction,
+ final boolean chargesIncluded) {
+ final TellerEntity tellerEntity = getTellerEntity(tellerCode);
final JournalEntry journalEntry = this.prepareJournalEntry(tellerTransaction);
final TellerTransactionCosts tellerTransactionCosts = this.getDepositTransactionCosts(tellerTransaction);
@@ -109,7 +89,11 @@ public class TellerTransactionProcessor {
debtors.add(customerDebtor);
if (!tellerTransactionCosts.getCharges().isEmpty()) {
- debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
+ if (chargesIncluded) {
+ debtors.add(this.createChargesDebtor(tellerEntity.getTellerAccountIdentifier(), tellerTransactionCosts));
+ } else {
+ debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
+ }
}
final HashSet<Creditor> creditors = new HashSet<>();
@@ -125,14 +109,8 @@ public class TellerTransactionProcessor {
this.accountingService.postJournalEntry(journalEntry);
}
- private void processCashDeposit(final String tellerCode, final TellerTransaction tellerTransaction) {
- final Optional<TellerEntity> optionalTeller = this.tellerRepository.findByIdentifier(tellerCode);
- if (!optionalTeller.isPresent()) {
- this.logger.warn("Teller {} not found.", tellerCode);
- throw new IllegalStateException("Teller not found.");
- }
-
- final TellerEntity tellerEntity = optionalTeller.get();
+ public void processCashDeposit(final String tellerCode, final TellerTransaction tellerTransaction, final boolean chargesIncluded) {
+ final TellerEntity tellerEntity = getTellerEntity(tellerCode);
final JournalEntry journalEntry = this.prepareJournalEntry(tellerTransaction);
final TellerTransactionCosts tellerTransactionCosts = this.getDepositTransactionCosts(tellerTransaction);
@@ -141,12 +119,15 @@ public class TellerTransactionProcessor {
final Debtor tellerDebtor = new Debtor();
tellerDebtor.setAccountNumber(tellerEntity.getTellerAccountIdentifier());
- tellerDebtor.setAmount(tellerTransaction.getAmount().toString());
- debtors.add(tellerDebtor);
-
- if (!tellerTransactionCosts.getCharges().isEmpty()) {
- debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
+ if (chargesIncluded) {
+ tellerDebtor.setAmount(tellerTransactionCosts.getTotalAmount().toString());
+ } else {
+ tellerDebtor.setAmount(tellerTransaction.getAmount().toString());
+ if (!tellerTransactionCosts.getCharges().isEmpty()) {
+ debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
+ }
}
+ debtors.add(tellerDebtor);
final HashSet<Creditor> creditors = new HashSet<>();
journalEntry.setCreditors(creditors);
@@ -161,14 +142,9 @@ public class TellerTransactionProcessor {
this.accountingService.postJournalEntry(journalEntry);
}
- private void processCashWithdrawal(final String tellerCode, final TellerTransaction tellerTransaction) {
- final Optional<TellerEntity> optionalTeller = this.tellerRepository.findByIdentifier(tellerCode);
- if (!optionalTeller.isPresent()) {
- this.logger.warn("Teller {} not found.", tellerCode);
- throw new IllegalStateException("Teller not found.");
- }
-
- final TellerEntity tellerEntity = optionalTeller.get();
+ public void processCashWithdrawal(final String tellerCode, final TellerTransaction tellerTransaction,
+ final boolean chargesIncluded) {
+ final TellerEntity tellerEntity = getTellerEntity(tellerCode);
final JournalEntry journalEntry = this.prepareJournalEntry(tellerTransaction);
final TellerTransactionCosts tellerTransactionCosts = this.getDepositTransactionCosts(tellerTransaction);
@@ -181,7 +157,11 @@ public class TellerTransactionProcessor {
debtors.add(customerDebtor);
if (!tellerTransactionCosts.getCharges().isEmpty()) {
- debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
+ if (chargesIncluded) {
+ debtors.add(this.createChargesDebtor(tellerEntity.getTellerAccountIdentifier(), tellerTransactionCosts));
+ } else {
+ debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
+ }
}
final HashSet<Creditor> creditors = new HashSet<>();
@@ -197,28 +177,23 @@ public class TellerTransactionProcessor {
this.accountingService.postJournalEntry(journalEntry);
}
- private void processDepositAccountClosing(final String tellerCode, final TellerTransaction tellerTransaction) {
- final List<ProductInstance> productInstances =
- this.depositAccountManagementService.fetchProductInstances(tellerTransaction.getCustomerIdentifier());
+ public void processDepositAccountClosing(final String tellerCode, final TellerTransaction tellerTransaction,
+ final boolean chargesIncluded) {
+ this.processCashWithdrawal(tellerCode, tellerTransaction, chargesIncluded);
- this.processCashWithdrawal(tellerCode, tellerTransaction);
-
- productInstances.forEach(productInstance -> {
- if (productInstance.getAccountIdentifier().equals(tellerTransaction.getCustomerAccountIdentifier())) {
- this.depositAccountManagementService.closeProductInstance(tellerTransaction.getCustomerAccountIdentifier());
- this.accountingService.closeAccount(tellerTransaction.getCustomerAccountIdentifier());
- }
- });
+ this.depositAccountManagementService.closeProductInstance(tellerTransaction.getCustomerAccountIdentifier());
+ this.accountingService.closeAccount(tellerTransaction.getCustomerAccountIdentifier());
}
- private void processDepositAccountOpening(final String tellerCode, final TellerTransaction tellerTransaction) {
+ public void processDepositAccountOpening(final String tellerCode, final TellerTransaction tellerTransaction,
+ final boolean chargesIncluded) {
final ProductInstance productInstances =
this.depositAccountManagementService.findProductInstance(tellerTransaction.getCustomerAccountIdentifier());
final ProductDefinition productDefinition =
this.depositAccountManagementService.findProductDefinition(productInstances.getProductIdentifier());
- this.processCashDeposit(tellerCode, tellerTransaction);
+ this.processCashDeposit(tellerCode, tellerTransaction, chargesIncluded);
if ((tellerTransaction.getAmount() + productInstances.getBalance()) >= productDefinition.getMinimumBalance()) {
this.depositAccountManagementService.activateProductInstance(tellerTransaction.getCustomerAccountIdentifier());
@@ -226,6 +201,16 @@ public class TellerTransactionProcessor {
}
}
+ private TellerEntity getTellerEntity(final String tellerCode) {
+ final Optional<TellerEntity> optionalTeller = this.tellerRepository.findByIdentifier(tellerCode);
+ if (!optionalTeller.isPresent()) {
+ this.logger.warn("Teller {} not found.", tellerCode);
+ throw new IllegalStateException("Teller not found.");
+ }
+
+ return optionalTeller.get();
+ }
+
private JournalEntry prepareJournalEntry(final TellerTransaction tellerTransaction) {
final JournalEntry journalEntry = new JournalEntry();
journalEntry.setTransactionIdentifier(tellerTransaction.getIdentifier());
@@ -237,19 +222,6 @@ public class TellerTransactionProcessor {
return journalEntry;
}
- private TellerTransactionCosts getDepositTransactionCosts(final TellerTransaction tellerTransaction) {
- final List<Charge> charges = this.depositAccountManagementService.getCharges(tellerTransaction);
-
- final TellerTransactionCosts tellerTransactionCosts = new TellerTransactionCosts();
- tellerTransactionCosts.setCharges(charges);
- tellerTransactionCosts.setTellerTransactionIdentifier(tellerTransaction.getIdentifier());
- tellerTransactionCosts.setTotalAmount(
- tellerTransaction.getAmount() + charges.stream().mapToDouble(Charge::getAmount).sum()
- );
-
- return tellerTransactionCosts;
- }
-
private Debtor createChargesDebtor(final String accountIdentifier, final TellerTransactionCosts tellerTransactionCosts) {
final Debtor chargesDebtor = new Debtor();
chargesDebtor.setAccountNumber(accountIdentifier);
diff --git a/service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java b/service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java
index c03adff..705911a 100644
--- a/service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java
+++ b/service/src/main/java/io/mifos/teller/service/internal/processor/TellerTransactionProcessor.java
@@ -15,67 +15,44 @@
*/
package io.mifos.teller.service.internal.processor;
-import io.mifos.accounting.api.v1.domain.Creditor;
-import io.mifos.accounting.api.v1.domain.Debtor;
-import io.mifos.accounting.api.v1.domain.JournalEntry;
-import io.mifos.core.api.util.UserContextHolder;
-import io.mifos.deposit.api.v1.definition.domain.ProductDefinition;
-import io.mifos.deposit.api.v1.instance.domain.ProductInstance;
import io.mifos.teller.ServiceConstants;
-import io.mifos.teller.api.v1.domain.Charge;
import io.mifos.teller.api.v1.domain.TellerTransaction;
import io.mifos.teller.api.v1.domain.TellerTransactionCosts;
-import io.mifos.teller.service.internal.repository.TellerEntity;
-import io.mifos.teller.service.internal.repository.TellerRepository;
-import io.mifos.teller.service.internal.service.helper.AccountingService;
-import io.mifos.teller.service.internal.service.helper.DepositAccountManagementService;
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.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
@Component
public class TellerTransactionProcessor {
private final Logger logger;
- private final AccountingService accountingService;
- private final DepositAccountManagementService depositAccountManagementService;
- private final TellerRepository tellerRepository;
+ private final DepositTransactionHandler depositTransactionHandler;
@Autowired
public TellerTransactionProcessor(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
- final AccountingService accountingService,
- final DepositAccountManagementService depositAccountManagementService,
- final TellerRepository tellerRepository) {
+ final DepositTransactionHandler depositTransactionHandler) {
super();
this.logger = logger;
- this.accountingService = accountingService;
- this.depositAccountManagementService = depositAccountManagementService;
- this.tellerRepository = tellerRepository;
+ this.depositTransactionHandler = depositTransactionHandler;
}
- public void process(final String tellerCode, final TellerTransaction tellerTransaction) {
+ public void process(final String tellerCode, final TellerTransaction tellerTransaction, final Boolean chargesIncluded) {
switch (tellerTransaction.getTransactionType()) {
case ServiceConstants.TX_OPEN_ACCOUNT:
- this.processDepositAccountOpening(tellerCode, tellerTransaction);
+ this.depositTransactionHandler.processDepositAccountOpening(tellerCode, tellerTransaction, chargesIncluded);
break;
case ServiceConstants.TX_CLOSE_ACCOUNT:
- this.processDepositAccountClosing(tellerCode, tellerTransaction);
+ this.depositTransactionHandler.processDepositAccountClosing(tellerCode, tellerTransaction, chargesIncluded);
break;
case ServiceConstants.TX_ACCOUNT_TRANSFER:
- this.processTransfer(tellerTransaction);
+ this.depositTransactionHandler.processTransfer(tellerCode, tellerTransaction, chargesIncluded);
break;
case ServiceConstants.TX_CASH_DEPOSIT:
- this.processCashDeposit(tellerCode, tellerTransaction);
+ this.depositTransactionHandler.processCashDeposit(tellerCode, tellerTransaction, chargesIncluded);
break;
case ServiceConstants.TX_CASH_WITHDRAWAL:
- this.processCashWithdrawal(tellerCode, tellerTransaction);
+ this.depositTransactionHandler.processCashWithdrawal(tellerCode, tellerTransaction, chargesIncluded);
break;
default:
throw new IllegalArgumentException("Unsupported TX type " + tellerTransaction.getTransactionType());
@@ -89,191 +66,10 @@ public class TellerTransactionProcessor {
case ServiceConstants.TX_ACCOUNT_TRANSFER:
case ServiceConstants.TX_CASH_DEPOSIT:
case ServiceConstants.TX_CASH_WITHDRAWAL:
- return this.getDepositTransactionCosts(tellerTransaction);
+ return this.depositTransactionHandler.getDepositTransactionCosts(tellerTransaction);
default:
throw new IllegalArgumentException("Unsupported TX type " + tellerTransaction.getTransactionType());
}
}
- private void processTransfer(final TellerTransaction tellerTransaction) {
- final JournalEntry journalEntry = this.prepareJournalEntry(tellerTransaction);
-
- final TellerTransactionCosts tellerTransactionCosts = this.getDepositTransactionCosts(tellerTransaction);
-
- final HashSet<Debtor> debtors = new HashSet<>();
- journalEntry.setDebtors(debtors);
-
- final Debtor customerDebtor = new Debtor();
- customerDebtor.setAccountNumber(tellerTransaction.getCustomerAccountIdentifier());
- customerDebtor.setAmount(tellerTransaction.getAmount().toString());
- debtors.add(customerDebtor);
-
- if (!tellerTransactionCosts.getCharges().isEmpty()) {
- debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
- }
-
- final HashSet<Creditor> creditors = new HashSet<>();
- journalEntry.setCreditors(creditors);
-
- final Creditor targetCreditor = new Creditor();
- targetCreditor.setAccountNumber(tellerTransaction.getTargetAccountIdentifier());
- targetCreditor.setAmount(tellerTransaction.getAmount().toString());
- creditors.add(targetCreditor);
-
- creditors.addAll(this.createChargeCreditors(tellerTransactionCosts));
-
- this.accountingService.postJournalEntry(journalEntry);
- }
-
- private void processCashDeposit(final String tellerCode, final TellerTransaction tellerTransaction) {
- final Optional<TellerEntity> optionalTeller = this.tellerRepository.findByIdentifier(tellerCode);
- if (!optionalTeller.isPresent()) {
- this.logger.warn("Teller {} not found.", tellerCode);
- throw new IllegalStateException("Teller not found.");
- }
-
- final TellerEntity tellerEntity = optionalTeller.get();
- final JournalEntry journalEntry = this.prepareJournalEntry(tellerTransaction);
- final TellerTransactionCosts tellerTransactionCosts = this.getDepositTransactionCosts(tellerTransaction);
-
- final HashSet<Debtor> debtors = new HashSet<>();
- journalEntry.setDebtors(debtors);
-
- final Debtor tellerDebtor = new Debtor();
- tellerDebtor.setAccountNumber(tellerEntity.getTellerAccountIdentifier());
- tellerDebtor.setAmount(tellerTransaction.getAmount().toString());
- debtors.add(tellerDebtor);
-
- if (!tellerTransactionCosts.getCharges().isEmpty()) {
- debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
- }
-
- final HashSet<Creditor> creditors = new HashSet<>();
- journalEntry.setCreditors(creditors);
-
- final Creditor customerCreditor = new Creditor();
- customerCreditor.setAccountNumber(tellerTransaction.getCustomerAccountIdentifier());
- customerCreditor.setAmount(tellerTransaction.getAmount().toString());
- creditors.add(customerCreditor);
-
- creditors.addAll(this.createChargeCreditors(tellerTransactionCosts));
-
- this.accountingService.postJournalEntry(journalEntry);
- }
-
- private void processCashWithdrawal(final String tellerCode, final TellerTransaction tellerTransaction) {
- final Optional<TellerEntity> optionalTeller = this.tellerRepository.findByIdentifier(tellerCode);
- if (!optionalTeller.isPresent()) {
- this.logger.warn("Teller {} not found.", tellerCode);
- throw new IllegalStateException("Teller not found.");
- }
-
- final TellerEntity tellerEntity = optionalTeller.get();
- final JournalEntry journalEntry = this.prepareJournalEntry(tellerTransaction);
- final TellerTransactionCosts tellerTransactionCosts = this.getDepositTransactionCosts(tellerTransaction);
-
- final HashSet<Debtor> debtors = new HashSet<>();
- journalEntry.setDebtors(debtors);
-
- final Debtor customerDebtor = new Debtor();
- customerDebtor.setAccountNumber(tellerTransaction.getCustomerAccountIdentifier());
- customerDebtor.setAmount(tellerTransaction.getAmount().toString());
- debtors.add(customerDebtor);
-
- if (!tellerTransactionCosts.getCharges().isEmpty()) {
- debtors.add(this.createChargesDebtor(tellerTransaction.getCustomerAccountIdentifier(), tellerTransactionCosts));
- }
-
- final HashSet<Creditor> creditors = new HashSet<>();
- journalEntry.setCreditors(creditors);
-
- final Creditor tellerCreditor = new Creditor();
- tellerCreditor.setAccountNumber(tellerEntity.getTellerAccountIdentifier());
- tellerCreditor.setAmount(tellerTransaction.getAmount().toString());
- creditors.add(tellerCreditor);
-
- creditors.addAll(this.createChargeCreditors(tellerTransactionCosts));
-
- this.accountingService.postJournalEntry(journalEntry);
- }
-
- private void processDepositAccountClosing(final String tellerCode, final TellerTransaction tellerTransaction) {
- final List<ProductInstance> productInstances =
- this.depositAccountManagementService.fetchProductInstances(tellerTransaction.getCustomerIdentifier());
-
- this.processCashWithdrawal(tellerCode, tellerTransaction);
-
- productInstances.forEach(productInstance -> {
- if (productInstance.getAccountIdentifier().equals(tellerTransaction.getCustomerAccountIdentifier())) {
- this.depositAccountManagementService.closeProductInstance(tellerTransaction.getCustomerAccountIdentifier());
- this.accountingService.closeAccount(tellerTransaction.getCustomerAccountIdentifier());
- }
- });
- }
-
- private void processDepositAccountOpening(final String tellerCode, final TellerTransaction tellerTransaction) {
- final ProductInstance productInstances =
- this.depositAccountManagementService.findProductInstance(tellerTransaction.getCustomerAccountIdentifier());
-
- final ProductDefinition productDefinition =
- this.depositAccountManagementService.findProductDefinition(productInstances.getProductIdentifier());
-
- this.processCashDeposit(tellerCode, tellerTransaction);
-
- if ((tellerTransaction.getAmount() + productInstances.getBalance()) >= productDefinition.getMinimumBalance()) {
- this.depositAccountManagementService.activateProductInstance(tellerTransaction.getCustomerAccountIdentifier());
- this.accountingService.openAccount(tellerTransaction.getCustomerAccountIdentifier());
- }
- }
-
- private JournalEntry prepareJournalEntry(final TellerTransaction tellerTransaction) {
- final JournalEntry journalEntry = new JournalEntry();
- journalEntry.setTransactionIdentifier(tellerTransaction.getIdentifier());
- journalEntry.setTransactionDate(tellerTransaction.getTransactionDate());
- journalEntry.setTransactionType(tellerTransaction.getTransactionType());
- journalEntry.setMessage(tellerTransaction.getTransactionType());
- journalEntry.setClerk(UserContextHolder.checkedGetUser());
-
- return journalEntry;
- }
-
- private TellerTransactionCosts getDepositTransactionCosts(final TellerTransaction tellerTransaction) {
- final List<Charge> charges = this.depositAccountManagementService.getCharges(tellerTransaction);
-
- final TellerTransactionCosts tellerTransactionCosts = new TellerTransactionCosts();
- tellerTransactionCosts.setCharges(charges);
- tellerTransactionCosts.setTellerTransactionIdentifier(tellerTransaction.getIdentifier());
- tellerTransactionCosts.setTotalAmount(
- tellerTransaction.getAmount() + charges.stream().mapToDouble(Charge::getAmount).sum()
- );
-
- return tellerTransactionCosts;
- }
-
- private Debtor createChargesDebtor(final String accountIdentifier, final TellerTransactionCosts tellerTransactionCosts) {
- final Debtor chargesDebtor = new Debtor();
- chargesDebtor.setAccountNumber(accountIdentifier);
- chargesDebtor.setAmount(
- Double.valueOf(
- tellerTransactionCosts.getCharges()
- .stream()
- .mapToDouble(Charge::getAmount)
- .sum()
- ).toString()
- );
-
- return chargesDebtor;
- }
-
- private Set<Creditor> createChargeCreditors(final TellerTransactionCosts tellerTransactionCosts) {
- return tellerTransactionCosts.getCharges()
- .stream()
- .map(charge -> {
- final Creditor chargeCreditor = new Creditor();
- chargeCreditor.setAccountNumber(charge.getIncomeAccountIdentifier());
- chargeCreditor.setAmount(charge.getAmount().toString());
- return chargeCreditor;
- })
- .collect(Collectors.toSet());
- }
}
diff --git a/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java b/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java
index 6f1104f..6295119 100644
--- a/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java
+++ b/service/src/main/java/io/mifos/teller/service/rest/TellerOperationRestController.java
@@ -84,7 +84,7 @@ public class TellerOperationRestController {
)
@ResponseBody
ResponseEntity<Teller> unlockDrawer(@PathVariable("tellerCode") final String tellerCode,
- @RequestBody @Valid final UnlockDrawerCommand unlockDrawerCommand) {
+ @RequestBody @Valid final UnlockDrawerCommand unlockDrawerCommand) {
final Teller teller = this.verifyTeller(tellerCode);
if (teller.getState().equals(Teller.State.CLOSED.name())) {
@@ -170,11 +170,17 @@ public class TellerOperationRestController {
if (!optionalCustomerAccount.isPresent()) {
throw ServiceException.badRequest("Customer account {0} not found.");
} else {
+ final Account customerAccount = optionalCustomerAccount.get();
+
+ if (!customerAccount.getState().equals(Account.State.OPEN)) {
+ throw ServiceException.conflict("Account {0} is not open.", customerAccount.getIdentifier());
+ }
+
if (transactionType.equals(ServiceConstants.TX_ACCOUNT_TRANSFER)
|| transactionType.equals(ServiceConstants.TX_CASH_WITHDRAWAL)
|| transactionType.equals(ServiceConstants.TX_CLOSE_ACCOUNT)) {
- final Account customerAccount = optionalCustomerAccount.get();
+
if (customerAccount.getBalance() < tellerTransaction.getAmount()) {
throw ServiceException.conflict("Not enough balance.");
}
@@ -206,7 +212,8 @@ public class TellerOperationRestController {
@ResponseBody
ResponseEntity<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) {
final Teller teller = this.verifyTeller(tellerCode);
this.verifyEmployee(teller);
@@ -217,7 +224,7 @@ public class TellerOperationRestController {
switch (command.toUpperCase()) {
case "CONFIRM" :
- this.commandGateway.process(new ConfirmTellerTransactionCommand(tellerTransactionIdentifier));
+ this.commandGateway.process(new ConfirmTellerTransactionCommand(tellerTransactionIdentifier, charges));
break;
case "CANCEL" :
this.commandGateway.process(new CancelTellerTransactionCommand(tellerTransactionIdentifier));
--
To stop receiving notification emails like this one, please contact
myrle@apache.org.