fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From my...@apache.org
Subject [fineract-cn-payroll] 22/27: added account validation before initializing payroll transaction
Date Mon, 22 Jan 2018 15:29:38 GMT
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-payroll.git

commit 23bd6e3446df127f93d248987ec864eff7215c94
Author: mgeiss <mgeiss@mifos.org>
AuthorDate: Fri Oct 6 16:22:07 2017 +0200

    added account validation before initializing payroll transaction
---
 .../payroll/api/v1/client/PayrollManager.java      |   3 +-
 .../io/mifos/payroll/TestPayrollDistribution.java  | 111 ++++++++++++++++++---
 .../rest/PayrollDistributionRestController.java    |  35 +++++--
 3 files changed, 128 insertions(+), 21 deletions(-)

diff --git a/api/src/main/java/io/mifos/payroll/api/v1/client/PayrollManager.java b/api/src/main/java/io/mifos/payroll/api/v1/client/PayrollManager.java
index 5c232c0..d9235cf 100644
--- a/api/src/main/java/io/mifos/payroll/api/v1/client/PayrollManager.java
+++ b/api/src/main/java/io/mifos/payroll/api/v1/client/PayrollManager.java
@@ -69,7 +69,8 @@ public interface PayrollManager {
       consumes = MediaType.APPLICATION_JSON_VALUE
   )
   @ThrowsExceptions({
-      @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = PayrollPaymentValidationException.class)
+      @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = PayrollPaymentValidationException.class),
+      @ThrowsException(status = HttpStatus.CONFLICT, exception = PayrollPaymentValidationException.class)
   })
   void distribute(@RequestBody @Valid final PayrollCollectionSheet payrollCollectionSheet);
 
diff --git a/component-test/src/main/java/io/mifos/payroll/TestPayrollDistribution.java b/component-test/src/main/java/io/mifos/payroll/TestPayrollDistribution.java
index 661b586..cca752c 100644
--- a/component-test/src/main/java/io/mifos/payroll/TestPayrollDistribution.java
+++ b/component-test/src/main/java/io/mifos/payroll/TestPayrollDistribution.java
@@ -19,6 +19,8 @@ import com.google.common.collect.Lists;
 import io.mifos.accounting.api.v1.domain.Account;
 import io.mifos.customer.api.v1.domain.Customer;
 import io.mifos.payroll.api.v1.EventConstants;
+import io.mifos.payroll.api.v1.client.PayrollPaymentValidationException;
+import io.mifos.payroll.api.v1.domain.PayrollAllocation;
 import io.mifos.payroll.api.v1.domain.PayrollCollectionHistory;
 import io.mifos.payroll.api.v1.domain.PayrollCollectionSheet;
 import io.mifos.payroll.api.v1.domain.PayrollConfiguration;
@@ -67,17 +69,19 @@ public class TestPayrollDistribution extends AbstractPayrollTest {
     payrollPayment.setSalary(BigDecimal.valueOf(1234.56D));
     payrollCollectionSheet.setPayrollPayments(Lists.newArrayList(payrollPayment));
 
+    final Account sourceAccount = new Account();
+    sourceAccount.setState(Account.State.OPEN.name());
     Mockito
-        .doAnswer(invocation -> Optional.of(new Account()))
+        .doAnswer(invocation -> Optional.of(sourceAccount))
         .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(payrollCollectionSheet.getSourceAccountNumber()));
 
     Mockito
         .doAnswer(invocation -> Optional.empty())
         .when(this.accountingAdaptorSpy).postPayrollPayment(
-            Matchers.any(PayrollCollectionEntity.class),
-            Matchers.refEq(payrollPayment),
-            Matchers.any(PayrollConfiguration.class)
-        );
+        Matchers.any(PayrollCollectionEntity.class),
+        Matchers.refEq(payrollPayment),
+        Matchers.any(PayrollConfiguration.class)
+    );
 
     super.testSubject.distribute(payrollCollectionSheet);
     Assert.assertTrue(super.eventRecorder.wait(EventConstants.POST_DISTRIBUTION, payrollCollectionSheet.getSourceAccountNumber()));
@@ -94,20 +98,103 @@ public class TestPayrollDistribution extends AbstractPayrollTest {
     Assert.assertTrue(fetchedPayrollPayment.getProcessed());
   }
 
