You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ra...@apache.org on 2016/11/14 14:06:08 UTC
[06/14] incubator-fineract git commit: SMS Campaign feature
implementation
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageAssembler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageAssembler.java
index 32a56e1..695edfb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageAssembler.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageAssembler.java
@@ -18,6 +18,9 @@
*/
package org.apache.fineract.infrastructure.sms.domain;
+import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign;
+import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaignRepository;
+import org.apache.fineract.infrastructure.campaigns.sms.exception.SmsCampaignNotFound;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.sms.SmsApiConstants;
@@ -40,17 +43,19 @@ public class SmsMessageAssembler {
private final GroupRepositoryWrapper groupRepository;
private final ClientRepositoryWrapper clientRepository;
private final StaffRepositoryWrapper staffRepository;
+ private final SmsCampaignRepository smsCampaignRepository;
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public SmsMessageAssembler(final SmsMessageRepository smsMessageRepository, final GroupRepositoryWrapper groupRepositoryWrapper,
final ClientRepositoryWrapper clientRepository, final StaffRepositoryWrapper staffRepository,
- final FromJsonHelper fromApiJsonHelper) {
+ final FromJsonHelper fromApiJsonHelper, final SmsCampaignRepository smsCampaignRepository) {
this.smsMessageRepository = smsMessageRepository;
this.groupRepository = groupRepositoryWrapper;
this.clientRepository = clientRepository;
this.staffRepository = staffRepository;
this.fromApiJsonHelper = fromApiJsonHelper;
+ this.smsCampaignRepository = smsCampaignRepository;
}
public SmsMessage assembleFromJson(final JsonCommand command) {
@@ -58,13 +63,20 @@ public class SmsMessageAssembler {
final JsonElement element = command.parsedJson();
String mobileNo = null;
-
Group group = null;
+ Long externalId = null;
if (this.fromApiJsonHelper.parameterExists(SmsApiConstants.groupIdParamName, element)) {
final Long groupId = this.fromApiJsonHelper.extractLongNamed(SmsApiConstants.groupIdParamName, element);
group = this.groupRepository.findOneWithNotFoundDetection(groupId);
}
+ SmsCampaign smsCampaign = null;
+ if (this.fromApiJsonHelper.parameterExists(SmsApiConstants.campaignIdParamName, element)) {
+ final Long campaignId = this.fromApiJsonHelper.extractLongNamed(SmsApiConstants.campaignIdParamName, element);
+ smsCampaign = this.smsCampaignRepository.findOne(campaignId);
+ if (smsCampaign == null) { throw new SmsCampaignNotFound(campaignId); }
+ }
+
Client client = null;
if (this.fromApiJsonHelper.parameterExists(SmsApiConstants.clientIdParamName, element)) {
final Long clientId = this.fromApiJsonHelper.extractLongNamed(SmsApiConstants.clientIdParamName, element);
@@ -81,7 +93,7 @@ public class SmsMessageAssembler {
final String message = this.fromApiJsonHelper.extractStringNamed(SmsApiConstants.messageParamName, element);
- return SmsMessage.pendingSms(group, client, staff, message, mobileNo);
+ return SmsMessage.pendingSms(externalId, group, client, staff, message, mobileNo, smsCampaign);
}
public SmsMessage assembleFromResourceId(final Long resourceId) {
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageRepository.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageRepository.java
index 4d9768a..9dadb59 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageRepository.java
@@ -18,9 +18,12 @@
*/
package org.apache.fineract.infrastructure.sms.domain;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface SmsMessageRepository extends JpaRepository<SmsMessage, Long>, JpaSpecificationExecutor<SmsMessage> {
- // no extra behaviour
+
+ Page<SmsMessage> findByStatusType(final Integer status, Pageable pageable);
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageStatusType.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageStatusType.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageStatusType.java
index 72dce38..a97c2c6 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageStatusType.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/domain/SmsMessageStatusType.java
@@ -22,6 +22,7 @@ public enum SmsMessageStatusType {
INVALID(0, "smsMessageStatusType.invalid"), //
PENDING(100, "smsMessageStatusType.pending"), //
+ WAITING_FOR_DELIVERY_REPORT(150, "smsMessageStatusType.waitingForDeliveryReport"),
SENT(200, "smsMessageStatusType.sent"), //
DELIVERED(300, "smsMessageStatusType.delivered"), //
FAILED(400, "smsMessageStatusType.failed");
@@ -36,6 +37,9 @@ public enum SmsMessageStatusType {
case 100:
enumeration = SmsMessageStatusType.PENDING;
break;
+ case 150:
+ enumeration = SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT;
+ break;
case 200:
enumeration = SmsMessageStatusType.SENT;
break;
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/exception/SmsCountryCodeNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/exception/SmsCountryCodeNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/exception/SmsCountryCodeNotFoundException.java
new file mode 100644
index 0000000..bfdbaad
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/exception/SmsCountryCodeNotFoundException.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fineract.infrastructure.sms.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+public class SmsCountryCodeNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+ public SmsCountryCodeNotFoundException() {
+ super("error.msg.sms.country.code.not.found", "SMS country code does not exist");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobService.java
new file mode 100644
index 0000000..8d3e545
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobService.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fineract.infrastructure.sms.scheduler;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessage;
+
+/**
+ * Scheduled Job service interface for SMS message
+ **/
+public interface SmsMessageScheduledJobService {
+
+ /**
+ * sends a batch of SMS messages to the SMS gateway
+ **/
+ public void sendMessagesToGateway();
+
+ /**
+ * sends triggered batch SMS messages to SMS gateway
+ * @param smsDataMap
+ */
+ public void sendTriggeredMessages(Map<SmsCampaign, Collection<SmsMessage>> smsDataMap);
+
+ /**
+ * get delivery report from the SMS gateway
+ **/
+ public void getDeliveryReports();
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobServiceImpl.java
new file mode 100644
index 0000000..3e23a10
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/scheduler/SmsMessageScheduledJobServiceImpl.java
@@ -0,0 +1,295 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fineract.infrastructure.sms.scheduler;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.fineract.infrastructure.campaigns.helper.SmsConfigUtils;
+import org.apache.fineract.infrastructure.campaigns.sms.constants.SmsCampaignConstants;
+import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign;
+import org.apache.fineract.infrastructure.campaigns.sms.exception.ConnectionFailureException;
+import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.infrastructure.jobs.annotation.CronTarget;
+import org.apache.fineract.infrastructure.jobs.service.JobName;
+import org.apache.fineract.infrastructure.sms.data.SmsMessageApiQueueResourceData;
+import org.apache.fineract.infrastructure.sms.data.SmsMessageDeliveryReportData;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessage;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessageRepository;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessageStatusType;
+import org.apache.fineract.infrastructure.sms.service.SmsReadPlatformService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.client.RestTemplate;
+
+import com.google.gson.Gson;
+
+/**
+ * Scheduled job services that send SMS messages and get delivery reports for
+ * the sent SMS messages
+ **/
+@Service
+public class SmsMessageScheduledJobServiceImpl implements SmsMessageScheduledJobService {
+
+ private final SmsMessageRepository smsMessageRepository;
+ private final SmsReadPlatformService smsReadPlatformService;
+ private static final Logger logger = LoggerFactory.getLogger(SmsMessageScheduledJobServiceImpl.class);
+ private final RestTemplate restTemplate = new RestTemplate();
+ private ExecutorService genericExecutorService ;
+ private ExecutorService triggeredExecutorService ;
+ private final SmsConfigUtils smsConfigUtils ;
+
+
+ /**
+ * SmsMessageScheduledJobServiceImpl constructor
+ **/
+ @Autowired
+ public SmsMessageScheduledJobServiceImpl(SmsMessageRepository smsMessageRepository, SmsReadPlatformService smsReadPlatformService,
+ final SmsConfigUtils smsConfigUtils) {
+ this.smsMessageRepository = smsMessageRepository;
+ this.smsReadPlatformService = smsReadPlatformService;
+ this.smsConfigUtils = smsConfigUtils ;
+ }
+
+ @PostConstruct
+ public void initializeExecutorService() {
+ genericExecutorService = Executors.newSingleThreadExecutor();
+ triggeredExecutorService = Executors.newSingleThreadExecutor() ;
+ }
+
+ /**
+ * Send batches of SMS messages to the SMS gateway (or intermediate gateway)
+ **/
+ @Override
+ @Transactional
+ @CronTarget(jobName = JobName.SEND_MESSAGES_TO_SMS_GATEWAY)
+ public void sendMessagesToGateway() {
+ Integer pageLimit = 200;
+ Integer page = 0;
+ int totalRecords = 0;
+ do {
+ PageRequest pageRequest = new PageRequest(0, pageLimit);
+ org.springframework.data.domain.Page<SmsMessage> pendingMessages = this.smsMessageRepository.findByStatusType(
+ SmsMessageStatusType.PENDING.getValue(), pageRequest);
+ List<SmsMessage> toSaveMessages = new ArrayList<>() ;
+ try {
+
+ if (pendingMessages.getContent().size() > 0) {
+ final String tenantIdentifier = ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+ Iterator<SmsMessage> pendingMessageIterator = pendingMessages.iterator();
+ Collection<SmsMessageApiQueueResourceData> apiQueueResourceDatas = new ArrayList<>();
+ while (pendingMessageIterator.hasNext()) {
+ SmsMessage smsData = pendingMessageIterator.next();
+
+ SmsMessageApiQueueResourceData apiQueueResourceData = SmsMessageApiQueueResourceData.instance(smsData.getId(),
+ tenantIdentifier, null, null, smsData.getMobileNo(), smsData.getMessage(), smsData.getSmsCampaign()
+ .getProviderId());
+ apiQueueResourceDatas.add(apiQueueResourceData);
+ smsData.setStatusType(SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT.getValue());
+ toSaveMessages.add(smsData) ;
+ }
+ this.smsMessageRepository.save(toSaveMessages);
+ this.smsMessageRepository.flush();
+ this.genericExecutorService.execute(new SmsTask(ThreadLocalContextUtil.getTenant(), apiQueueResourceDatas));
+
+// new MyThread(ThreadLocalContextUtil.getTenant(), apiQueueResourceDatas).start();
+ }
+ } catch (Exception e) {
+ throw new ConnectionFailureException(SmsCampaignConstants.SMS);
+ }
+ page ++;
+ totalRecords = pendingMessages.getTotalPages();
+ } while (page < totalRecords);
+ }
+
+ class SmsTask implements Runnable, ApplicationListener<ContextClosedEvent> {
+
+ private final FineractPlatformTenant tenant;
+ private final Collection<SmsMessageApiQueueResourceData> apiQueueResourceDatas;
+
+ public SmsTask(final FineractPlatformTenant tenant, final Collection<SmsMessageApiQueueResourceData> apiQueueResourceDatas) {
+ this.tenant = tenant;
+ this.apiQueueResourceDatas = apiQueueResourceDatas;
+ }
+
+ @Override
+ public void run() {
+ ThreadLocalContextUtil.setTenant(tenant);
+ connectAndSendToIntermediateServer(tenant.getTenantIdentifier(), apiQueueResourceDatas);
+ }
+
+ @Override
+ public void onApplicationEvent(ContextClosedEvent event) {
+ genericExecutorService.shutdown();
+ logger.info("Shutting down the ExecutorService");
+ }
+ }
+
+ private void connectAndSendToIntermediateServer(String tenantIdentifier,
+ Collection<SmsMessageApiQueueResourceData> apiQueueResourceDatas) {
+ Map<String, Object> hostConfig = this.smsConfigUtils.getMessageGateWayRequestURI("sms", SmsMessageApiQueueResourceData.toJsonString(apiQueueResourceDatas)) ;
+ URI uri = (URI)hostConfig.get("uri") ;
+ HttpEntity<?> entity = (HttpEntity<?>)hostConfig.get("entity") ;
+ ResponseEntity<String> responseOne = restTemplate.exchange(uri, HttpMethod.POST, entity,
+ new ParameterizedTypeReference<String>() {});
+ if (responseOne != null) {
+// String smsResponse = responseOne.getBody();
+ if (!responseOne.getStatusCode().equals(HttpStatus.ACCEPTED)) {
+ System.out.println(responseOne.getStatusCode().name());
+ throw new ConnectionFailureException(SmsCampaignConstants.SMS);
+ }
+ }
+ }
+
+ @Override
+ public void sendTriggeredMessages(Map<SmsCampaign, Collection<SmsMessage>> smsDataMap) {
+ try {
+ if (!smsDataMap.isEmpty()) {
+ for (Entry<SmsCampaign, Collection<SmsMessage>> entry : smsDataMap.entrySet()) {
+ Iterator<SmsMessage> smsMessageIterator = entry.getValue().iterator();
+ Collection<SmsMessageApiQueueResourceData> apiQueueResourceDatas = new ArrayList<>();
+ StringBuilder request = new StringBuilder();
+ while (smsMessageIterator.hasNext()) {
+ SmsMessage smsMessage = smsMessageIterator.next();
+ SmsMessageApiQueueResourceData apiQueueResourceData = SmsMessageApiQueueResourceData.instance(smsMessage.getId(),
+ null, null, null, smsMessage.getMobileNo(), smsMessage.getMessage(), entry.getKey().getProviderId());
+ apiQueueResourceDatas.add(apiQueueResourceData);
+ smsMessage.setStatusType(SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT.getValue());
+ }
+ this.smsMessageRepository.save(entry.getValue()) ;
+ request.append(SmsMessageApiQueueResourceData.toJsonString(apiQueueResourceDatas));
+ logger.info("Sending triggered SMS with request - " + request.toString());
+ this.triggeredExecutorService.execute(new SmsTask(ThreadLocalContextUtil.getTenant(), apiQueueResourceDatas));
+ }
+ }
+ } catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * get SMS message delivery reports from the SMS gateway (or intermediate
+ * gateway)
+ **/
+ @Override
+ @Transactional
+ @CronTarget(jobName = JobName.GET_DELIVERY_REPORTS_FROM_SMS_GATEWAY)
+ public void getDeliveryReports() {
+ int page = 0;
+ int totalRecords = 0;
+ Integer limit = 200;
+ do {
+ Page<Long> smsMessageInternalIds = this.smsReadPlatformService.retrieveAllWaitingForDeliveryReport(limit);
+ // only proceed if there are sms message with status type enum 300
+ try {
+
+ if (smsMessageInternalIds.getPageItems().size() > 0) {
+ // make request
+ Map<String, Object> hostConfig = this.smsConfigUtils.getMessageGateWayRequestURI("sms", new Gson().toJson(smsMessageInternalIds.getPageItems())) ;
+ URI uri = (URI)hostConfig.get("uri") ;
+ HttpEntity<?> entity = (HttpEntity<?>)hostConfig.get("entity") ;
+ ResponseEntity<Collection<SmsMessageDeliveryReportData>> responseOne = restTemplate.exchange(uri, HttpMethod.POST, entity,
+ new ParameterizedTypeReference<Collection<SmsMessageDeliveryReportData>>() {});
+
+ Collection<SmsMessageDeliveryReportData> smsMessageDeliveryReportDatas = responseOne.getBody();
+ Iterator<SmsMessageDeliveryReportData> responseReportIterator = smsMessageDeliveryReportDatas.iterator();
+ while (responseReportIterator.hasNext()) {
+ SmsMessageDeliveryReportData smsMessageDeliveryReportData = responseReportIterator.next();
+ Integer deliveryStatus = smsMessageDeliveryReportData.getDeliveryStatus();
+
+ if (!smsMessageDeliveryReportData.getHasError()
+ && (deliveryStatus != 100)) {
+ SmsMessage smsMessage = this.smsMessageRepository.findOne(smsMessageDeliveryReportData.getId());
+ Integer statusType = smsMessage.getStatusType();
+ boolean statusChanged = false;
+
+ switch (deliveryStatus) {
+ case 0:
+ statusType = SmsMessageStatusType.INVALID.getValue();
+ break;
+ case 150:
+ statusType = SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT.getValue();
+ break;
+ case 200:
+ statusType = SmsMessageStatusType.SENT.getValue();
+ break;
+ case 300:
+ statusType = SmsMessageStatusType.DELIVERED.getValue();
+ break;
+
+ case 400:
+ statusType = SmsMessageStatusType.FAILED.getValue();
+ break;
+
+ default:
+ statusType = smsMessage.getStatusType();
+ break;
+ }
+
+ statusChanged = !statusType.equals(smsMessage.getStatusType());
+
+ // update the status Type enum
+ smsMessage.setStatusType(statusType);
+
+ // save the SmsMessage entity
+ this.smsMessageRepository.save(smsMessage);
+
+ if (statusChanged) {
+ logger.info("Status of SMS message id: " + smsMessage.getId() + " successfully changed to " + statusType);
+ }
+ }
+ }
+
+ if (smsMessageDeliveryReportDatas.size() > 0) {
+ logger.info(smsMessageDeliveryReportDatas.size() + " "
+ + "delivery report(s) successfully received from the intermediate gateway - sms");
+ }
+ }
+ }
+
+ catch (Exception e) {
+ logger.error(e.getMessage(), e);
+ }
+ page ++;
+ totalRecords = smsMessageInternalIds.getTotalFilteredRecords();
+ } while (page < totalRecords);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformService.java
index db330da..68a9a99 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformService.java
@@ -19,7 +19,11 @@
package org.apache.fineract.infrastructure.sms.service;
import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.sms.data.SmsData;
public interface SmsReadPlatformService {
@@ -27,4 +31,20 @@ public interface SmsReadPlatformService {
Collection<SmsData> retrieveAll();
SmsData retrieveOne(Long resourceId);
+
+ Collection<SmsData> retrieveAllPending(final Long campaignId, final Integer limit);
+
+ Collection<SmsData> retrieveAllSent(Integer limit);
+
+ Collection<SmsData> retrieveAllDelivered(Integer limit);
+
+ Collection<SmsData> retrieveAllFailed(Integer limit);
+
+ Page<SmsData> retrieveSmsByStatus(final Long campaignId, SearchParameters searchParameters, Integer status, Date dateFrom, Date dateTo);
+
+ List<Long> retrieveExternalIdsOfAllSent(Integer limit);
+
+ Page<Long> retrieveAllWaitingForDeliveryReport(Integer limit);
+
+ List<Long> retrieveAllPending(Integer limit);
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformServiceImpl.java
index c4fd088..5ad0eac 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/sms/service/SmsReadPlatformServiceImpl.java
@@ -20,13 +20,22 @@ package org.apache.fineract.infrastructure.sms.service;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Date;
+import java.util.List;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.sms.data.SmsData;
import org.apache.fineract.infrastructure.sms.domain.SmsMessageEnumerations;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessageStatusType;
import org.apache.fineract.infrastructure.sms.exception.SmsNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -39,6 +48,7 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
private final JdbcTemplate jdbcTemplate;
private final SmsMapper smsRowMapper;
+ private final PaginationHelper<SmsData> paginationHelper = new PaginationHelper<>();
@Autowired
public SmsReadPlatformServiceImpl(final RoutingDataSource dataSource) {
@@ -58,8 +68,11 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
sql.append("smo.staff_id as staffId, ");
sql.append("smo.status_enum as statusId, ");
sql.append("smo.mobile_no as mobileNo, ");
- sql.append("smo.message as message ");
- sql.append("from sms_messages_outbound smo");
+ sql.append("smo.message as message, ");
+ sql.append("smc.provider_id as providerId, ");
+ sql.append("smc.campaign_name as campaignName ");
+ sql.append("from sms_messages_outbound smo ");
+ sql.append("join sms_campaign smc on smc.id = smo.campaign_id ");
this.schema = sql.toString();
}
@@ -67,6 +80,10 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
public String schema() {
return this.schema;
}
+
+ public String tableName() {
+ return "sms_messages_outbound";
+ }
@Override
public SmsData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
@@ -82,7 +99,11 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
final Integer statusId = JdbcSupport.getInteger(rs, "statusId");
final EnumOptionData status = SmsMessageEnumerations.status(statusId);
- return SmsData.instance(id, groupId, clientId, staffId, status, mobileNo, message);
+ final Long providerId = JdbcSupport.getLong(rs, "providerId");
+
+ final String campaignName = rs.getString("campaignName");
+
+ return SmsData.instance(id, groupId, clientId, staffId, status, mobileNo, message, providerId, campaignName);
}
}
@@ -104,4 +125,122 @@ public class SmsReadPlatformServiceImpl implements SmsReadPlatformService {
throw new SmsNotFoundException(resourceId);
}
}
+
+ @Override
+ public Collection<SmsData> retrieveAllPending(final Long campaignId, final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum = " + SmsMessageStatusType.PENDING.getValue();
+ if (campaignId != null) {
+ sql += " and smo.campaign_id = " + campaignId;
+ }
+
+ sql += sqlPlusLimit;
+
+ return this.jdbcTemplate.query(sql, this.smsRowMapper, new Object[] {});
+ }
+
+ @Override
+ public Collection<SmsData> retrieveAllSent(final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ final String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum IN (" + SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT.getValue()
+ + "," + SmsMessageStatusType.SENT.getValue() + ")" + sqlPlusLimit;
+
+ return this.jdbcTemplate.query(sql, this.smsRowMapper, new Object[] {});
+ }
+
+ @Override
+ public List<Long> retrieveExternalIdsOfAllSent(final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ final String sql = "select external_id from " + this.smsRowMapper.tableName() + " where status_enum = "
+ + SmsMessageStatusType.SENT.getValue() + sqlPlusLimit;
+
+ return this.jdbcTemplate.queryForList(sql, Long.class);
+ }
+
+ @Override
+ public Page<Long> retrieveAllWaitingForDeliveryReport(final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ final String sql = "select id from " + this.smsRowMapper.tableName() + " where status_enum = "
+ + SmsMessageStatusType.WAITING_FOR_DELIVERY_REPORT.getValue() + sqlPlusLimit;
+ final String sqlCountRows = "SELECT FOUND_ROWS()";
+ return this.paginationHelper.fetchPage(jdbcTemplate, sql, sqlCountRows, Long.class);
+ //(this.jdbcTemplate, sqlCountRows, new Object [] {}, Long.class); this.jdbcTemplate.queryForList(sql, Long.class);
+ }
+
+ @Override
+ public List<Long> retrieveAllPending(final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ final String sql = "select external_id from " + this.smsRowMapper.tableName() + " where status_enum = "
+ + SmsMessageStatusType.PENDING.getValue() + sqlPlusLimit;
+
+ return this.jdbcTemplate.queryForList(sql, Long.class);
+ }
+
+ @Override
+ public Collection<SmsData> retrieveAllDelivered(final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ final String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum = " + SmsMessageStatusType.DELIVERED.getValue()
+ + sqlPlusLimit;
+
+ return this.jdbcTemplate.query(sql, this.smsRowMapper, new Object[] {});
+ }
+
+ @Override
+ public Collection<SmsData> retrieveAllFailed(final Integer limit) {
+ final String sqlPlusLimit = (limit > 0) ? " limit 0, " + limit : "";
+ final String sql = "select " + this.smsRowMapper.schema() + " where smo.status_enum = " + SmsMessageStatusType.FAILED.getValue()
+ + sqlPlusLimit;
+
+ return this.jdbcTemplate.query(sql, this.smsRowMapper, new Object[] {});
+ }
+
+ @Override
+ public Page<SmsData> retrieveSmsByStatus(final Long campaignId, final SearchParameters searchParameters, final Integer status, final Date dateFrom, final Date dateTo) {
+ final StringBuilder sqlBuilder = new StringBuilder(200);
+ final Object[] objectArray = new Object[10];
+ int arrayPos = 0;
+ sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+ sqlBuilder.append(this.smsRowMapper.schema());
+ if (status != null) {
+ sqlBuilder.append(" where smo.campaign_id = ? and smo.status_enum= ? ");
+ objectArray[arrayPos] = campaignId;
+ arrayPos = arrayPos + 1;
+ objectArray[arrayPos] = status;
+ arrayPos = arrayPos + 1;
+ }
+ String fromDateString = null;
+ String toDateString = null;
+ if (dateFrom != null && dateTo != null) {
+ final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+ fromDateString = df.format(dateFrom);
+ toDateString = df.format(dateTo);
+ sqlBuilder.append(" and smo.submittedon_date >= ? and smo.submittedon_date <= ? ");
+ objectArray[arrayPos] = fromDateString;
+ arrayPos = arrayPos + 1;
+
+ objectArray[arrayPos] = toDateString;
+ arrayPos = arrayPos + 1;
+ }
+
+ if (searchParameters.isOrderByRequested()) {
+ sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
+
+ if (searchParameters.isSortOrderProvided()) {
+ sqlBuilder.append(' ').append(searchParameters.getSortOrder());
+ }
+ } else {
+ sqlBuilder.append(" order by smo.submittedon_date, smo.id");
+ }
+
+ if (searchParameters.isLimited()) {
+ sqlBuilder.append(" limit ").append(searchParameters.getLimit());
+ if (searchParameters.isOffset()) {
+ sqlBuilder.append(" offset ").append(searchParameters.getOffset());
+ }
+ }
+ final String sqlCountRows = "SELECT FOUND_ROWS()";
+ final Object[] finalObjectArray = Arrays.copyOf(objectArray, arrayPos);
+ return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray, this.smsRowMapper);
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
index 0530452..5e82970 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/Client.java
@@ -46,6 +46,7 @@ import org.apache.fineract.infrastructure.codes.domain.CodeValue;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.documentmanagement.domain.Image;
@@ -57,7 +58,6 @@ import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.useradministration.domain.AppUser;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
-import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
@Entity
@Table(name = "m_client", uniqueConstraints = { @UniqueConstraint(columnNames = { "account_no" }, name = "account_no_UNIQUE"), //
@@ -1004,4 +1004,10 @@ public final class Client extends AbstractPersistableCustom<Long> {
public void loadLazyCollections() {
this.groups.size() ;
}
+
+ public String getFirstname(){return this.firstname;}
+
+ public String getMiddlename(){return this.middlename;}
+
+ public String getLastname(){return this.lastname;}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
index c8e7266..b7656f8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientTransaction.java
@@ -205,6 +205,10 @@ public class ClientTransaction extends AbstractPersistableCustom<Long> {
return client.getId();
}
+ public Client getClient() {
+ return this.client ;
+ }
+
public Money getAmount() {
return Money.of(getCurrency(), this.amount);
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
index 3c620ab..5db7a02 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.client.service;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@@ -63,6 +64,9 @@ import org.apache.fineract.portfolio.client.exception.ClientHasNoStaffException;
import org.apache.fineract.portfolio.client.exception.ClientMustBePendingToBeDeletedException;
import org.apache.fineract.portfolio.client.exception.InvalidClientSavingProductException;
import org.apache.fineract.portfolio.client.exception.InvalidClientStateTransitionException;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
+import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.portfolio.group.domain.GroupRepository;
import org.apache.fineract.portfolio.group.exception.GroupMemberCountNotInPermissibleRangeException;
@@ -113,13 +117,15 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
private final CommandProcessingService commandProcessingService;
private final ConfigurationDomainService configurationDomainService;
private final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository;
- private final FromJsonHelper fromApiJsonHelper;
- private final ConfigurationReadPlatformService configurationReadPlatformService;
- private final AddressWritePlatformService addressWritePlatformService;
+ private final FromJsonHelper fromApiJsonHelper;
+ private final ConfigurationReadPlatformService configurationReadPlatformService;
+ private final AddressWritePlatformService addressWritePlatformService;
+ private final BusinessEventNotifierService businessEventNotifierService;
@Autowired
public ClientWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
- final ClientRepositoryWrapper clientRepository, final ClientNonPersonRepositoryWrapper clientNonPersonRepository, final OfficeRepositoryWrapper officeRepositoryWrapper, final NoteRepository noteRepository,
+ final ClientRepositoryWrapper clientRepository, final ClientNonPersonRepositoryWrapper clientNonPersonRepository,
+ final OfficeRepositoryWrapper officeRepositoryWrapper, final NoteRepository noteRepository,
final ClientDataValidator fromApiJsonDeserializer, final AccountNumberGenerator accountNumberGenerator,
final GroupRepository groupRepository, final StaffRepositoryWrapper staffRepository,
final CodeValueRepositoryWrapper codeValueRepository, final LoanRepositoryWrapper loanRepositoryWrapper,
@@ -128,7 +134,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final CommandProcessingService commandProcessingService, final ConfigurationDomainService configurationDomainService,
final AccountNumberFormatRepositoryWrapper accountNumberFormatRepository, final FromJsonHelper fromApiJsonHelper,
final ConfigurationReadPlatformService configurationReadPlatformService,
- final AddressWritePlatformService addressWritePlatformService) {
+ final AddressWritePlatformService addressWritePlatformService, final BusinessEventNotifierService businessEventNotifierService) {
this.context = context;
this.clientRepository = clientRepository;
this.clientNonPersonRepository = clientNonPersonRepository;
@@ -147,8 +153,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.configurationDomainService = configurationDomainService;
this.accountNumberFormatRepository = accountNumberFormatRepository;
this.fromApiJsonHelper = fromApiJsonHelper;
- this.configurationReadPlatformService = configurationReadPlatformService;
- this.addressWritePlatformService = addressWritePlatformService;
+ this.configurationReadPlatformService = configurationReadPlatformService;
+ this.addressWritePlatformService = addressWritePlatformService;
+ this.businessEventNotifierService = businessEventNotifierService;
}
@Transactional
@@ -158,7 +165,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
if (client.isNotPending()) { throw new ClientMustBePendingToBeDeletedException(clientId); }
-
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_DELETE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
final List<Note> relatedNotes = this.noteRepository.findByClientId(clientId);
this.noteRepository.deleteInBatch(relatedNotes);
@@ -167,7 +175,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.clientNonPersonRepository.delete(clientNonPerson);
this.clientRepository.delete(client);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_DELETE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
return new CommandProcessingResultBuilder() //
.withOfficeId(client.officeId()) //
.withClientId(clientId) //
@@ -275,6 +284,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final Client newClient = Client.createNew(currentUser, clientOffice, clientParentGroup, staff, savingsProductId, gender,
clientType, clientClassification, legalFormValue, command);
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_CREATE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, newClient));
boolean rollbackTransaction = false;
if (newClient.isActive()) {
validateParentGroupRulesBeforeClientActivation(newClient);
@@ -306,7 +317,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.addressWritePlatformService.addNewClientAddress(newClient, command);
}
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_CREATE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, newClient));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(clientOffice.getId()) //
@@ -523,7 +535,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId, true);
validateParentGroupRulesBeforeClientActivation(client);
-
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_ACTIVATE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
final Locale locale = command.extractLocale();
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
final LocalDate activationDate = command.localDateValueOfParameterNamed("activationDate");
@@ -532,7 +545,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
client.activate(currentUser, fmt, activationDate);
CommandProcessingResult result = openSavingsAccount(client, fmt);
this.clientRepository.saveAndFlush(client);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_ACTIVATE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.officeId()) //
@@ -609,7 +623,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.fromApiJsonDeserializer.validateForAssignStaff(command.json());
final Client clientForUpdate = this.clientRepository.findOneWithNotFoundDetection(clientId);
-
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_ASSIGN_STAFF,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, clientForUpdate));
Staff staff = null;
final Long staffId = command.longValueOfParameterNamed(ClientApiConstants.staffIdParamName);
if (staffId != null) {
@@ -625,7 +640,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.clientRepository.saveAndFlush(clientForUpdate);
actualChanges.put(ClientApiConstants.staffIdParamName, staffId);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_ASSIGN_STAFF,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, clientForUpdate));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(clientForUpdate.officeId()) //
@@ -644,6 +660,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.fromApiJsonDeserializer.validateClose(command);
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_CLOSE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
final LocalDate closureDate = command.localDateValueOfParameterNamed(ClientApiConstants.closureDateParamName);
final Long closureReasonId = command.longValueOfParameterNamed(ClientApiConstants.closureReasonIdParamName);
@@ -689,7 +707,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
client.close(currentUser, closureReason, closureDate.toDate());
this.clientRepository.saveAndFlush(client);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_CLOSE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withClientId(clientId) //
@@ -763,6 +782,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.fromApiJsonDeserializer.validateRejection(command);
final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId);
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_REJECT,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
final LocalDate rejectionDate = command.localDateValueOfParameterNamed(ClientApiConstants.rejectionDateParamName);
final Long rejectionReasonId = command.longValueOfParameterNamed(ClientApiConstants.rejectionReasonIdParamName);
@@ -780,7 +801,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
}
client.reject(currentUser, rejectionReason, rejectionDate.toDate());
this.clientRepository.saveAndFlush(client);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_REJECT,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withClientId(entityId) //
@@ -794,6 +816,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.fromApiJsonDeserializer.validateWithdrawn(command);
final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId);
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_WITHDRAW,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
final LocalDate withdrawalDate = command.localDateValueOfParameterNamed(ClientApiConstants.withdrawalDateParamName);
final Long withdrawalReasonId = command.longValueOfParameterNamed(ClientApiConstants.withdrawalReasonIdParamName);
@@ -811,7 +835,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
}
client.withdraw(currentUser, withdrawalReason, withdrawalDate.toDate());
this.clientRepository.saveAndFlush(client);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_WITHDRAW,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withClientId(entityId) //
@@ -825,6 +850,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.fromApiJsonDeserializer.validateReactivate(command);
final Client client = this.clientRepository.findOneWithNotFoundDetection(entityId);
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.CLIENTS_REACTIVATE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
final LocalDate reactivateDate = command.localDateValueOfParameterNamed(ClientApiConstants.reactivationDateParamName);
if (!client.isClosed()) {
@@ -837,7 +864,8 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
}
client.reActivate(currentUser, reactivateDate.toDate());
this.clientRepository.saveAndFlush(client);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_REACTIVATE,
+ constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withClientId(entityId) //
@@ -899,4 +927,10 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
.withEntityId(entityId) //
.build();
}
+
+ private Map<BUSINESS_ENTITY, Object> constructEntityMap(final BUSINESS_ENTITY entityEvent, Object entity) {
+ Map<BUSINESS_ENTITY, Object> map = new HashMap<>(1);
+ map.put(entityEvent, entity);
+ return map;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
index b5f5258..9532b52 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
@@ -24,15 +24,25 @@ import java.util.Set;
public class BusinessEventNotificationConstants {
public static enum BUSINESS_EVENTS {
- LOAN_APPROVED("loan_approved"), LOAN_UNDO_APPROVAL("loan_undo_approval"), LOAN_UNDO_DISBURSAL("loan_undo_disbursal"), LOAN_UNDO_LASTDISBURSAL("loan_undo_lastdisbursal"),LOAN_UNDO_TRANSACTION(
- "loan_undo_transaction"), LOAN_ADJUST_TRANSACTION("loan_adjust_transaction"), LOAN_MAKE_REPAYMENT(
- "loan_repayment_transaction"), LOAN_WRITTEN_OFF("loan_writtenoff"), LOAN_UNDO_WRITTEN_OFF("loan_undo_writtenoff"), LOAN_DISBURSAL(
- "loan_disbursal"), LOAN_WAIVE_INTEREST("loan_waive_interest"), LOAN_CLOSE("loan_close"), LOAN_CLOSE_AS_RESCHEDULE(
- "loan_close_as_reschedule"), LOAN_ADD_CHARGE("loan_add_charge"), LOAN_UPDATE_CHARGE("loan_update_charge"), LOAN_WAIVE_CHARGE(
- "loan_waive_charge"), LOAN_DELETE_CHARGE("loan_delete_charge"), LOAN_CHARGE_PAYMENT("loan_charge_payment"), LOAN_INITIATE_TRANSFER(
- "loan_initiate_transfer"), LOAN_ACCEPT_TRANSFER("loan_accept_transfer"), LOAN_WITHDRAW_TRANSFER("loan_withdraw_transfer"), LOAN_REJECT_TRANSFER(
- "loan_reject_transfer"), LOAN_REASSIGN_OFFICER("loan_reassign_officer"), LOAN_REMOVE_OFFICER("loan_remove_officer"), LOAN_APPLY_OVERDUE_CHARGE(
- "loan_apply_overdue_charge"), LOAN_INTEREST_RECALCULATION("loan_interest_recalculation"), LOAN_REFUND("loan_refund"), LOAN_FORECLOSURE("loan_foreclosure");
+ LOAN_APPROVED("loan_approved"), LOAN_REJECTED("loan_reject"), LOAN_UNDO_APPROVAL("loan_undo_approval"), LOAN_UNDO_DISBURSAL("loan_undo_disbursal"), LOAN_UNDO_LASTDISBURSAL(
+ "loan_undo_lastdisbursal"), LOAN_UNDO_TRANSACTION("loan_undo_transaction"), LOAN_ADJUST_TRANSACTION(
+ "loan_adjust_transaction"), LOAN_MAKE_REPAYMENT("loan_repayment_transaction"), LOAN_WRITTEN_OFF("loan_writtenoff"), LOAN_UNDO_WRITTEN_OFF(
+ "loan_undo_writtenoff"), LOAN_DISBURSAL("loan_disbursal"), LOAN_WAIVE_INTEREST("loan_waive_interest"), LOAN_CLOSE(
+ "loan_close"), LOAN_CLOSE_AS_RESCHEDULE("loan_close_as_reschedule"), LOAN_ADD_CHARGE("loan_add_charge"), LOAN_UPDATE_CHARGE(
+ "loan_update_charge"), LOAN_WAIVE_CHARGE("loan_waive_charge"), LOAN_DELETE_CHARGE("loan_delete_charge"), LOAN_CHARGE_PAYMENT(
+ "loan_charge_payment"), LOAN_INITIATE_TRANSFER("loan_initiate_transfer"), LOAN_ACCEPT_TRANSFER("loan_accept_transfer"), LOAN_WITHDRAW_TRANSFER(
+ "loan_withdraw_transfer"), LOAN_REJECT_TRANSFER("loan_reject_transfer"), LOAN_REASSIGN_OFFICER("loan_reassign_officer"), LOAN_REMOVE_OFFICER(
+ "loan_remove_officer"), LOAN_APPLY_OVERDUE_CHARGE("loan_apply_overdue_charge"), LOAN_INTEREST_RECALCULATION(
+ "loan_interest_recalculation"), LOAN_REFUND("loan_refund"), LOAN_FORECLOSURE("loan_foreclosure"), SAVINGS_ACTIVATE(
+ "savings_activated"), SAVINGS_ADJUST_TRANSACTION("savings_adjust_transaction"), SAVINGS_APPLY_ANNUAL_FEE(
+ "savings_apply_annual_fee"), SAVINGS_CALCULATE_INTEREST("savings_calculate_interest"), SAVINGS_CLOSE("savings_close"), SAVINGS_POST_INTEREST(
+ "savings_post_interest"), SAVINGS_REJECT("savings_reject"), SAVINGS_DEPOSIT("savings_deposit"), SAVINGS_WITHDRAWAL(
+ "savings_withdrawal"), SAVINGS_UNDO("savings_undo"), SAVINGS_ADD_CHARGE("savings_add_charge"), SAVINGS_WAIVE_CHARGE(
+ "savings_waive_charge"), SAVINGS_PAY_CHARGE("savings_pay_charge"), CLIENTS_ACCEPT_TRANSFER("clients_accept_transfer"), CLIENTS_ACTIVATE(
+ "clients_activate"), CLIENTS_ASSIGN_STAFF("clients_assign_staff"), CLIENTS_CLOSE("clients_close"), CLIENTS_CREATE(
+ "clients_create"), CLIENTS_DELETE("clients_delete"), CLIENTS_PROPOSE_TRANSFER("clients_propose_transfer"), CLIENTS_REACTIVATE(
+ "clients_reactivate"), CLIENTS_REJECT("clients_reject"), CLIENTS_REJECT_TRANSFER("clients_reject_transfer"), CLIENTS_WITHDRAW(
+ "clients_withdraw"), CLIENTS_WITHDRAW_TRANSFER("clients_withdraw_transfer");
private final String value;
@@ -58,7 +68,7 @@ public class BusinessEventNotificationConstants {
public static enum BUSINESS_ENTITY {
LOAN("loan"), LOAN_TRANSACTION("loan_transaction"), LOAN_CHARGE("loan_charge"), LOAN_ADJUSTED_TRANSACTION(
- "loan_adjusted_transaction");
+ "loan_adjusted_transaction"), SAVING("saving"), CLIENT("client"), SAVINGS_TRANSACTION("Savings Transaction");
private final String value;
@@ -70,4 +80,5 @@ public class BusinessEventNotificationConstants {
return this.value;
}
}
+
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index 0b6fbf1..c236e37 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -358,7 +358,7 @@ public class LoansApiResource {
public String retrieveLoan(@PathParam("loanId") final Long loanId,
@DefaultValue("false") @QueryParam("staffInSelectedOfficeOnly") final boolean staffInSelectedOfficeOnly,
@Context final UriInfo uriInfo) {
-
+ long start = System.currentTimeMillis() ;
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
LoanAccountData loanBasicDetails = this.loanReadPlatformService.retrieveOne(loanId);
@@ -392,9 +392,7 @@ public class LoansApiResource {
if(calendarData != null)
loanBasicDetails = LoanAccountData.withLoanCalendarData(loanBasicDetails, calendarData);
}
-
Collection<InterestRatePeriodData> interestRatesPeriods = this.loanReadPlatformService.retrieveLoanInterestRatePeriodData(loanBasicDetails);
-
Collection<LoanTransactionData> loanRepayments = null;
LoanScheduleData repaymentSchedule = null;
Collection<LoanChargeData> charges = null;
@@ -597,7 +595,13 @@ public class LoansApiResource {
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters(),
mandatoryResponseParameters);
- return this.toApiJsonSerializer.serialize(settings, loanAccount, this.LOAN_DATA_PARAMETERS);
+ long end = System.currentTimeMillis() ;
+ System.out.println("LoansApiResource.retrieveLoan() Time took: "+(end-start));
+ start = System.currentTimeMillis() ;
+ String toReturn = this.toApiJsonSerializer.serialize(settings, loanAccount, this.LOAN_DATA_PARAMETERS);
+ end = System.currentTimeMillis() ;
+ System.out.println("LoansApiResource.retrieveLoan() Time took to Serialize: "+(end-start));
+ return toReturn ;
}
@GET
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index c1b0f2c..15e23cb 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -6389,7 +6389,6 @@ public class Loan extends AbstractPersistableCustom<Long> {
public Collection<LoanCharge> getLoanCharges() {
return this.charges;
}
-
public void initializeLazyCollections() {
this.charges.size() ;
this.trancheCharges.size() ;
@@ -6412,4 +6411,9 @@ public class Loan extends AbstractPersistableCustom<Long> {
public void initializeRepaymentSchedule() {
this.repaymentScheduleInstallments.size() ;
}
+ public boolean hasInvalidLoanType() {
+ return AccountType.fromInt(this.loanType).isInvalid();
+ }
+
+ public boolean isIndividualLoan(){return AccountType.fromInt(this.loanType).isIndividualAccount();}
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
index 3dc1cb7..0da6393 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
@@ -778,6 +778,14 @@ public class LoanTransaction extends AbstractPersistableCustom<Long> {
return isAccrual();
}
+ public BigDecimal getOutstandingLoanBalance() {
+ return outstandingLoanBalance;
+ }
+
+ public PaymentDetail getPaymentDetail() {
+ return this.paymentDetail;
+ }
+
public boolean isPaymentTransaction() {
return this.isNotReversed()
&& !(this.isDisbursement() || this.isAccrual() || this.isRepaymentAtDisbursement() || this.isNonMonetaryTransaction() || this
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidLoanTypeException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidLoanTypeException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidLoanTypeException.java
new file mode 100644
index 0000000..6c64060
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/exception/InvalidLoanTypeException.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fineract.portfolio.loanaccount.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+
+/**
+ * {@link AbstractPlatformDomainRuleException} thrown an action to transition a
+ * loan from one state to another violates a domain rule.
+ */
+public class InvalidLoanTypeException extends AbstractPlatformDomainRuleException {
+
+ public InvalidLoanTypeException(final String defaultUserMessage, final Object... defaultUserMessageArgs) {
+ super("error.msg.loan.type.invalid", defaultUserMessage, defaultUserMessageArgs);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
index b697797..221273f 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@@ -1233,7 +1233,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.noteRepository.save(note);
}
}
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_REJECTED, constructEntityMap(BUSINESS_ENTITY.LOAN, loan));
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(loan.getId()) //
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
index 75a44ea..46d9795 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
@@ -392,7 +392,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
String sql = "select " + mapper.schema() + " where l.id =?";
LoanTransactionData loanTransactionData = this.jdbcTemplate.queryForObject(sql, mapper, LoanTransactionType.REPAYMENT.getValue(),
loanId, loanId);
-
final Collection<PaymentTypeData> paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
return LoanTransactionData.templateOnTop(loanTransactionData, paymentOptions);
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java
index c02bc9d..be39011 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java
@@ -115,4 +115,5 @@ public final class PaymentDetail extends AbstractPersistableCustom<Long> {
return this.paymentType;
}
+ public String getReceiptNumber() { return this.receiptNumber; }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
index 6426026..ae1b0f4 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountDomainServiceJpa.java
@@ -25,6 +25,9 @@ import org.apache.fineract.infrastructure.security.service.PlatformSecurityConte
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
+import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
import org.apache.fineract.portfolio.savings.SavingsAccountTransactionType;
import org.apache.fineract.portfolio.savings.SavingsTransactionBooleanValues;
@@ -40,6 +43,7 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Date;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -55,6 +59,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
private final ConfigurationDomainService configurationDomainService;
private final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository;
+ private final BusinessEventNotifierService businessEventNotifierService;
@Autowired
public SavingsAccountDomainServiceJpa(final SavingsAccountRepositoryWrapper savingsAccountRepository,
@@ -62,7 +67,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final ApplicationCurrencyRepositoryWrapper applicationCurrencyRepositoryWrapper,
final JournalEntryWritePlatformService journalEntryWritePlatformService,
final ConfigurationDomainService configurationDomainService, final PlatformSecurityContext context,
- final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository) {
+ final DepositAccountOnHoldTransactionRepository depositAccountOnHoldTransactionRepository,
+ final BusinessEventNotifierService businessEventNotifierService) {
this.savingsAccountRepository = savingsAccountRepository;
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
this.applicationCurrencyRepositoryWrapper = applicationCurrencyRepositoryWrapper;
@@ -70,6 +76,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
this.configurationDomainService = configurationDomainService;
this.context = context;
this.depositAccountOnHoldTransactionRepository = depositAccountOnHoldTransactionRepository;
+ this.businessEventNotifierService = businessEventNotifierService;
}
@Transactional
@@ -82,9 +89,10 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
-
if (transactionBooleanValues.isRegularTransaction() && !account.allowWithdrawal()) { throw new DepositAccountTransactionNotAllowedException(
account.getId(), "withdraw", account.depositAccountType()); }
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.SAVINGS_WITHDRAWAL,
+ constructEntityMap(BUSINESS_ENTITY.SAVING, account));
final Set<Long> existingTransactionIds = new HashSet<>();
final boolean interestPostAsOn = false;
final Set<Long> existingReversedTransactionIds = new HashSet<>();
@@ -92,7 +100,6 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail, new Date(), user);
final SavingsAccountTransaction withdrawal = account.withdraw(transactionDTO, transactionBooleanValues.isApplyWithdrawFee());
-
final MathContext mc = MathContext.DECIMAL64;
if (account.isBeforeLastPostingPeriod(transactionDate)) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
@@ -114,7 +121,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, transactionBooleanValues.isAccountTransfer());
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SAVINGS_WITHDRAWAL,
+ constructEntityMap(BUSINESS_ENTITY.SAVING, account));
return withdrawal;
}
@@ -147,7 +155,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
if (isRegularTransaction && !account.allowDeposit()) { throw new DepositAccountTransactionNotAllowedException(account.getId(),
"deposit", account.depositAccountType()); }
-
+ this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.SAVINGS_DEPOSIT,
+ constructEntityMap(BUSINESS_ENTITY.SAVING, account));
boolean isInterestTransfer = false;
final Set<Long> existingTransactionIds = new HashSet<>();
final Set<Long> existingReversedTransactionIds = new HashSet<>();
@@ -172,7 +181,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
this.savingsAccountRepository.save(account);
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
-
+ this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SAVINGS_DEPOSIT,
+ constructEntityMap(BUSINESS_ENTITY.SAVING, account));
return deposit;
}
@@ -218,4 +228,10 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final boolean isAccountTransfer = false;
postJournalEntries(account, existingTransactionIds, existingReversedTransactionIds, isAccountTransfer);
}
+
+ private Map<BUSINESS_ENTITY, Object> constructEntityMap(final BUSINESS_ENTITY entityEvent, Object entity) {
+ Map<BUSINESS_ENTITY, Object> map = new HashMap<>(1);
+ map.put(entityEvent, entity);
+ return map;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/911cab85/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
index 56e6485..c623709 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
@@ -729,16 +729,15 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
public void updateAmount(final Money amount) {
this.amount = amount.getAmount();
}
-
+
public Integer getTypeOf() {
return this.typeOf;
}
-
+
public SavingsAccount getSavingsAccount() {
return this.savingsAccount;
}
-
public void setSavingsAccount(SavingsAccount savingsAccount) {
this.savingsAccount = savingsAccount;
}
@@ -747,4 +746,7 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
return this.dateOf;
}
+ public PaymentDetail getPaymentDetail() {
+ return this.paymentDetail ;
+ }
}
\ No newline at end of file