This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new d21110f7b FINERACT-1724: Put user notification feature behind feature 
toggle
d21110f7b is described below

commit d21110f7b26298a40278e0c120586f3a96d0d1fa
Author: Adam Saghy <[email protected]>
AuthorDate: Wed Mar 22 19:12:31 2023 +0100

    FINERACT-1724: Put user notification feature behind feature toggle
---
 .../core/config/FineractProperties.java            |  15 +++
 .../TenantAwareBasicAuthenticationFilter.java      |   6 +-
 .../NotificationEventListener.java                 |  33 +-----
 .../service/NotificationDomainServiceImpl.java     |  29 +-----
 .../service/NotificationWritePlatformService.java  |   3 -
 .../NotificationWritePlatformServiceImpl.java      |  20 ----
 ...rmService.java => UserNotificationService.java} |  13 +--
 .../service/UserNotificationServiceImpl.java       | 114 +++++++++++++++++++++
 .../src/main/resources/application.properties      |   2 +
 9 files changed, 146 insertions(+), 89 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
index bcf601ab8..7348d52e2 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
@@ -58,6 +58,8 @@ public class FineractProperties {
     private FineractQueryProperties query;
     private FineractApiProperties api;
 
+    private FineractNotificationProperties notification;
+
     @Getter
     @Setter
     public static class FineractTenantProperties {
@@ -280,4 +282,17 @@ public class FineractProperties {
         private int inlineLoanCob;
     }
 
+    @Getter
+    @Setter
+    public static class FineractNotificationProperties {
+
+        private UserNotificationSystemProperties userNotificationSystem;
+    }
+
+    @Getter
+    @Setter
+    public static class UserNotificationSystemProperties {
+
+        private boolean enabled;
+    }
 }
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 d9a43c437..3709ec45d 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
@@ -37,7 +37,7 @@ import 
org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.security.data.PlatformRequestLog;
 import 
org.apache.fineract.infrastructure.security.exception.InvalidTenantIdentifierException;
 import 
org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
-import 
org.apache.fineract.notification.service.NotificationReadPlatformService;
+import org.apache.fineract.notification.service.UserNotificationService;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -79,7 +79,7 @@ public class TenantAwareBasicAuthenticationFilter extends 
BasicAuthenticationFil
     private CacheWritePlatformService cacheWritePlatformService;
 
     @Autowired
-    private NotificationReadPlatformService notificationReadPlatformService;
+    private UserNotificationService userNotificationService;
 
     @Autowired
     private BasicAuthTenantDetailsService basicAuthTenantDetailsService;
@@ -170,7 +170,7 @@ public class TenantAwareBasicAuthenticationFilter extends 
BasicAuthenticationFil
         super.onSuccessfulAuthentication(request, response, authResult);
         AppUser user = (AppUser) authResult.getPrincipal();
 
-        if 
(notificationReadPlatformService.hasUnreadNotifications(user.getId())) {
+        if (userNotificationService.hasUnreadUserNotifications(user.getId())) {
             response.addHeader("X-Notification-Refresh", "true");
         } else {
             response.addHeader("X-Notification-Refresh", "false");
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
index 31dc3cbe9..75eb78f58 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
@@ -18,46 +18,19 @@
  */
 package org.apache.fineract.notification.eventandlistener;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
 import lombok.RequiredArgsConstructor;
 import org.apache.fineract.notification.data.NotificationData;
-import 
org.apache.fineract.notification.service.NotificationWritePlatformService;
-import org.apache.fineract.useradministration.domain.AppUser;
-import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.apache.fineract.notification.service.UserNotificationService;
 import org.springframework.stereotype.Service;
 
 @Service
 @RequiredArgsConstructor
 public class NotificationEventListener {
 
-    private final NotificationWritePlatformService 
notificationWritePlatformService;
-    private final AppUserRepository appUserRepository;
+    private final UserNotificationService userNotificationService;
 
     public void receive(NotificationData notificationData) {
-        Long appUserId = notificationData.getActorId();
+        userNotificationService.notifyUsers(notificationData);
 
-        Set<Long> userIds = notificationData.getUserIds();
-
-        if (notificationData.getOfficeId() != null) {
-            List<Long> tempUserIds = new ArrayList<>(userIds);
-            for (Long userId : tempUserIds) {
-                AppUser appUser = 
appUserRepository.findById(userId).orElseThrow();
-                if (!Objects.equals(appUser.getOffice().getId(), 
notificationData.getOfficeId())) {
-                    userIds.remove(userId);
-                }
-            }
-        }
-
-        // Don't notify the same user who triggered the event
-        if (userIds.contains(appUserId)) {
-            userIds.remove(appUserId);
-        }
-
-        notificationWritePlatformService.notify(userIds, 
notificationData.getObjectType(), notificationData.getObjectId(),
-                notificationData.getAction(), notificationData.getActorId(), 
notificationData.getContent(),
-                notificationData.isSystemGenerated());
     }
 }
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 1fcb893a7..750452359 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,15 +18,10 @@
  */
 package org.apache.fineract.notification.service;
 
-import static java.util.stream.Collectors.toSet;
-
-import java.util.Collection;
-import java.util.Set;
 import javax.annotation.PostConstruct;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
-import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.event.business.BusinessEventListener;
 import 
org.apache.fineract.infrastructure.event.business.domain.client.ClientCreateBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.domain.deposit.FixedDepositAccountCreateBusinessEvent;
@@ -50,8 +45,6 @@ import 
org.apache.fineract.infrastructure.event.business.domain.share.ShareAccou
 import 
org.apache.fineract.infrastructure.event.business.domain.share.ShareProductDividentsCreateBusinessEvent;
 import 
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
-import org.apache.fineract.notification.data.NotificationData;
-import 
org.apache.fineract.notification.eventandlistener.NotificationEventPublisher;
 import org.apache.fineract.portfolio.client.domain.Client;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
@@ -62,8 +55,6 @@ 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.springframework.stereotype.Service;
 
 @Service
@@ -73,8 +64,7 @@ public class NotificationDomainServiceImpl implements 
NotificationDomainService
 
     private final BusinessEventNotifierService businessEventNotifierService;
     private final PlatformSecurityContext context;
-    private final NotificationEventPublisher notificationEventPublisher;
-    private final AppUserRepository appUserRepository;
+    private final UserNotificationService userNotificationService;
 
     @PostConstruct
     public void addListeners() {
@@ -327,22 +317,7 @@ public class NotificationDomainServiceImpl implements 
NotificationDomainService
     private void buildNotification(String permission, String objectType, Long 
objectIdentifier, String notificationContent,
             String eventType, Long appUserId, Long officeId) {
 
-        String tenantIdentifier = 
ThreadLocalContextUtil.getTenant().getTenantIdentifier();
-        Set<Long> userIds = getNotifiableUserIds(officeId, permission);
-        NotificationData notificationData = new 
NotificationData().setObjectType(objectType).setObjectId(objectIdentifier)
-                
.setAction(eventType).setActorId(appUserId).setContent(notificationContent).setRead(false).setSystemGenerated(false)
-                
.setTenantIdentifier(tenantIdentifier).setOfficeId(officeId).setUserIds(userIds);
-        try {
-            notificationEventPublisher.broadcastNotification(notificationData);
-        } catch (Exception e) {
-            // We want to avoid rethrowing the exception to stop the business 
transaction from rolling back
-            log.error("Error while broadcasting notification event", e);
-        }
+        userNotificationService.notifyUsers(permission, objectType, 
objectIdentifier, notificationContent, eventType, appUserId, officeId);
     }
 
-    private Set<Long> getNotifiableUserIds(Long officeId, String permission) {
-        Collection<AppUser> users = appUserRepository.findByOfficeId(officeId);
-        Collection<AppUser> usersWithPermission = users.stream().filter(aU -> 
aU.hasAnyPermission(permission, "ALL_FUNCTIONS")).toList();
-        return 
usersWithPermission.stream().map(AppUser::getId).collect(toSet());
-    }
 }
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 d0999baf6..65a38804c 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
@@ -22,9 +22,6 @@ import java.util.Collection;
 
 public interface NotificationWritePlatformService {
 
-    Long notify(Long userId, String objectType, Long objectId, String action, 
Long actorId, String notificationContent,
-            boolean isSystemGenerated);
-
     Long notify(Collection<Long> userIds, String objectType, Long objectId, 
String action, Long actorId, String notificationContent,
             boolean isSystemGenerated);
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
index 42105d9cc..e5a5b68f4 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
@@ -40,26 +40,6 @@ public class NotificationWritePlatformServiceImpl implements 
NotificationWritePl
     private final AppUserRepository appUserRepository;
     private final NotificationMapperWritePlatformService 
notificationMapperWritePlatformService;
 
-    @Override
-    public Long notify(Long userId, String objectType, Long objectIdentifier, 
String action, Long actorId, String notificationContent,
-            boolean isSystemGenerated) {
-
-        Long generatedNotificationId = 
insertIntoNotificationGenerator(objectType, objectIdentifier, action, actorId, 
notificationContent,
-                isSystemGenerated);
-        insertIntoNotificationMapper(userId, generatedNotificationId);
-        return generatedNotificationId;
-    }
-
-    private Long insertIntoNotificationMapper(Long userId, Long 
generatedNotificationId) {
-        AppUser appUser = this.appUserRepository.findById(userId).orElse(null);
-        NotificationMapper notificationMapper = new NotificationMapper()
-                
.setNotification(this.notificationGeneratorReadRepositoryWrapper.findById(generatedNotificationId)).setUserId(appUser)
-                
.setRead(false).setCreatedAt(DateUtils.getLocalDateTimeOfSystem());
-
-        this.notificationMapperWritePlatformService.create(notificationMapper);
-        return notificationMapper.getId();
-    }
-
     private Long insertIntoNotificationGenerator(String objectType, Long 
objectIdentifier, String action, Long actorId,
             String notificationContent, boolean isSystemGenerated) {
 
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/UserNotificationService.java
similarity index 67%
copy from 
fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
copy to 
fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationService.java
index d0999baf6..06b9a6405 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/UserNotificationService.java
@@ -18,13 +18,14 @@
  */
 package org.apache.fineract.notification.service;
 
-import java.util.Collection;
+import org.apache.fineract.notification.data.NotificationData;
 
-public interface NotificationWritePlatformService {
+public interface UserNotificationService {
 
-    Long notify(Long userId, String objectType, Long objectId, String action, 
Long actorId, String notificationContent,
-            boolean isSystemGenerated);
+    void notifyUsers(String permission, String objectType, Long 
objectIdentifier, String notificationContent, String eventType,
+            Long appUserId, Long officeId);
 
-    Long notify(Collection<Long> userIds, String objectType, Long objectId, 
String action, Long actorId, String notificationContent,
-            boolean isSystemGenerated);
+    boolean hasUnreadUserNotifications(Long appUserId);
+
+    void notifyUsers(NotificationData notificationData);
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationServiceImpl.java
new file mode 100644
index 000000000..f597aa4a1
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/UserNotificationServiceImpl.java
@@ -0,0 +1,114 @@
+/**
+ * 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 static java.util.stream.Collectors.toSet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.notification.data.NotificationData;
+import 
org.apache.fineract.notification.eventandlistener.NotificationEventPublisher;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class UserNotificationServiceImpl implements UserNotificationService {
+
+    private final NotificationEventPublisher notificationEventPublisher;
+    private final AppUserRepository appUserRepository;
+    private final FineractProperties fineractProperties;
+    private final NotificationReadPlatformService 
notificationReadPlatformService;
+    private final NotificationWritePlatformService 
notificationWritePlatformService;
+
+    @Override
+    public void notifyUsers(String permission, String objectType, Long 
objectIdentifier, String notificationContent, String eventType,
+            Long appUserId, Long officeId) {
+
+        if (userNotificationSystemIsEnabled()) {
+            String tenantIdentifier = 
ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+            Set<Long> userIds = getNotifiableUserIds(officeId, permission);
+            NotificationData notificationData = new 
NotificationData().setObjectType(objectType).setObjectId(objectIdentifier)
+                    
.setAction(eventType).setActorId(appUserId).setContent(notificationContent).setRead(false).setSystemGenerated(false)
+                    
.setTenantIdentifier(tenantIdentifier).setOfficeId(officeId).setUserIds(userIds);
+            try {
+                
notificationEventPublisher.broadcastNotification(notificationData);
+            } catch (Exception e) {
+                // We want to avoid rethrowing the exception to stop the 
business transaction from rolling back
+                log.error("Error while broadcasting notification event", e);
+            }
+        }
+    }
+
+    @Override
+    public boolean hasUnreadUserNotifications(Long appUserId) {
+        if (userNotificationSystemIsEnabled()) {
+            return 
notificationReadPlatformService.hasUnreadNotifications(appUserId);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public void notifyUsers(NotificationData notificationData) {
+        if (userNotificationSystemIsEnabled()) {
+            Long appUserId = notificationData.getActorId();
+
+            Set<Long> userIds = notificationData.getUserIds();
+
+            if (notificationData.getOfficeId() != null) {
+                List<Long> tempUserIds = new ArrayList<>(userIds);
+                for (Long userId : tempUserIds) {
+                    AppUser appUser = 
appUserRepository.findById(userId).orElseThrow();
+                    if (!Objects.equals(appUser.getOffice().getId(), 
notificationData.getOfficeId())) {
+                        userIds.remove(userId);
+                    }
+                }
+            }
+
+            // Don't notify the same user who triggered the event
+            if (userIds.contains(appUserId)) {
+                userIds.remove(appUserId);
+            }
+
+            notificationWritePlatformService.notify(userIds, 
notificationData.getObjectType(), notificationData.getObjectId(),
+                    notificationData.getAction(), 
notificationData.getActorId(), notificationData.getContent(),
+                    notificationData.isSystemGenerated());
+        }
+    }
+
+    private boolean userNotificationSystemIsEnabled() {
+        return 
fineractProperties.getNotification().getUserNotificationSystem().isEnabled();
+    }
+
+    private Set<Long> getNotifiableUserIds(Long officeId, String permission) {
+        Collection<AppUser> users = appUserRepository.findByOfficeId(officeId);
+        Collection<AppUser> usersWithPermission = users.stream().filter(aU -> 
aU.hasAnyPermission(permission, "ALL_FUNCTIONS")).toList();
+        return 
usersWithPermission.stream().map(AppUser::getId).collect(toSet());
+    }
+}
diff --git a/fineract-provider/src/main/resources/application.properties 
b/fineract-provider/src/main/resources/application.properties
index 714e20715..195496ba0 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -102,6 +102,8 @@ 
fineract.report.export.s3.enabled=${FINERACT_REPORT_EXPORT_S3_ENABLED:false}
 
 
fineract.jpa.statementLoggingEnabled=${FINERACT_STATEMENT_LOGGING_ENABLED:false}
 
+fineract.notification.user-notification-system.enabled=${FINERACT_USER_NOTIFICATION_SYSTEM_ENABLED:true}
+
 # Logging pattern for the console
 logging.pattern.console=${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd 
HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} 
%clr(%replace([%X{correlationId}]){'\\[\\]', ''}) %clr(---){faint} 
%clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} 
%m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}}
 

Reply via email to