fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From av...@apache.org
Subject [4/5] fineract git commit: Notification sub-system
Date Wed, 13 Dec 2017 12:39:53 GMT
Notification sub-system


Project: http://git-wip-us.apache.org/repos/asf/fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/fineract/commit/7395d6c5
Tree: http://git-wip-us.apache.org/repos/asf/fineract/tree/7395d6c5
Diff: http://git-wip-us.apache.org/repos/asf/fineract/diff/7395d6c5

Branch: refs/heads/develop
Commit: 7395d6c5439ffb6e7b375c4a74b78d453a3a2693
Parents: 58184a5
Author: Anh3h <courageangeh@gmail.com>
Authored: Wed Aug 23 07:27:57 2017 +0100
Committer: Avik Ganguly <avikg@apache.org>
Committed: Wed Dec 13 18:04:36 2017 +0530

----------------------------------------------------------------------
 fineract-provider/dependencies.gradle           |    1 -
 .../integrationtests/NotificationApiTest.java   |    5 +-
 .../common/NotificationHelper.java              |    3 +-
 .../TenantAwareBasicAuthenticationFilter.java   |    8 +
 .../api/NotificationApiResource.java            |    2 +-
 .../cache/CacheNotificationResponseHeader.java  |    1 -
 .../notification/data/NotificationData.java     |   12 +-
 .../fineract/notification/data/TopicData.java   |   76 ++
 .../notification/data/TopicSubscriberData.java  |   60 +
 .../notification/domain/Notification.java       |    6 +-
 .../notification/domain/NotificationMapper.java |    1 -
 .../domain/NotificationMapperRepository.java    |    1 -
 .../domain/NotificationRepository.java          |    1 -
 .../fineract/notification/domain/Topic.java     |  122 ++
 .../notification/domain/TopicRepository.java    |   29 +
 .../notification/domain/TopicSubscriber.java    |   80 ++
 .../domain/TopicSubscriberRepository.java       |   29 +
 .../eventandlistener/NotificationEvent.java     |   51 +
 .../exception/TopicNotFoundException.java       |   32 +
 .../service/NotificationDomainServiceImpl.java  | 1085 +++++++++---------
 .../NotificationMapperWritePlatformService.java |    1 -
 .../NotificationReadPlatformServiceImpl.java    |   10 +-
 .../NotificationWritePlatformService.java       |    1 +
 .../service/TopicReadPlatformService.java       |   32 +
 .../service/TopicReadPlatformServiceImpl.java   |   98 ++
 .../TopicSubscriberReadPlatformService.java     |   29 +
 .../TopicSubscriberReadPlatformServiceImpl.java |   78 ++
 .../TopicSubscriberWritePlatformService.java    |   27 +
 ...erWritePlatformServiceJpaRepositoryImpl.java |   42 +
 .../service/TopicWritePlatformService.java      |   27 +
 ...icWritePlatformServiceJpaRepositoryImpl.java |   42 +
 .../organisation/office/domain/Office.java      |    4 +
 ...ceWritePlatformServiceJpaRepositoryImpl.java |   49 +-
 .../BusinessEventNotificationConstants.java     |    1 +
 ...esWritePlatformServiceJpaRepositoryImpl.java |    2 +
 ...ctWritePlatformServiceJpaRepositoryImpl.java |    5 +
 ...ssWritePlatformServiceJpaRepositoryImpl.java |    6 +
 ...ctWritePlatformServiceJpaRepositoryImpl.java |    8 +-
 .../useradministration/domain/Role.java         |    4 +
 ...erWritePlatformServiceJpaRepositoryImpl.java |   91 +-
 ...leWritePlatformServiceJpaRepositoryImpl.java |   50 +-
 .../resources/META-INF/spring/appContext.xml    |    1 -
 .../META-INF/spring/notificationContext.xml     |    1 +
 .../core_db/V336__topic_module_table.sql        |   45 +
 .../apache/fineract/notification/Listener.java  |    3 +-
 .../fineract/notification/ListenerTest.java     |    3 +-
 .../fineract/notification/SenderTest.java       |    4 +-
 .../fineract/notification/StorageTest.java      |    6 +-
 .../apache/fineract/notification/TopicTest.java |  109 ++
 49 files changed, 1795 insertions(+), 589 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/dependencies.gradle
----------------------------------------------------------------------
diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle
index 27a256c..d157c89 100644
--- a/fineract-provider/dependencies.gradle
+++ b/fineract-provider/dependencies.gradle
@@ -93,7 +93,6 @@ dependencies {
                 //[group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.0']
                 [group: 'org.springframework', name:'spring-jms'],
                 [group: 'org.apache.activemq', name: 'activemq-broker']
-
      )
      testCompile 'junit:junit:4.11',
                  'junit:junit-dep:4.11',

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
index c516502..b052649 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
@@ -1,5 +1,3 @@
-package org.apache.fineract.integrationtests;
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -18,7 +16,7 @@ package org.apache.fineract.integrationtests;
  * specific language governing permissions and limitations
  * under the License.
  */
-
+package org.apache.fineract.integrationtests;
 
 import com.jayway.restassured.builder.RequestSpecBuilder;
 import com.jayway.restassured.builder.ResponseSpecBuilder;
@@ -54,4 +52,5 @@ public class NotificationApiTest {
         System.out.println("Response : " + response.toString());
         Assert.assertNotNull(response);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
index efac104..a2674ba 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
@@ -1,5 +1,3 @@
-package org.apache.fineract.integrationtests.common;
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -18,6 +16,7 @@ package org.apache.fineract.integrationtests.common;
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.fineract.integrationtests.common;
 
 import com.jayway.restassured.specification.RequestSpecification;
 import com.jayway.restassured.specification.ResponseSpecification;

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
index a36079d..ccd71cb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.lang.time.StopWatch;
+import org.apache.fineract.notification.service.NotificationReadPlatformService;
 import org.apache.fineract.infrastructure.cache.domain.CacheType;
 import org.apache.fineract.infrastructure.cache.service.CacheWritePlatformService;
 import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
@@ -78,6 +79,7 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
     private final ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer;
     private final ConfigurationDomainService configurationDomainService;
     private final CacheWritePlatformService cacheWritePlatformService;
+
     private final NotificationReadPlatformService notificationReadPlatformService;
     private final String tenantRequestHeader = "Fineract-Platform-TenantId";
     private final boolean exceptionIfHeaderMissing = true;
@@ -177,6 +179,12 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
             response.addHeader("X-Notification-Refresh", "false");
         }
 		