+  @Test(expected = PayrollPaymentValidationException.class)
+  public void shouldNotDistributePaymentsAllocatedAccountClosed() throws Exception {
+    final String customerIdentifier = RandomStringUtils.randomAlphanumeric(32);
+    final PayrollConfiguration payrollConfiguration = DomainObjectGenerator.getPayrollConfiguration();
+    this.prepareMocks(customerIdentifier, payrollConfiguration);
+
+    final PayrollAllocation invalidPayrollAllocation = new PayrollAllocation();
+    invalidPayrollAllocation.setAccountNumber(RandomStringUtils.randomAlphanumeric(34));
+    invalidPayrollAllocation.setProportional(Boolean.FALSE);
+    invalidPayrollAllocation.setAmount(BigDecimal.valueOf(200.00D));
+    payrollConfiguration.getPayrollAllocations().add(invalidPayrollAllocation);
+
+    final Account invalidPayrollAccount = new Account();
+    invalidPayrollAccount.setState(Account.State.CLOSED.name());
+    Mockito
+        .doAnswer(invocation -> Optional.of(invalidPayrollAccount))
+        .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(invalidPayrollAllocation.getAccountNumber()));
+
+    super.testSubject.setPayrollConfiguration(customerIdentifier, payrollConfiguration);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PUT_CONFIGURATION, customerIdentifier));
+
+    final PayrollCollectionSheet payrollCollectionSheet = new PayrollCollectionSheet();
+    payrollCollectionSheet.setSourceAccountNumber(RandomStringUtils.randomAlphanumeric(34));
+    final PayrollPayment payrollPayment = new PayrollPayment();
+    payrollPayment.setCustomerIdentifier(customerIdentifier);
+    payrollPayment.setEmployer("ACME, Inc.");
+    payrollPayment.setSalary(BigDecimal.valueOf(1234.56D));
+    payrollCollectionSheet.setPayrollPayments(Lists.newArrayList(payrollPayment));
+
+    final Account sourceAccount = new Account();
+    sourceAccount.setState(Account.State.OPEN.name());
+    Mockito
+        .doAnswer(invocation -> Optional.of(sourceAccount))
+        .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(payrollCollectionSheet.getSourceAccountNumber()));
+
+    Mockito
+        .doAnswer(invocation -> Optional.empty())
+        .when(this.accountingAdaptorSpy).postPayrollPayment(
+        Matchers.any(PayrollCollectionEntity.class),
+        Matchers.refEq(payrollPayment),
+        Matchers.any(PayrollConfiguration.class)
+    );
+
+    super.testSubject.distribute(payrollCollectionSheet);
+  }
+
+  @Test(expected = PayrollPaymentValidationException.class)
+  public void shouldNotDistributePaymentsSourceAccountClosed() throws Exception {
+    final String customerIdentifier = RandomStringUtils.randomAlphanumeric(32);
+    final PayrollConfiguration payrollConfiguration = DomainObjectGenerator.getPayrollConfiguration();
+    this.prepareMocks(customerIdentifier, payrollConfiguration);
+
+    super.testSubject.setPayrollConfiguration(customerIdentifier, payrollConfiguration);
+    Assert.assertTrue(super.eventRecorder.wait(EventConstants.PUT_CONFIGURATION, customerIdentifier));
+
+    final PayrollCollectionSheet payrollCollectionSheet = new PayrollCollectionSheet();
+    payrollCollectionSheet.setSourceAccountNumber(RandomStringUtils.randomAlphanumeric(34));
+    final PayrollPayment payrollPayment = new PayrollPayment();
+    payrollPayment.setCustomerIdentifier(customerIdentifier);
+    payrollPayment.setEmployer("ACME, Inc.");
+    payrollPayment.setSalary(BigDecimal.valueOf(1234.56D));
+    payrollCollectionSheet.setPayrollPayments(Lists.newArrayList(payrollPayment));
+
+    final Account sourceAccount = new Account();
+    sourceAccount.setState(Account.State.CLOSED.name());
+    Mockito
+        .doAnswer(invocation -> Optional.of(sourceAccount))
+        .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(payrollCollectionSheet.getSourceAccountNumber()));
+
+    Mockito
+        .doAnswer(invocation -> Optional.empty())
+        .when(this.accountingAdaptorSpy).postPayrollPayment(
+        Matchers.any(PayrollCollectionEntity.class),
+        Matchers.refEq(payrollPayment),
+        Matchers.any(PayrollConfiguration.class)
+    );
+
+    super.testSubject.distribute(payrollCollectionSheet);
+  }
+
   private void prepareMocks(final String customerIdentifier, final PayrollConfiguration payrollConfiguration)
{
     Mockito
         .doAnswer(invocation -> Optional.of(new Customer()))
         .when(this.customerAdaptorSpy).findCustomer(Matchers.eq(customerIdentifier));
 
+    final Account mainAccount = new Account();
+    mainAccount.setState(Account.State.OPEN.name());
     Mockito
-        .doAnswer(invocation -> Optional.of(new Account()))
+        .doAnswer(invocation -> Optional.of(mainAccount))
         .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(payrollConfiguration.getMainAccountNumber()));
 
-    payrollConfiguration.getPayrollAllocations().forEach(payrollAllocation ->
-        Mockito
-            .doAnswer(invocation -> Optional.of(new Account()))
-            .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(payrollAllocation.getAccountNumber()))
-    );
+    payrollConfiguration.getPayrollAllocations().forEach(payrollAllocation -> {
+      final Account allocatedAccount = new Account();
+      allocatedAccount.setState(Account.State.OPEN.name());
+      Mockito
+          .doAnswer(invocation -> Optional.of(allocatedAccount))
+          .when(this.accountingAdaptorSpy).findAccount(Matchers.eq(payrollAllocation.getAccountNumber()));
+    });
   }
