added ability to activate and close product instances
diff --git a/api/src/main/java/io/mifos/deposit/api/v1/EventConstants.java b/api/src/main/java/io/mifos/deposit/api/v1/EventConstants.java
index f6c20a3..81afd39 100644
--- a/api/src/main/java/io/mifos/deposit/api/v1/EventConstants.java
+++ b/api/src/main/java/io/mifos/deposit/api/v1/EventConstants.java
@@ -36,4 +36,11 @@
String SELECTOR_POST_PRODUCT_INSTANCE = SELECTOR_NAME + " = '" + POST_PRODUCT_INSTANCE + "'";
String POST_PRODUCT_INSTANCE_STATE_CHANGE = "post-product-instance-state-change";
String SELECTOR_POST_PRODUCT_INSTANCE_STATE_CHANGE = SELECTOR_NAME + " = '" + POST_PRODUCT_INSTANCE_STATE_CHANGE + "'";
+ String ACTIVATE_PRODUCT_INSTANCE = "activate-process-instance";
+ String SELECTOR_ACTIVATE_PRODUCT_INSTANCE = SELECTOR_NAME + " = '" + ACTIVATE_PRODUCT_INSTANCE + "'";
+ String CLOSE_PRODUCT_INSTANCE = "close-process-instance";
+ String SELECTOR_CLOSE_PRODUCT_INSTANCE = SELECTOR_NAME + " = '" + CLOSE_PRODUCT_INSTANCE + "'";
+
+ String ACTIVATE_PRODUCT_INSTANCE_COMMAND = "ACTIVATE";
+ String CLOSE_PRODUCT_INSTANCE_COMMAND = "CLOSE";
}
diff --git a/api/src/main/java/io/mifos/deposit/api/v1/client/DepositAccountManager.java b/api/src/main/java/io/mifos/deposit/api/v1/client/DepositAccountManager.java
index 2cc93d4..cf34325 100644
--- a/api/src/main/java/io/mifos/deposit/api/v1/client/DepositAccountManager.java
+++ b/api/src/main/java/io/mifos/deposit/api/v1/client/DepositAccountManager.java
@@ -104,7 +104,7 @@
@RequestBody @Valid final ProductDefinitionCommand command);
@RequestMapping(
- value = "/{identifier}/commands",
+ value = "/definitions/{identifier}/commands",
method = RequestMethod.GET,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.ALL_VALUE
@@ -126,4 +126,13 @@
produces = MediaType.ALL_VALUE
)
List<ProductInstance> fetchProductInstances(@RequestParam(value = "customer", required = true) final String customer);
+
+ @RequestMapping(
+ value = "/instances/{identifier}",
+ method = RequestMethod.POST,
+ consumes = MediaType.APPLICATION_JSON_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE
+ )
+ void postProductInstanceCommand(@PathVariable("identifier") final String identifier,
+ @RequestParam(value = "command", required = true) final String command);
}
diff --git a/component-test/src/main/java/io/mifos/deposit/TestProductInstance.java b/component-test/src/main/java/io/mifos/deposit/TestProductInstance.java
index 34b4682..e11817a 100644
--- a/component-test/src/main/java/io/mifos/deposit/TestProductInstance.java
+++ b/component-test/src/main/java/io/mifos/deposit/TestProductInstance.java
@@ -54,4 +54,64 @@
Assert.assertEquals(productDefinition.getEquityLedgerIdentifier() + "." + customerIdentifier + ".00001",
foundProductInstance.getAccountIdentifier());
}
+
+ @Test
+ public void shouldActivateProductInstance() throws Exception {
+ final String customerIdentifier = "08154712";
+ final ProductDefinition productDefinition = Fixture.productDefinition();
+
+ super.depositAccountManager.create(productDefinition);
+
+ super.eventRecorder.wait(EventConstants.POST_PRODUCT_DEFINITION, productDefinition.getIdentifier());
+
+ final ProductInstance productInstance = new ProductInstance();
+ productInstance.setProductIdentifier(productDefinition.getIdentifier());
+ productInstance.setCustomerIdentifier(customerIdentifier);
+
+ super.depositAccountManager.create(productInstance);
+
+ super.eventRecorder.wait(EventConstants.POST_PRODUCT_INSTANCE, customerIdentifier);
+
+ final List<ProductInstance> productInstances = super.depositAccountManager.findProductInstances(productDefinition.getIdentifier());
+ Assert.assertNotNull(productInstances);
+ Assert.assertEquals(1, productInstances.size());
+ final ProductInstance foundProductInstance = productInstances.get(0);
+
+ super.depositAccountManager.postProductInstanceCommand(
+ foundProductInstance.getAccountIdentifier(), EventConstants.ACTIVATE_PRODUCT_INSTANCE_COMMAND);
+
+ Assert.assertTrue(
+ super.eventRecorder.wait(EventConstants.ACTIVATE_PRODUCT_INSTANCE,
+ foundProductInstance.getAccountIdentifier()));
+ }
+
+ @Test
+ public void shouldCloseProductInstance() throws Exception {
+ final String customerIdentifier = "08154713";
+ final ProductDefinition productDefinition = Fixture.productDefinition();
+
+ super.depositAccountManager.create(productDefinition);
+
+ super.eventRecorder.wait(EventConstants.POST_PRODUCT_DEFINITION, productDefinition.getIdentifier());
+
+ final ProductInstance productInstance = new ProductInstance();
+ productInstance.setProductIdentifier(productDefinition.getIdentifier());
+ productInstance.setCustomerIdentifier(customerIdentifier);
+
+ super.depositAccountManager.create(productInstance);
+
+ super.eventRecorder.wait(EventConstants.POST_PRODUCT_INSTANCE, customerIdentifier);
+
+ final List<ProductInstance> productInstances = super.depositAccountManager.findProductInstances(productDefinition.getIdentifier());
+ Assert.assertNotNull(productInstances);
+ Assert.assertEquals(1, productInstances.size());
+ final ProductInstance foundProductInstance = productInstances.get(0);
+
+ super.depositAccountManager.postProductInstanceCommand(
+ foundProductInstance.getAccountIdentifier(), EventConstants.CLOSE_PRODUCT_INSTANCE_COMMAND);
+
+ Assert.assertTrue(
+ super.eventRecorder.wait(EventConstants.CLOSE_PRODUCT_INSTANCE,
+ foundProductInstance.getAccountIdentifier()));
+ }
}
diff --git a/component-test/src/main/java/io/mifos/deposit/listener/ProductInstanceEventListener.java b/component-test/src/main/java/io/mifos/deposit/listener/ProductInstanceEventListener.java
index 94b36c9..2cdf9e3 100644
--- a/component-test/src/main/java/io/mifos/deposit/listener/ProductInstanceEventListener.java
+++ b/component-test/src/main/java/io/mifos/deposit/listener/ProductInstanceEventListener.java
@@ -50,4 +50,26 @@
this.logger.debug("Product instance created.");
this.eventRecorder.event(tenant, EventConstants.POST_PRODUCT_INSTANCE, payload, String.class);
}
+
+ @JmsListener(
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_ACTIVATE_PRODUCT_INSTANCE,
+ subscription = EventConstants.DESTINATION
+ )
+ public void onActivateInstance(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.logger.debug("Product instance created.");
+ this.eventRecorder.event(tenant, EventConstants.ACTIVATE_PRODUCT_INSTANCE, payload, String.class);
+ }
+
+ @JmsListener(
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_CLOSE_PRODUCT_INSTANCE,
+ subscription = EventConstants.DESTINATION
+ )
+ public void onCloseInstance(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.logger.debug("Product instance created.");
+ this.eventRecorder.event(tenant, EventConstants.CLOSE_PRODUCT_INSTANCE, payload, String.class);
+ }
}
diff --git a/service/src/main/java/io/mifos/deposit/service/internal/command/ActivateProductInstanceCommand.java b/service/src/main/java/io/mifos/deposit/service/internal/command/ActivateProductInstanceCommand.java
new file mode 100644
index 0000000..66ad60b
--- /dev/null
+++ b/service/src/main/java/io/mifos/deposit/service/internal/command/ActivateProductInstanceCommand.java
@@ -0,0 +1,29 @@
+/*
+ * 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.deposit.service.internal.command;
+
+public class ActivateProductInstanceCommand {
+ private final String identifier;
+
+ public ActivateProductInstanceCommand(final String identifier) {
+ super();
+ this.identifier = identifier;
+ }
+
+ public String identifier() {
+ return this.identifier;
+ }
+}
diff --git a/service/src/main/java/io/mifos/deposit/service/internal/command/CloseProductInstanceCommand.java b/service/src/main/java/io/mifos/deposit/service/internal/command/CloseProductInstanceCommand.java
new file mode 100644
index 0000000..8bbb03a
--- /dev/null
+++ b/service/src/main/java/io/mifos/deposit/service/internal/command/CloseProductInstanceCommand.java
@@ -0,0 +1,29 @@
+/*
+ * 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.deposit.service.internal.command;
+
+public class CloseProductInstanceCommand {
+ private final String identifier;
+
+ public CloseProductInstanceCommand(final String identifier) {
+ super();
+ this.identifier = identifier;
+ }
+
+ public String identifier() {
+ return this.identifier;
+ }
+}
diff --git a/service/src/main/java/io/mifos/deposit/service/internal/command/handler/ProductInstanceAggregate.java b/service/src/main/java/io/mifos/deposit/service/internal/command/handler/ProductInstanceAggregate.java
index 4612e0e..124253b 100644
--- a/service/src/main/java/io/mifos/deposit/service/internal/command/handler/ProductInstanceAggregate.java
+++ b/service/src/main/java/io/mifos/deposit/service/internal/command/handler/ProductInstanceAggregate.java
@@ -22,6 +22,8 @@
import io.mifos.deposit.api.v1.EventConstants;
import io.mifos.deposit.api.v1.instance.domain.ProductInstance;
import io.mifos.deposit.service.ServiceConstants;
+import io.mifos.deposit.service.internal.command.ActivateProductInstanceCommand;
+import io.mifos.deposit.service.internal.command.CloseProductInstanceCommand;
import io.mifos.deposit.service.internal.command.CreateProductInstanceCommand;
import io.mifos.deposit.service.internal.mapper.ProductInstanceMapper;
import io.mifos.deposit.service.internal.repository.ProductDefinitionEntity;
@@ -29,7 +31,6 @@
import io.mifos.deposit.service.internal.repository.ProductInstanceEntity;
import io.mifos.deposit.service.internal.repository.ProductInstanceRepository;
import io.mifos.deposit.service.internal.service.helper.AccountingService;
-import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -82,10 +83,10 @@
final StringBuilder stringBuilder = new StringBuilder();
final String accountNumber = stringBuilder
- .append(productDefinitionEntity.getEquityLedgerIdentifier())
- .append(".")
.append(productInstance.getCustomerIdentifier())
.append(".")
+ .append(productDefinitionEntity.getEquityLedgerIdentifier())
+ .append(".")
.append(String.format("%05d", accountSuffix))
.toString();
@@ -103,4 +104,50 @@
this.productInstanceRepository.save(productInstanceEntity);
return productInstance.getCustomerIdentifier();
}
+
+ @Transactional
+ @CommandHandler
+ @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.ACTIVATE_PRODUCT_INSTANCE)
+ public String process(final ActivateProductInstanceCommand activateProductInstanceCommand) {
+ final String accountIdentifier = activateProductInstanceCommand.identifier();
+ final Optional<ProductInstanceEntity> optionalProductInstance =
+ this.productInstanceRepository.findByAccountIdentifier(accountIdentifier);
+
+ if (optionalProductInstance.isPresent()) {
+ final ProductInstanceEntity productInstanceEntity = optionalProductInstance.get();
+ productInstanceEntity.setState("ACTIVE");
+ productInstanceEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
+ productInstanceEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
+ this.productInstanceRepository.save(productInstanceEntity);
+
+ return accountIdentifier;
+ } else {
+ this.logger.warn("Product instance for account {} not found.", accountIdentifier);
+ }
+
+ return null;
+ }
+
+ @Transactional
+ @CommandHandler
+ @EventEmitter(selectorName = EventConstants.SELECTOR_NAME, selectorValue = EventConstants.CLOSE_PRODUCT_INSTANCE)
+ public String process(final CloseProductInstanceCommand closeProductInstanceCommand) {
+ final String accountIdentifier = closeProductInstanceCommand.identifier();
+ final Optional<ProductInstanceEntity> optionalProductInstance =
+ this.productInstanceRepository.findByAccountIdentifier(accountIdentifier);
+
+ if (optionalProductInstance.isPresent()) {
+ final ProductInstanceEntity productInstanceEntity = optionalProductInstance.get();
+ productInstanceEntity.setState("CLOSED");
+ productInstanceEntity.setLastModifiedBy(UserContextHolder.checkedGetUser());
+ productInstanceEntity.setLastModifiedOn(LocalDateTime.now(Clock.systemUTC()));
+ this.productInstanceRepository.save(productInstanceEntity);
+
+ return accountIdentifier;
+ } else {
+ this.logger.warn("Product instance for account {} not found.", accountIdentifier);
+ }
+
+ return null;
+ }
}
diff --git a/service/src/main/java/io/mifos/deposit/service/internal/repository/ProductInstanceRepository.java b/service/src/main/java/io/mifos/deposit/service/internal/repository/ProductInstanceRepository.java
index 930986d..0091204 100644
--- a/service/src/main/java/io/mifos/deposit/service/internal/repository/ProductInstanceRepository.java
+++ b/service/src/main/java/io/mifos/deposit/service/internal/repository/ProductInstanceRepository.java
@@ -18,6 +18,7 @@
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
+import java.util.Optional;
public interface ProductInstanceRepository extends JpaRepository<ProductInstanceEntity, Long> {
@@ -27,4 +28,6 @@
List<ProductInstanceEntity> findByProductDefinitionAndCustomerIdentifier(
final ProductDefinitionEntity productDefinitionEntity, final String customerIdentifier);
+
+ Optional<ProductInstanceEntity> findByAccountIdentifier(final String identifier);
}
diff --git a/service/src/main/java/io/mifos/deposit/service/internal/service/ProductInstanceService.java b/service/src/main/java/io/mifos/deposit/service/internal/service/ProductInstanceService.java
index e16698a..53067ed 100644
--- a/service/src/main/java/io/mifos/deposit/service/internal/service/ProductInstanceService.java
+++ b/service/src/main/java/io/mifos/deposit/service/internal/service/ProductInstanceService.java
@@ -65,4 +65,8 @@
.collect(Collectors.toList())).orElseGet(Collections::emptyList);
}
+
+ public Optional<ProductInstance> findByAccountIdentifier(final String identifier) {
+ return this.productInstanceRepository.findByAccountIdentifier(identifier).map(ProductInstanceMapper::map);
+ }
}
diff --git a/service/src/main/java/io/mifos/deposit/service/internal/service/helper/AccountingService.java b/service/src/main/java/io/mifos/deposit/service/internal/service/helper/AccountingService.java
index 1d1f1dd..3c68e87 100644
--- a/service/src/main/java/io/mifos/deposit/service/internal/service/helper/AccountingService.java
+++ b/service/src/main/java/io/mifos/deposit/service/internal/service/helper/AccountingService.java
@@ -1,3 +1,18 @@
+/*
+ * 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.deposit.service.internal.service.helper;
import io.mifos.accounting.api.v1.client.LedgerManager;
diff --git a/service/src/main/java/io/mifos/deposit/service/rest/ProductInstanceRestController.java b/service/src/main/java/io/mifos/deposit/service/rest/ProductInstanceRestController.java
index 7006b39..59f4a25 100644
--- a/service/src/main/java/io/mifos/deposit/service/rest/ProductInstanceRestController.java
+++ b/service/src/main/java/io/mifos/deposit/service/rest/ProductInstanceRestController.java
@@ -18,9 +18,13 @@
import io.mifos.anubis.annotation.AcceptedTokenType;
import io.mifos.anubis.annotation.Permittable;
import io.mifos.core.command.gateway.CommandGateway;
+import io.mifos.core.lang.ServiceException;
+import io.mifos.deposit.api.v1.EventConstants;
import io.mifos.deposit.api.v1.PermittableGroupIds;
import io.mifos.deposit.api.v1.instance.domain.ProductInstance;
import io.mifos.deposit.service.ServiceConstants;
+import io.mifos.deposit.service.internal.command.ActivateProductInstanceCommand;
+import io.mifos.deposit.service.internal.command.CloseProductInstanceCommand;
import io.mifos.deposit.service.internal.command.CreateProductInstanceCommand;
import io.mifos.deposit.service.internal.service.ProductInstanceService;
import org.slf4j.Logger;
@@ -28,6 +32,7 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@@ -80,4 +85,32 @@
public ResponseEntity<List<ProductInstance>> fetchProductInstances(@RequestParam(value = "customer", required = true) final String customerIdentifier) {
return ResponseEntity.ok(this.productInstanceService.findByCustomer(customerIdentifier));
}
+
+ @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.INSTANCE_MANAGEMENT)
+ @RequestMapping(
+ value = "/{identifier}",
+ method = RequestMethod.POST,
+ consumes = MediaType.APPLICATION_JSON_VALUE,
+ produces = MediaType.APPLICATION_JSON_VALUE
+ )
+ @ResponseBody
+ ResponseEntity<Void> postProductInstanceCommand(@PathVariable("identifier") final String identifier,
+ @RequestParam(value = "command", required = true) final String command) {
+ if (!this.productInstanceService.findByAccountIdentifier(identifier).isPresent()) {
+ throw ServiceException.notFound("Product instance {0} not found.", identifier);
+ }
+
+ switch (command.toUpperCase()) {
+ case EventConstants.ACTIVATE_PRODUCT_INSTANCE_COMMAND:
+ this.commandGateway.process(new ActivateProductInstanceCommand(identifier));
+ break;
+ case EventConstants.CLOSE_PRODUCT_INSTANCE_COMMAND:
+ this.commandGateway.process(new CloseProductInstanceCommand(identifier));
+ break;
+ default:
+ throw ServiceException.badRequest("Unsupported command {0}", command);
+ }
+
+ return ResponseEntity.accepted().build();
+ }
}