Skip to content
Permalink
Browse files
Merge pull request #8 from markusgeiss/develop
added validation to rest controller to exit early when a cheque is re…
  • Loading branch information
markusgeiss committed Sep 8, 2017
2 parents 74f815a + af6e8a7 commit ee39db79a8b4ff8495a4cdecb83ed91e7dd4dac5
Showing 4 changed files with 113 additions and 1 deletion.
@@ -21,6 +21,7 @@
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.TransactionProcessingException;
import io.mifos.teller.api.v1.domain.Cheque;
import io.mifos.teller.api.v1.domain.MICR;
@@ -634,4 +635,54 @@ public void shouldProcessCheque() throws Exception {
tellerTransactionCosts.getTellerTransactionIdentifier())
);
}

@Test(expected = TellerTransactionValidationException.class)
public void shouldNotProcessChequeAlreadyUsed() 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 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(246.80D));

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

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(246.80D));
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());

super.testSubject.post(teller.getCode(), chequeTransaction);

super.testSubject.post(teller.getCode(), chequeTransaction);
}
}
@@ -17,6 +17,7 @@

import io.mifos.cheque.api.v1.client.ChequeManager;
import io.mifos.cheque.api.v1.domain.ChequeTransaction;
import io.mifos.core.api.util.NotFoundException;
import io.mifos.teller.ServiceConstants;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
@@ -40,4 +41,13 @@ public ChequeService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logge
public void process(final ChequeTransaction chequeTransaction) {
this.chequeManager.process(chequeTransaction);
}

public boolean chequeExists(final String identifier) {
try {
this.chequeManager.get(identifier);
return true;
} catch (final NotFoundException nfex) {
return false;
}
}
}
@@ -0,0 +1,41 @@
/*
* 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.service.internal.util;

import io.mifos.teller.api.v1.domain.MICR;

public class MICRParser {
private static final String DELIMITER = "~";

private MICRParser() {
super();
}

public static String toIdentifier(final MICR micr) {
if (micr == null
|| micr.getChequeNumber() == null || micr.getChequeNumber().isEmpty()
|| micr.getBranchSortCode() == null || micr.getBranchSortCode().isEmpty()
|| micr.getAccountNumber() == null || micr.getAccountNumber().isEmpty()) {
throw new IllegalArgumentException("MICR must be given and all values need to be set.");
}

return micr.getChequeNumber()
+ MICRParser.DELIMITER
+ micr.getBranchSortCode()
+ MICRParser.DELIMITER
+ micr.getAccountNumber();
}
}
@@ -36,6 +36,8 @@
import io.mifos.teller.service.internal.service.TellerManagementService;
import io.mifos.teller.service.internal.service.TellerOperationService;
import io.mifos.teller.service.internal.service.helper.AccountingService;
import io.mifos.teller.service.internal.service.helper.ChequeService;
import io.mifos.teller.service.internal.util.MICRParser;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -65,18 +67,21 @@ public class TellerOperationRestController {
private final TellerOperationService tellerOperationService;
private final TellerManagementService tellerManagementService;
private final AccountingService accountingService;
private final ChequeService chequeService;

@Autowired
public TellerOperationRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
final CommandGateway commandGateway,
final TellerOperationService tellerOperationService,
final TellerManagementService tellerManagementService,
final AccountingService accountingService) {
final AccountingService accountingService,
final ChequeService chequeService) {
this.logger = logger;
this.commandGateway = commandGateway;
this.tellerOperationService = tellerOperationService;
this.tellerManagementService = tellerManagementService;
this.accountingService = accountingService;
this.chequeService = chequeService;
}

@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.TELLER_OPERATION)
@@ -175,6 +180,11 @@ ResponseEntity<TellerTransactionCosts> post(@PathVariable("tellerCode") final St
if (dateIssued.isBefore(sixMonth)) {
throw ServiceException.conflict("Cheque is older than 6 month.");
}

final String chequeIdentifier = MICRParser.toIdentifier(tellerTransaction.getCheque().getMicr());
if (this.chequeService.chequeExists(chequeIdentifier)) {
throw ServiceException.conflict("Cheque {0} already used.", chequeIdentifier);
}
}

final Optional<Account> optionalCustomerAccount =

0 comments on commit ee39db7

Please sign in to comment.