-
 }
diff --git a/service/src/main/java/io/mifos/payroll/service/rest/PayrollDistributionRestController.java
b/service/src/main/java/io/mifos/payroll/service/rest/PayrollDistributionRestController.java
index 7a2a8ea..681c48f 100644
--- a/service/src/main/java/io/mifos/payroll/service/rest/PayrollDistributionRestController.java
+++ b/service/src/main/java/io/mifos/payroll/service/rest/PayrollDistributionRestController.java
@@ -15,6 +15,7 @@
  */
 package io.mifos.payroll.service.rest;
 
+import io.mifos.accounting.api.v1.domain.Account;
 import io.mifos.anubis.annotation.AcceptedTokenType;
 import io.mifos.anubis.annotation.Permittable;
 import io.mifos.anubis.annotation.Permittables;
@@ -23,11 +24,13 @@ import io.mifos.core.lang.ServiceException;
 import io.mifos.payroll.api.v1.PermittableGroupIds;
 import io.mifos.payroll.api.v1.domain.PayrollCollectionHistory;
 import io.mifos.payroll.api.v1.domain.PayrollCollectionSheet;
+import io.mifos.payroll.api.v1.domain.PayrollConfiguration;
 import io.mifos.payroll.api.v1.domain.PayrollPaymentPage;
 import io.mifos.payroll.service.ServiceConstants;
 import io.mifos.payroll.service.internal.command.DistributePayrollCommand;
 import io.mifos.payroll.service.internal.service.PayrollConfigurationService;
 import io.mifos.payroll.service.internal.service.PayrollDistributionService;
+import io.mifos.payroll.service.internal.service.adaptor.AccountingAdaptor;
 import io.mifos.payroll.service.rest.util.PageableBuilder;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -53,17 +56,20 @@ public class PayrollDistributionRestController {
   private final CommandGateway commandGateway;
   private final PayrollDistributionService payrollDistributionService;
   private final PayrollConfigurationService payrollConfigurationService;
+  private final AccountingAdaptor accountingAdaptor;
 
   @Autowired
   public PayrollDistributionRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final
Logger logger,
                                            final CommandGateway commandGateway,
                                            final PayrollDistributionService payrollDistributionService,
-                                           final PayrollConfigurationService payrollConfigurationService)
{
+                                           final PayrollConfigurationService payrollConfigurationService,
+                                           final AccountingAdaptor accountingAdaptor) {
     super();
     this.logger = logger;
     this.commandGateway = commandGateway;
     this.payrollDistributionService = payrollDistributionService;
     this.payrollConfigurationService = payrollConfigurationService;
+    this.accountingAdaptor = accountingAdaptor;
   }
 
   @Permittables({
@@ -81,14 +87,17 @@ public class PayrollDistributionRestController {
   @ResponseBody
   public ResponseEntity<Void> distribute(@RequestBody @Valid final PayrollCollectionSheet
payrollCollectionSheet) {
 
-    this.payrollConfigurationService.findAccount(payrollCollectionSheet.getSourceAccountNumber())
-        .orElseThrow(() -> ServiceException.notFound("Account {0} not available.", payrollCollectionSheet.getSourceAccountNumber()));
+    this.verifyAccount(payrollCollectionSheet.getSourceAccountNumber());
+    payrollCollectionSheet.getPayrollPayments()
+        .forEach(payrollPayment -> {
+          final PayrollConfiguration payrollConfiguration =
+              this.payrollConfigurationService.findPayrollConfiguration(payrollPayment.getCustomerIdentifier())
+                  .orElseThrow(() -> ServiceException.conflict("Payroll configuration
for certain customers not available."));
 
-    if (payrollCollectionSheet.getPayrollPayments()
-        .stream().anyMatch(payrollPayment ->
-              !this.payrollConfigurationService.findPayrollConfiguration(payrollPayment.getCustomerIdentifier()).isPresent()))
{
-      throw ServiceException.conflict("Payroll configuration for certain customers not available.");
-    }
+          this.verifyAccount(payrollConfiguration.getMainAccountNumber());
+          payrollConfiguration.getPayrollAllocations()
+              .forEach(payrollAllocation -> this.verifyAccount(payrollAllocation.getAccountNumber()));
+        });
 
     this.commandGateway.process(new DistributePayrollCommand(payrollCollectionSheet));
 
@@ -138,4 +147,14 @@ public class PayrollDistributionRestController {
     return ResponseEntity.ok(this.payrollDistributionService
         .fetchPayments(identifier, PageableBuilder.create(pageIndex, size, sortColumn, sortDirection)));
   }
+
+  private void verifyAccount(final String accountIdentifier) {
+    final Account account = this.accountingAdaptor.findAccount(accountIdentifier).orElseThrow(
+        () -> ServiceException.conflict("Account {0} not found.")
+    );
+
+    if (!account.getState().equals(Account.State.OPEN.name())) {
+      throw ServiceException.conflict("Account {0} must be open.", accountIdentifier);
+    }
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
myrle@apache.org.

Mime
View raw message