+		if(notificationReadPlatformService.hasUnreadNotifications(user.getId())) {
+			response.addHeader("X-Notification-Refresh", "true");
+		} else {
+			response.addHeader("X-Notification-Refresh", "false");
+		}
+		
 		String pathURL = request.getRequestURI();
 		boolean isSelfServiceRequest = (pathURL != null && pathURL.contains("/self/"));
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
index 065d7cb..860c74f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
@@ -18,7 +18,6 @@
  */
 package org.apache.fineract.notification.api;
 
-
 import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
 import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
 import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
@@ -86,4 +85,5 @@ public class NotificationApiResource {
         this.context.authenticatedUser();
         this.notificationReadPlatformService.updateNotificationReadStatus();
     }
+
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java b/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
index 205050b..3b5a6e1 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
@@ -18,7 +18,6 @@
  */
 package org.apache.fineract.notification.cache;
 
-
 public class CacheNotificationResponseHeader {
 
     private boolean hasNotifications;

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java b/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
index 63dab1a..865447c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
@@ -29,6 +29,7 @@ public class NotificationData implements Serializable {
     private String action;
     private Long actorId;
     private String content;
+	private boolean isRead;
     private boolean isSystemGenerated;
     private String tenantIdentifier;
     private String createdAt;
@@ -40,12 +41,13 @@ public class NotificationData implements Serializable {
     }
 
     public NotificationData(String objectType, Long objectId, String action, Long actorId, String content, boolean isSystemGenerated,
-                            String tenantIdentifier, Long officeId, List<Long> userIds) {
+    		boolean isRead, String tenantIdentifier, Long officeId, List<Long> userIds) {
         this.objectType = objectType;
         this.objectId = objectId;
         this.action = action;
         this.actorId = actorId;
         this.content = content;
+		this.isRead = isRead;
         this.isSystemGenerated = isSystemGenerated;
         this.tenantIdentifier = tenantIdentifier;
         this.officeId = officeId;
@@ -123,6 +125,14 @@ public class NotificationData implements Serializable {
     public void setContent(String content) {
         this.content = content;
     }
+    
+	public boolean isRead() {
+		return this.isRead;
+	}
+
+	public void setRead(boolean isRead) {
+		this.isRead = isRead;
+	}
 
     public boolean isSystemGenerated() {
         return isSystemGenerated;

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicData.java b/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicData.java
new file mode 100644
index 0000000..9e070fb
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicData.java
@@ -0,0 +1,76 @@
+/**
+ * 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.notification.data;
+
+import java.io.Serializable;
+
+public class TopicData implements Serializable {
+
+	private final Long id;
+	private final String title;
+	private final boolean enabled;
+	private final Long entityId;
+	private final String entityType;
+	private final String memberType;
+
+	public TopicData(Long id, String title, boolean enabled, Long entityId, String entityType,
+			String memberType) {
+		this.id = id;
+		this.title = title;
+		this.enabled = enabled;
+		this.entityId = entityId;
+		this.entityType = entityType;
+		this.memberType = memberType;
+	}
+
+	public TopicData(Long id, String title, Long entityId, String entityType,
+			String memberType) {
+		this.id = id;
+		this.title = title;
+		this.enabled = true;
+		this.entityId = entityId;
+		this.entityType = entityType;
+		this.memberType = memberType;
+	}
+
+	public Long getId() {
+		return this.id;
+	}
+
+	public String getTitle() {
+		return this.title;
+	}
+
+	public boolean isEnabled() {
+		return this.enabled;
+	}
+
+	public Long getEntityId() {
+		return this.entityId;
+	}
+
+	public String getEntityType() {
+		return this.entityType;
+	}
+
+	public String getMemberType() {
+		return this.memberType;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicSubscriberData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicSubscriberData.java b/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicSubscriberData.java
new file mode 100644
index 0000000..7691694
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/data/TopicSubscriberData.java
@@ -0,0 +1,60 @@
+/**
+ * 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.notification.data;
+
+import org.joda.time.LocalDate;
+
+public class TopicSubscriberData {
+	
+	private final Long id;
+	private final Long topicId;
+	private final Long userId;
+	private final LocalDate subscriptionDate;
+	
+	public TopicSubscriberData(Long id, Long topicId, Long userId, LocalDate subscriptionDate) {
+		this.id = id;
+		this.topicId = topicId;
+		this.userId = userId;
+		this.subscriptionDate = subscriptionDate;
+	}
+
+	public TopicSubscriberData(Long id, Long topicId, Long userId) {
+		this.id = id;
+		this.topicId = topicId;
+		this.userId = userId;
+		this.subscriptionDate = new LocalDate();
+	}
+
+	public Long getId() {
+		return this.id;
+	}
+
+	public Long getTopicId() {
+		return this.topicId;
+	}
+
+	public Long getUserId() {
+		return this.userId;
+	}
+
+	public LocalDate getSubscriptionDate() {
+		return this.subscriptionDate;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
index cf7d41e..4985f25 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
@@ -20,9 +20,7 @@ package org.apache.fineract.notification.domain;
 
 import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Table;
+import javax.persistence.*;
 
 @Entity
 @Table(name = "notification_generator")
@@ -90,7 +88,7 @@ public class Notification extends AbstractPersistableCustom<Long> {
         return actorId;
     }
 
-    public void setActor(Long actor) {
+    public void setActor(Long actorId) {
         this.actorId = actorId;
     }
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
index 5297d23..970b447 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
@@ -18,7 +18,6 @@
  */
 package org.apache.fineract.notification.domain;
 
-
 import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
 import org.apache.fineract.useradministration.domain.AppUser;
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
index fb88509..5caabf1 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
@@ -20,5 +20,4 @@ package org.apache.fineract.notification.domain;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 
-
 public interface NotificationMapperRepository extends JpaRepository<NotificationMapper, Long> {}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
index ed0675d..6b9160f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
@@ -20,5 +20,4 @@ package org.apache.fineract.notification.domain;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 
-
 public interface NotificationRepository extends JpaRepository<Notification, Long> {}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Topic.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Topic.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Topic.java
new file mode 100644
index 0000000..62f1a56
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Topic.java
@@ -0,0 +1,122 @@
+/**
+ * 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.notification.domain;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+
+@Entity
+@Table(name = "topic")
+public class Topic extends AbstractPersistableCustom<Long> {
+
+	@Column(name = "title", unique = true, nullable = false, length = 100)
+	private String title;
+	
+	@Column(name = "enabled", nullable = false)
+	private Boolean enabled;
+	
+	@Column(name = "entity_id", nullable = false)
+	private Long entityId;
+	
+	@Column(name = "entity_type")
+	private String entityType;
+	
+	@Column(name = "member_type")
+	private String memberType;
+	
+	public Topic() {
+	}
+	
+	public Topic(String title, Boolean enabled, Long entityId, String entityType, String memberType) {
+		this.title = title.trim();
+		this.enabled = enabled;
+		this.entityId = entityId;
+		this.entityType = entityType.trim();
+		this.memberType = memberType.trim();
+	}
+
+	public static Topic fromJson(final JsonCommand command) {
+		String title = "";
+		Boolean enabled = null;
+		Long entityId = 0L;
+		String entityType = "";
+		String memberType = "";
+		
+		if (command.hasParameter("title")) {
+			title = command.stringValueOfParameterNamed("title");
+		}
+		if (command.hasParameter("enabled")) {
+			enabled = command.booleanPrimitiveValueOfParameterNamed("enabled");
+		}
+		if (command.hasParameter("entityId")) {
+			entityId = command.longValueOfParameterNamed("entityId");
+		}
+		if (command.hasParameter("entityType")) {
+			entityType = command.stringValueOfParameterNamed("entityType");
+		}
+		if (command.hasParameter("memberType")) {
+			memberType = command.stringValueOfParameterNamed("memberType");
+		}
+		return new Topic(title, enabled, entityId, entityType, memberType);
+	}
+
+	public String getTitle() {
+		return this.title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+	public Boolean getEnabled() {
+		return this.enabled;
+	}
+
+	public void setEnabled(Boolean enabled) {
+		this.enabled = enabled;
+	}
+
+	public Long getEntityId() {
+		return this.entityId;
+	}
+
+	public void setEntityId(Long entityId) {
+		this.entityId = entityId;
+	}
+
+	public String getEntityType() {
+		return this.entityType;
+	}
+
+	public void setEntityType(String entityType) {
+		this.entityType = entityType;
+	}
+
+	public String getMemberType() {
+		return this.memberType;
+	}
+
+	public void setMemberType(String memberType) {
+		this.memberType = memberType;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicRepository.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicRepository.java
new file mode 100644
index 0000000..c01bb7b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicRepository.java
@@ -0,0 +1,29 @@
+/**
+ * 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.notification.domain;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface TopicRepository extends JpaRepository<Topic, Long>, JpaSpecificationExecutor<Topic> {
+	List<Topic> findByEntityId(Long entityId);
+	List<Topic> findByMemberType(String memberType);
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriber.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriber.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriber.java
new file mode 100644
index 0000000..74ef960
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriber.java
@@ -0,0 +1,80 @@
+/**
+ * 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.notification.domain;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.useradministration.domain.AppUser;
+
+@Entity
+@Table(name = "topic_subscriber")
+public class TopicSubscriber extends AbstractPersistableCustom<Long> {
+
+	@ManyToOne
+	@JoinColumn(name = "topic_id")
+	private Topic topic;
+	
+	@ManyToOne
+	@JoinColumn(name = "user_id")
+	private AppUser subscriber;
+	
+	@Column(name = "subscription_date")
+	private Date subscriptionDate;
+
+	public TopicSubscriber() {
+	}
+
+	public TopicSubscriber(Topic topic, AppUser subscriber, Date subscriptionDate) {
+		this.topic = topic;
+		this.subscriber = subscriber;
+		this.subscriptionDate = subscriptionDate;
+	}
+
+	public Topic getTopic() {
+		return this.topic;
+	}
+
+	public void setTopic(Topic topic) {
+		this.topic = topic;
+	}
+
+	public AppUser getSubscriber() {
+		return this.subscriber;
+	}
+
+	public void setSubscriber(AppUser subscriber) {
+		this.subscriber = subscriber;
+	}
+
+	public Date getSubscriptionDate() {
+		return this.subscriptionDate;
+	}
+
+	public void setSubscriptionDate(Date subscriptionDate) {
+		this.subscriptionDate = subscriptionDate;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriberRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriberRepository.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriberRepository.java
new file mode 100644
index 0000000..cd67fb9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/TopicSubscriberRepository.java
@@ -0,0 +1,29 @@
+/**
+ * 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.notification.domain;
+
+import java.util.List;
+
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface TopicSubscriberRepository extends JpaRepository<TopicSubscriber, Long>, JpaSpecificationExecutor<TopicSubscriber> {
+	List<TopicSubscriber> findBySubscriber(AppUser subscriber);
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEvent.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEvent.java b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEvent.java
new file mode 100644
index 0000000..9df5215
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEvent.java
@@ -0,0 +1,51 @@
+/**
+ * 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.notification.eventandlistener;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+import org.apache.fineract.notification.data.NotificationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NotificationEvent {
+	
+	private final JmsTemplate jmsTemplate;
+	
+	@Autowired
+	public NotificationEvent(JmsTemplate jmsTemplate) {
+		this.jmsTemplate = jmsTemplate;
+	}
+	
+	public void broadcastNotification(final Destination destination, final NotificationData notificationData) {
+		this.jmsTemplate.send(destination, new MessageCreator() {
+			@Override
+			public Message createMessage(Session session) throws JMSException {
+				return session.createObjectMessage(notificationData);
+			}
+		});
+	}
+	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/exception/TopicNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/exception/TopicNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/notification/exception/TopicNotFoundException.java
new file mode 100644
index 0000000..857ef4c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/exception/TopicNotFoundException.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.notification.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+/**
+ * A {@link RuntimeException} thrown when topic resources are not found.
+ */
+public class TopicNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+	public TopicNotFoundException(final Long id) {
+		super("error.msg.topic.id.invalid", "Topic with identifier " + id + " does not exist", id);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
index e8becbe..1744bd3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
@@ -18,13 +18,14 @@
  */
 package org.apache.fineract.notification.service;
 
-
 import org.apache.activemq.command.ActiveMQQueue;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.notification.data.NotificationData;
-import org.apache.fineract.notification.eventandlistener.NotificationEventService;
+import org.apache.fineract.notification.data.TopicSubscriberData;
+import org.apache.fineract.notification.eventandlistener.NotificationEvent;
+import org.apache.fineract.organisation.office.domain.OfficeRepository;
 import org.apache.fineract.portfolio.client.domain.Client;
 import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
 import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
@@ -39,552 +40,562 @@ import org.apache.fineract.portfolio.savings.domain.RecurringDepositAccount;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
 import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
 import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
-import org.apache.fineract.useradministration.domain.AppUser;
-import org.apache.fineract.useradministration.domain.AppUserRepository;
 import org.apache.fineract.useradministration.domain.Role;
+import org.apache.fineract.useradministration.domain.RoleRepository;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
 import javax.jms.Queue;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 @Service
 public class NotificationDomainServiceImpl implements NotificationDomainService {
 
-    private final BusinessEventNotifierService businessEventNotifierService;
-    private final NotificationEventService notificationEventService;
-    private final AppUserRepository appUserRepository;
-    private final PlatformSecurityContext context;
-
-
-    @Autowired
-    public NotificationDomainServiceImpl(final BusinessEventNotifierService businessEventNotifierService,
-                                         final NotificationEventService notificationEventService,
-                                         final AppUserRepository appUserRepository,
-                                         final PlatformSecurityContext context) {
-        this.businessEventNotifierService = businessEventNotifierService;
-        this.notificationEventService = notificationEventService;
-        this.appUserRepository = appUserRepository;
-        this.context = context;
-    }
-
-    @PostConstruct
-    public void addListeners() {
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.CLIENTS_CREATE,
-                new ClientCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_APPROVE,
-                new SavingsAccountApprovedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.CENTERS_CREATE,
-                new CenterCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.GROUPS_CREATE,
-                new GroupCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_DEPOSIT,
-                new SavingsAccountDepositListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_PRODUCT_DIVIDENDS_CREATE,
-                new ShareProductDividendCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.FIXED_DEPOSIT_ACCOUNT_CREATE,
-                new FixedDepositAccountCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.RECURRING_DEPOSIT_ACCOUNT_CREATE,
-                new RecurringDepositAccountCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_POST_INTEREST,
-                new SavingsPostInterestListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CREATE,
-                new LoanCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_APPROVED,
-                new LoanApprovedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CLOSE,
-                new LoanClosedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CLOSE_AS_RESCHEDULE,
-                new LoanCloseAsRescheduledListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT,
-                new LoanMakeRepaymentListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_PRODUCT_CREATE,
-                new LoanProductCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_CREATE,
-                new SavingsAccountCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_CLOSE,
-                new SavingsAccountClosedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_ACCOUNT_CREATE,
-                new ShareAccountCreatedListener());
-        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_ACCOUNT_APPROVE,
-                new ShareAccountApprovedListener());
-    }
-
-    private abstract class NotificationBusinessEventAdapter implements BusinessEventListner {
-
-        @Override
-        public void businessEventToBeExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
-            //Nothing to do
-        }
-    }
-
-    private class ClientCreatedListener extends  NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
-            Client client;
-            Object entity = businessEventEntity.get(BusinessEventNotificationConstants.BUSINESS_ENTITY.CLIENT);
-            if (entity != null) {
-                client = (Client) entity;
-                buildNotification(
-                        "ACTIVATE_CLIENT",
-                        "client",
-                        client.getId(),
-                        "New client created",
-                        "created",
-                        context.authenticatedUser().getId(),
-                        client.getOffice().getId()
-                );
-            }
-        }
-    }
-
-    private class CenterCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
-            CommandProcessingResult commandProcessingResult;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.GROUP);
-            if (entity != null) {
-                commandProcessingResult = (CommandProcessingResult) entity;
-                buildNotification(
-                        "ACTIVATE_CENTER",
-                        "center",
-                        commandProcessingResult.getGroupId(),
-                        "New center created",
-                        "created",
-                        context.authenticatedUser().getId(),
-                        commandProcessingResult.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class GroupCreatedListener extends  NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
-            CommandProcessingResult commandProcessingResult;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.GROUP);
-            if (entity != null) {
-                commandProcessingResult = (CommandProcessingResult) entity;
-                buildNotification(
-                        "ACTIVATE_GROUP",
-                        "group",
-                        commandProcessingResult.getGroupId(),
-                        "New group created",
-                        "created",
-                        context.authenticatedUser().getId(),
-                        commandProcessingResult.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class SavingsAccountDepositListener extends  NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            SavingsAccountTransaction savingsAccountTransaction;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVINGS_TRANSACTION);
-            if (entity != null) {
-                savingsAccountTransaction = (SavingsAccountTransaction) entity;
-                buildNotification(
-                        "READ_SAVINGSACCOUNT",
-                        "savingsAccount",
-                        savingsAccountTransaction.getSavingsAccount().getId(),
-                        "Deposit made",
-                        "depositMade",
-                        context.authenticatedUser().getId(),
-                        savingsAccountTransaction.getSavingsAccount().officeId()
-                );
-            }
-        }
-    }
-
-    private class ShareProductDividendCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            Long shareProductId;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_PRODUCT);
-            if (entity != null) {
-                shareProductId = (Long) entity;
-                buildNotification(
-                        "READ_DIVIDEND_SHAREPRODUCT",
-                        "shareProduct",
-                        shareProductId,
-                        "Dividend posted to account",
-                        "dividendPosted",
-                        context.authenticatedUser().getId(),
-                        context.authenticatedUser().getOffice().getId()
-                );
-            }
-        }
-    }
-
-    private class FixedDepositAccountCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            FixedDepositAccount fixedDepositAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.DEPOSIT_ACCOUNT);
-            if (entity != null) {
-                fixedDepositAccount = (FixedDepositAccount) entity;
-                buildNotification(
-                        "APPROVE_FIXEDDEPOSITACCOUNT",
-                        "fixedDeposit",
-                        fixedDepositAccount.getId(),
-                        "New fixed deposit account created",
-                        "created",
-                        context.authenticatedUser().getId(),
-                        fixedDepositAccount.officeId()
-                );
-            }
-        }
-    }
-
-    private class RecurringDepositAccountCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            RecurringDepositAccount recurringDepositAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.DEPOSIT_ACCOUNT);
-            if (entity != null) {
-                recurringDepositAccount = (RecurringDepositAccount) entity;
-                buildNotification(
-                        "APPROVE_RECURRINGDEPOSITACCOUNT",
-                        "recurringDepositAccount",
-                        recurringDepositAccount.getId(),
-                        "New recurring deposit account created",
-                        "created",
-                        context.authenticatedUser().getId(),
-                        recurringDepositAccount.officeId()
-                );
-            }
-        }
-    }
-
-
-    private class SavingsAccountApprovedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            SavingsAccount  savingsAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
-            if (entity != null) {
-                savingsAccount = (SavingsAccount) entity;
-                if (savingsAccount.depositAccountType().equals(DepositAccountType.FIXED_DEPOSIT)) {
-
-                    buildNotification(
-                        "ACTIVATE_FIXEDDEPOSITACCOUNT",
-                        "fixedDeposit",
-                        savingsAccount.getId(),
-                        "Fixed deposit account approved",
-                        "approved",
-                        context.authenticatedUser().getId(),
-                        savingsAccount.officeId()
-                    );
-
-                } else if (savingsAccount.depositAccountType().equals(DepositAccountType.RECURRING_DEPOSIT)) {
-
-                    buildNotification(
-                        "ACTIVATE_RECURRINGDEPOSITACCOUNT",
-                        "recurringDepositAccount",
-                        savingsAccount.getId(),
-                        "Recurring deposit account approved",
-                        "approved",
-                        context.authenticatedUser().getId(),
-                        savingsAccount.officeId()
-                    );
-
-                } else if (savingsAccount.depositAccountType().equals(DepositAccountType.SAVINGS_DEPOSIT)) {
-
-                    buildNotification(
-                        "ACTIVATE_SAVINGSACCOUNT",
-                        "savingsAccount",
-                        savingsAccount.getId(),
-                        "Savings account approved",
-                        "approved",
-                        context.authenticatedUser().getId(),
-                        savingsAccount.officeId()
-                    );
-                }
-            }
-        }
-    }
-
-    private class SavingsPostInterestListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            SavingsAccount savingsAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
-            if (entity != null) {
-                savingsAccount = (SavingsAccount) entity;
-                buildNotification(
-                    "READ_SAVINGSACCOUNT",
-                    "savingsAccount",
-                    savingsAccount.getId(),
-                    "Interest posted to account",
-                    "interestPosted",
-                    context.authenticatedUser().getId(),
-                    savingsAccount.officeId()
-                );
-            }
-        }
-    }
-
-    private class LoanCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            Loan loan;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
-            if (entity != null) {
-                loan = (Loan) entity;
-                buildNotification(
-                    "APPROVE_LOAN",
-                    "loan",
-                    loan.getId(),
-                    "New loan created",
-                    "created",
-                    context.authenticatedUser().getId(),
-                    loan.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class LoanApprovedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            Loan loan;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
-            if (entity != null) {
-                loan = (Loan) entity;
-                buildNotification(
-                    "DISBURSE_LOAN",
-                    "loan",
-                    loan.getId(),
-                    "New loan approved",
-                    "approved",
-                    context.authenticatedUser().getId(),
-                    loan.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class LoanClosedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            Loan loan;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
-            if (entity != null) {
-                loan = (Loan) entity;
-                buildNotification(
-                    "READ_LOAN",
-                    "loan",
-                    loan.getId(),
-                    "Loan closed",
-                    "loanClosed",
-                    context.authenticatedUser().getId(),
-                    loan.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class LoanCloseAsRescheduledListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            Loan loan;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
-            if (entity != null) {
-                loan = (Loan) entity;
-                buildNotification(
-                    "READ_Rescheduled Loans",
-                    "loan",
-                    loan.getId(),
-                    "Loan has been rescheduled",
-                    "loanRescheduled",
-                    context.authenticatedUser().getId(),
-                    loan.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class LoanMakeRepaymentListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            Loan loan;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
-            if (entity != null) {
-                loan = (Loan) entity;
-                buildNotification(
-                    "READ_LOAN",
-                    "loan",
-                    loan.getId(),
-                    "Repayment made",
-                    "repaymentMade",
-                    context.authenticatedUser().getId(),
-                    loan.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class LoanProductCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-
-            LoanProduct loanProduct;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN_PRODUCT);
-            if (entity != null) {
-                loanProduct = (LoanProduct) entity;
-                buildNotification(
-                    "READ_LOANPRODUCT",
-                    "loanProduct",
-                    loanProduct.getId(),
-                    "New loan product created",
-                    "created",
-                    context.authenticatedUser().getId(),
-                    context.authenticatedUser().getOffice().getId()
-                );
-            }
-        }
-    }
-
-    private class SavingsAccountCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            SavingsAccount  savingsAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
-            if (entity != null) {
-                savingsAccount = (SavingsAccount) entity;
-                buildNotification(
-                    "APPROVE_SAVINGSACCOUNT",
-                    "savingsAccount",
-                    savingsAccount.getId(),
-                    "New savings account created",
-                    "created",
-                    context.authenticatedUser().getId(),
-                    savingsAccount.officeId()
-                );
-            }
-        }
-    }
-
-    private class SavingsAccountClosedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            SavingsAccount  savingsAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
-            if (entity != null) {
-                savingsAccount = (SavingsAccount) entity;
-                buildNotification(
-                    "READ_SAVINGSACCOUNT",
-                    "savingsAccount",
-                    savingsAccount.getId(),
-                    "Savings has gone into dormant",
-                    "closed",
-                    context.authenticatedUser().getId(),
-                    savingsAccount.officeId()
-                );
-            }
-        }
-    }
-
-    private class ShareAccountCreatedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            ShareAccount shareAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_ACCOUNT);
-            if (entity != null) {
-                shareAccount = (ShareAccount) entity;
-                buildNotification(
-                    "APPROVE_SHAREACCOUNT",
-                    "shareAccount",
-                    shareAccount.getId(),
-                    "New share account created",
-                    "created",
-                    context.authenticatedUser().getId(),
-                    shareAccount.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private class ShareAccountApprovedListener extends NotificationBusinessEventAdapter {
-
-        @Override
-        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
-            ShareAccount shareAccount;
-            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_ACCOUNT);
-            if (entity != null) {
-                shareAccount = (ShareAccount) entity;
-                buildNotification(
-                    "ACTIVATE_SHAREACCOUNT",
-                    "shareAccount",
-                    shareAccount.getId(),
-                    "Share account approved",
-                    "approved",
-                    context.authenticatedUser().getId(),
-                    shareAccount.getOfficeId()
-                );
-            }
-        }
-    }
-
-    private void buildNotification(String permission, String objectType,
-                                   Long objectIdentifier, String notificationContent, String eventType,
-                                   Long appUserId, Long officeId) {
-
-        String tenantIdentifier = ThreadLocalContextUtil.getTenant().getTenantIdentifier();
-        Queue queue = new ActiveMQQueue("NotificationQueue");
-        List<Long> userIds = retrieveUsersWithSpecificPermission(permission);
-        NotificationData notificationData = new NotificationData(
-                objectType,
-                objectIdentifier,
-                eventType,
-                appUserId,
-                notificationContent,
-                false,
-                tenantIdentifier,
-                officeId,
-                userIds
-        );
-        notificationEventService.broadcastNotification(queue, notificationData);
-
-    }
-
-    private List<Long> retrieveUsersWithSpecificPermission(String permission) {
-        List<AppUser> appUsers = appUserRepository.findAll();
-        List<Long> userIds = new ArrayList<>();
-        for (AppUser appUser : appUsers) {
-            Set<Role> roles = appUser.getRoles();
-            for (Role role : roles) {
-                if (role.hasPermissionTo(permission)) {
-                    if (!(userIds.contains(appUser.getId()))) {
-                        userIds.add(appUser.getId());
-                    }
-                }
-            }
-        }
-        return userIds;
-    }
+	private final BusinessEventNotifierService businessEventNotifierService;
+	private final NotificationEvent notificationEvent;
+	private final PlatformSecurityContext context;
+	private final RoleRepository roleRepository;
+	private final OfficeRepository officeRepository;
+	private final TopicSubscriberReadPlatformService topicSubscriberReadPlatformService;
+	
+	@Autowired
+	public NotificationDomainServiceImpl(final BusinessEventNotifierService businessEventNotifierService,
+			final NotificationEvent notificationEvent,
+			final PlatformSecurityContext context, final RoleRepository roleRepository,
+			final TopicSubscriberReadPlatformService topicSubscriberReadPlatformService,
+			final OfficeRepository officeRepository) {
+		
+		this.businessEventNotifierService = businessEventNotifierService;
+		this.notificationEvent = notificationEvent;
+		this.context = context;
+		this.roleRepository = roleRepository;
+		this.topicSubscriberReadPlatformService = topicSubscriberReadPlatformService;
+		this.officeRepository = officeRepository;
+	}
+	
+	@PostConstruct
+	public void addListeners() {
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.CLIENTS_CREATE,
+				new ClientCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_APPROVE,
+				new SavingsAccountApprovedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.CENTERS_CREATE,
+				new CenterCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.GROUPS_CREATE,
+				new GroupCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_DEPOSIT,
+				new SavingsAccountDepositListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_PRODUCT_DIVIDENDS_CREATE,
+				new ShareProductDividendCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.FIXED_DEPOSIT_ACCOUNT_CREATE,
+				new FixedDepositAccountCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.RECURRING_DEPOSIT_ACCOUNT_CREATE,
+				new RecurringDepositAccountCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_POST_INTEREST,
+				new SavingsPostInterestListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CREATE,
+				new LoanCreatedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_APPROVED,
+				new LoanApprovedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CLOSE,
+				new LoanClosedListener());
+		businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CLOSE_AS_RESCHEDULE,
+				new LoanCloseAsRescheduledListener());
+		 businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT,
+				 new LoanMakeRepaymentListener());
+		 businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_PRODUCT_CREATE,
+				 new LoanProductCreatedListener());
+		 businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_CREATE,
+				 new SavingsAccountCreatedListener());
+		 businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_CLOSE,
+				 new SavingsAccountClosedListener());
+		 businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_ACCOUNT_CREATE,
+				 new ShareAccountCreatedListener());
+		 businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_ACCOUNT_APPROVE,
+				 new ShareAccountApprovedListener());
+	}
+	
+	private abstract class NotificationBusinessEventAdapter implements BusinessEventListner {
+		@Override
+		public void businessEventToBeExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+		}
+	}
+	
+	private class ClientCreatedListener extends  NotificationBusinessEventAdapter {
+
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			Client client;
+			Object entity = businessEventEntity.get(BusinessEventNotificationConstants.BUSINESS_ENTITY.CLIENT);
+			if (entity != null) {
+				client = (Client) entity;
+				buildNotification(
+						"ACTIVATE_CLIENT",
+						"client",
+						client.getId(),
+						"New client created",
+						"created",
+						context.authenticatedUser().getId(),
+						client.getOffice().getId()
+				);
+			}
+		}	
+	}
+	
+	private class CenterCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+			CommandProcessingResult commandProcessingResult;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.GROUP);
+			if (entity != null) {
+				commandProcessingResult = (CommandProcessingResult) entity;
+				buildNotification(
+						"ACTIVATE_CENTER",
+						"center",
+						commandProcessingResult.getGroupId(),
+						"New center created",
+						"created",
+						context.authenticatedUser().getId(),
+						commandProcessingResult.getOfficeId()
+				);
+			}
+		}
+	}
+	
+	private class GroupCreatedListener extends  NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+			CommandProcessingResult commandProcessingResult;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.GROUP);
+			if (entity != null) {
+				commandProcessingResult = (CommandProcessingResult) entity;
+				buildNotification(
+						"ACTIVATE_GROUP",
+						"group",
+						commandProcessingResult.getGroupId(),
+						"New group created",
+						"created",
+						context.authenticatedUser().getId(),
+						commandProcessingResult.getOfficeId()
+				);
+			}
+		}
+	}
+	
+	private class SavingsAccountDepositListener extends  NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			SavingsAccountTransaction savingsAccountTransaction;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVINGS_TRANSACTION);
+			if (entity != null) {
+				savingsAccountTransaction = (SavingsAccountTransaction) entity;
+				buildNotification(
+						"READ_SAVINGSACCOUNT",
+						"savingsAccount",
+						savingsAccountTransaction.getSavingsAccount().getId(),
+						"Deposit made",
+						"depositMade",
+						context.authenticatedUser().getId(),
+						savingsAccountTransaction.getSavingsAccount().officeId()
+				);
+			}
+		}
+	}
+	
+	private class ShareProductDividendCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			Long shareProductId;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_PRODUCT);
+			if (entity != null) {
+				shareProductId = (Long) entity;
+				buildNotification(
+						"READ_DIVIDEND_SHAREPRODUCT",
+						"shareProduct",
+						shareProductId,
+						"Dividend posted to account",
+						"dividendPosted",
+						context.authenticatedUser().getId(),
+						context.authenticatedUser().getOffice().getId()
+				);
+			}
+		}
+	}
+	
+	private class FixedDepositAccountCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			FixedDepositAccount fixedDepositAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.DEPOSIT_ACCOUNT);
+			if (entity != null) {
+				fixedDepositAccount = (FixedDepositAccount) entity;
+				buildNotification(
+						"APPROVE_FIXEDDEPOSITACCOUNT",
+						"fixedDeposit",
+						fixedDepositAccount.getId(),
+						"New fixed deposit account created",
+						"created",
+						context.authenticatedUser().getId(),
+						fixedDepositAccount.officeId()
+				);
+			}
+		}
+	}
+	
+	private class RecurringDepositAccountCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			RecurringDepositAccount recurringDepositAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.DEPOSIT_ACCOUNT);
+			if (entity != null) {
+				recurringDepositAccount = (RecurringDepositAccount) entity;
+				buildNotification(
+						"APPROVE_RECURRINGDEPOSITACCOUNT",
+						"recurringDepositAccount",
+						recurringDepositAccount.getId(),
+						"New recurring deposit account created",
+						"created",
+						context.authenticatedUser().getId(),
+						recurringDepositAccount.officeId()
+				);
+			}
+		}
+	}
+	
+	private class SavingsAccountApprovedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			SavingsAccount  savingsAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+			if (entity != null) {
+				savingsAccount = (SavingsAccount) entity;
+				if (savingsAccount.depositAccountType().equals(DepositAccountType.FIXED_DEPOSIT)) {
+					
+					buildNotification(
+							"ACTIVATE_FIXEDDEPOSITACCOUNT",
+							"fixedDeposit",
+							savingsAccount.getId(),
+							"Fixed deposit account approved",
+							"approved",
+							context.authenticatedUser().getId(),
+							savingsAccount.officeId()
+					);					
+				} else if (savingsAccount.depositAccountType().equals(DepositAccountType.RECURRING_DEPOSIT)) {
+					
+					buildNotification(
+							"ACTIVATE_RECURRINGDEPOSITACCOUNT",
+							"recurringDepositAccount",
+							savingsAccount.getId(),
+							"Recurring deposit account approved",
+							"approved",
+							context.authenticatedUser().getId(),
+							savingsAccount.officeId()
+					);
+				} else if (savingsAccount.depositAccountType().equals(DepositAccountType.SAVINGS_DEPOSIT)) {
+					
+					buildNotification(
+							"ACTIVATE_SAVINGSACCOUNT",
+							"savingsAccount",
+							savingsAccount.getId(),
+							"Savings account approved",
+							"approved",
+							context.authenticatedUser().getId(),
+							savingsAccount.officeId()
+					);
+				}
+			}
+		}
+	}
+	
+	private class SavingsPostInterestListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			SavingsAccount savingsAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+			if (entity != null) {
+				savingsAccount = (SavingsAccount) entity;
+				buildNotification(
+						"READ_SAVINGSACCOUNT",
+						"savingsAccount",
+						savingsAccount.getId(),
+						"Interest posted to account",
+						"interestPosted",
+						context.authenticatedUser().getId(),
+						savingsAccount.officeId()
+				);
+			}
+		}
+	}
+	
+	private class LoanCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			Loan loan;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+			if (entity != null) {
+				loan = (Loan) entity;
+				buildNotification(
+						"APPROVE_LOAN",
+						"loan",
+						loan.getId(),
+						"New loan created",
+						"created",
+						context.authenticatedUser().getId(),
+						loan.getOfficeId()
+				);
+			}
+			
+		}
+	}
+	
+	private class LoanApprovedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			Loan loan;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+			if (entity != null) {
+				loan = (Loan) entity;
+				buildNotification(
+						"DISBURSE_LOAN",
+						"loan",
+						loan.getId(),
+						"New loan approved",
+						"approved",
+						context.authenticatedUser().getId(),
+						loan.getOfficeId()
+				);
+			}
+		}
+	}
+	
+	private class LoanClosedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			
+			Loan loan;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+			if (entity != null) {
+				loan = (Loan) entity;
+				buildNotification(
+						"READ_LOAN",
+						"loan",
+						loan.getId(),
+						"Loan closed",
+						"loanClosed",
+						context.authenticatedUser().getId(),
+						loan.getOfficeId()
+				);
+			}
+		}
+	}
+		
+	private class LoanCloseAsRescheduledListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			Loan loan;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+			if (entity != null) {
+				loan = (Loan) entity;
+				buildNotification(
+						"READ_Rescheduled Loans",
+						"loan",
+						loan.getId(),
+						"Loan has been rescheduled",
+						"loanRescheduled",
+						 context.authenticatedUser().getId(),
+						 loan.getOfficeId()
+				);
+			}
+		}
+	}
+		
+	private class LoanMakeRepaymentListener extends NotificationBusinessEventAdapter {
+			
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			Loan loan;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+			if (entity != null) {
+				loan = (Loan) entity;
+				buildNotification(
+						"READ_LOAN",
+						"loan",
+						loan.getId(),
+						"Repayment made",
+						"repaymentMade",
+						context.authenticatedUser().getId(),
+						loan.getOfficeId()
+				);
+			}
+		}
+	}
+	
+	private class LoanProductCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			
+			LoanProduct loanProduct;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN_PRODUCT);
+			if (entity != null) {
+				loanProduct = (LoanProduct) entity;
+				buildNotification(
+						"READ_LOANPRODUCT",
+						"loanProduct",
+						loanProduct.getId(),
+						"New loan product created",
+						"created",
+						context.authenticatedUser().getId(),
+						context.authenticatedUser().getOffice().getId()
+				);
+			}
+		}
+	}
+	
+	private class SavingsAccountCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			SavingsAccount  savingsAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+			if (entity != null) {
+				savingsAccount = (SavingsAccount) entity;
+				buildNotification(
+						"APPROVE_SAVINGSACCOUNT",
+						"savingsAccount",
+						savingsAccount.getId(),
+						"New savings account created",
+						"created",
+						context.authenticatedUser().getId(),
+						savingsAccount.officeId()
+				);
+			}
+		}
+	}
+	
+	private class SavingsAccountClosedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			SavingsAccount  savingsAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+			if (entity != null) {
+				savingsAccount = (SavingsAccount) entity;
+				buildNotification(
+						"READ_SAVINGSACCOUNT",
+						"savingsAccount",
+						savingsAccount.getId(),
+						"Savings has gone into dormant",
+						"closed",
+						context.authenticatedUser().getId(),
+						savingsAccount.officeId()
+				);
+			}
+		}
+	}
+	
+	private class ShareAccountCreatedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			ShareAccount shareAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_ACCOUNT);
+			if (entity != null) {
+				shareAccount = (ShareAccount) entity;
+				buildNotification(
+						"APPROVE_SHAREACCOUNT",
+						"shareAccount",
+						shareAccount.getId(),
+						"New share account created",
+						"created",
+						context.authenticatedUser().getId(),
+						shareAccount.getOfficeId()
+				);
+			}
+		}
+	}
+	
+	private class ShareAccountApprovedListener extends NotificationBusinessEventAdapter {
+		
+		@Override
+		public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+			ShareAccount shareAccount;
+			Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_ACCOUNT);
+			if (entity != null) {
+				shareAccount = (ShareAccount) entity;
+				buildNotification(
+						"ACTIVATE_SHAREACCOUNT",
+						"shareAccount",
+						shareAccount.getId(),
+						"Share account approved",
+						"approved",
+						context.authenticatedUser().getId(),
+						shareAccount.getOfficeId()
+				);
+			}
+		}
+	}
+	
+	private void buildNotification(String permission, String objectType, Long objectIdentifier, 
+			String notificationContent, String eventType,  Long appUserId, Long officeId) {
+		
+		String tenantIdentifier = ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+		Queue queue = new ActiveMQQueue("NotificationQueue");
+		List<Long> userIds = retrieveSubscribers(officeId, permission);
+		NotificationData notificationData = new NotificationData(
+				objectType,
+				objectIdentifier,
+				eventType,
+				appUserId,
+				notificationContent,
+				false,
+				false,
+				tenantIdentifier,
+				officeId,
+				userIds
+		);
+		notificationEvent.broadcastNotification(queue, notificationData);
+	}
+	
+	private List<Long> retrieveSubscribers(Long officeId, String permission) {
+		
+		Collection<TopicSubscriberData> topicSubscribers = new ArrayList<>();
+		List<Long> subscriberIds = new ArrayList<>();
+		Long entityId = officeId;
+		String entityType= "";
+		if (officeRepository.findOne(entityId).getParent() == null) {
+			entityType = "OFFICE";
+		} else {
+			entityType = "BRANCH";
+		}
+		List<Role> allRoles = roleRepository.findAll();
+		for (Role curRole : allRoles) {
+			if (curRole.hasPermissionTo(permission) || curRole.hasPermissionTo("ALL_FUNCTIONS")) {
+				System.out.println(curRole + " Role has permission");
+				String memberType = curRole.getName();
+				topicSubscribers = topicSubscriberReadPlatformService.getSubscribers(entityId, entityType, memberType);
+			}
+		}
+		
+		for (TopicSubscriberData topicSubscriber : topicSubscribers) {
+			subscriberIds.add(topicSubscriber.getUserId());
+		 }
+		 return subscriberIds;
+	}
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
index 72c2ded..fe8b13a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
@@ -20,7 +20,6 @@ package org.apache.fineract.notification.service;
 
 import org.apache.fineract.notification.domain.NotificationMapper;
 
-
 public interface NotificationMapperWritePlatformService {
 
     Long create(NotificationMapper notificationMapper);

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
index c701be2..1c53d4e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
@@ -61,16 +61,12 @@ public class NotificationReadPlatformServiceImpl implements NotificationReadPlat
                 Long lastFetch = notificationResponseHeaderCache.get(appUserId).getLastFetch();
                 if ((now - lastFetch) > 1) {
                     return this.createUpdateCacheValue(appUserId, now, notificationResponseHeaderCache);
-                } else {
-                    return notificationResponseHeaderCache.get(appUserId).hasNotifications();
                 }
-            } else {
-                return this.createUpdateCacheValue(appUserId, now, notificationResponseHeaderCache);
+				return notificationResponseHeaderCache.get(appUserId).hasNotifications();
             }
-        } else {
-            return this.initializeTenantNotificationResponseHeaderCache(tenantId, now, appUserId);
-
+			return this.createUpdateCacheValue(appUserId, now, notificationResponseHeaderCache);
         }
+		return this.initializeTenantNotificationResponseHeaderCache(tenantId, now, appUserId);
     }
 
     private boolean initializeTenantNotificationResponseHeaderCache(Long tenantId, Long now, Long appUserId) {

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
index 703cf8e..cb76070 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
@@ -26,4 +26,5 @@ public interface NotificationWritePlatformService {
 
     Long notify(List<Long> userIds, String objectType, Long objectId, String action,
                 Long actorId, String notificationContent, boolean isSystemGenerated);
+
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/7395d6c5/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicReadPlatformService.java
new file mode 100644
index 0000000..e6c9ea5
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/TopicReadPlatformService.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.notification.service;
+
+import java.util.Collection;
+import org.apache.fineract.notification.data.TopicData;
+
+public interface TopicReadPlatformService {
+	
+	Collection<TopicData> getAllTopics();
+	
+	Collection<TopicData> getAllEnabledTopics();
+
+	TopicData findById(Long id);
+	
+}


Mime
View raw message