← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14504: Change validation notifications from roles to user groups.

 

------------------------------------------------------------
revno: 14504
committer: Jim Grace <jimgrace@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-03-27 21:51:34 -0400
message:
  Change validation notifications from roles to user groups.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/ValidationResultToAlertFilter.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/validation/hibernate/ValidationRuleGroup.hbm.xml
  dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/AddValidationRuleGroupAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/ShowUpdateValidationRuleGroupFormAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/UpdateValidationRuleGroupAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleGroupForm.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/addValidationRuleGroupForm.js
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/updateValidationRuleGroupForm.js
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/validationRuleGroup.js
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/jsonValidationRuleGroup.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleGroupForm.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/validationRuleGroup.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRule.java	2014-03-28 01:51:34 +0000
@@ -253,13 +253,13 @@
     }
     
     /**
-     * Indicates whether this validation rule has user roles to alert.
+     * Indicates whether this validation rule has user groups to alert.
      */
-    public boolean hasUserRolesToAlert()
+    public boolean hasUserGroupsToAlert()
     {
         for ( ValidationRuleGroup group : groups )
         {
-            if ( group.hasUserRolesToAlert() )
+            if ( group.hasUserGroupsToAlert() )
             {
                 return true;
             }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/validation/ValidationRuleGroup.java	2014-03-28 01:51:34 +0000
@@ -45,6 +45,7 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.hisp.dhis.user.UserGroup;
 
 /**
  * @author Lars Helge Overland
@@ -63,8 +64,10 @@
     @Scanned
     private Set<ValidationRule> members = new HashSet<ValidationRule>();
     
-    private Set<UserAuthorityGroup> userAuthorityGroupsToAlert = new HashSet<UserAuthorityGroup>();
-    
+    private Set<UserGroup> userGroupsToAlert = new HashSet<UserGroup>();
+
+    private boolean alertByOrgUnits;
+
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------     
@@ -104,9 +107,9 @@
     /**
      * Indicates whether this group has user roles to alert.
      */
-    public boolean hasUserRolesToAlert()
+    public boolean hasUserGroupsToAlert()
     {
-        return userAuthorityGroupsToAlert != null && !userAuthorityGroupsToAlert.isEmpty();
+        return userGroupsToAlert != null && !userGroupsToAlert.isEmpty();
     }
 
     // -------------------------------------------------------------------------
@@ -144,16 +147,32 @@
     @JsonProperty
     @JsonSerialize( contentAs = BaseIdentifiableObject.class )
     @JsonView( { DetailedView.class } )
-    @JacksonXmlElementWrapper( localName = "userRolesToAlert", namespace = DxfNamespaces.DXF_2_0)
-    @JacksonXmlProperty( localName = "userRoleToAlert", namespace = DxfNamespaces.DXF_2_0)
-    public Set<UserAuthorityGroup> getUserAuthorityGroupsToAlert()
-    {
-        return userAuthorityGroupsToAlert;
-    }
-
-    public void setUserAuthorityGroupsToAlert( Set<UserAuthorityGroup> userAuthorityGroupsToAlert )
-    {
-        this.userAuthorityGroupsToAlert = userAuthorityGroupsToAlert;
+    @JacksonXmlElementWrapper( localName = "userGroupsToAlert", namespace = DxfNamespaces.DXF_2_0)
+    @JacksonXmlProperty( localName = "userGroupToAlert", namespace = DxfNamespaces.DXF_2_0)
+    public Set<UserGroup> getUserGroupsToAlert()
+    {
+        return userGroupsToAlert;
+    }
+
+    @JsonProperty
+    @JsonView( {DetailedView.class, ExportView.class} )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    public void setUserGroupsToAlert( Set<UserGroup> userGroupsToAlert )
+    {
+        this.userGroupsToAlert = userGroupsToAlert;
+    }
+
+    @JsonProperty
+    @JsonView( {DetailedView.class, ExportView.class} )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    public boolean isAlertByOrgUnits()
+    {
+        return alertByOrgUnits;
+    }
+
+    public void setAlertByOrgUnits( boolean alertByOrgUnits )
+    {
+        this.alertByOrgUnits = alertByOrgUnits;
     }
 
     @Override

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-03-25 14:01:51 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-03-28 01:51:34 +0000
@@ -122,6 +122,7 @@
         executeSql( "DROP TABLE loginfailure" );
         executeSql( "DROP TABLE dashboarditem_trackedentitytabularreports" );
         executeSql( "DROP TABLE categoryoptioncombousergroupaccesses" );
+        executeSql( "DROP TABLE validationrulegroupuserrolestoalert" );
         executeSql( "ALTER TABLE categoryoptioncombo drop column userid" );
         executeSql( "ALTER TABLE categoryoptioncombo drop column publicaccess" );
         executeSql( "ALTER TABLE dataelementcategoryoption drop column categoryid" );
@@ -703,6 +704,9 @@
         // update attribute.code, set to null if code=''
         executeSql( "UPDATE attribute SET code=NULL WHERE code=''" );
 
+        // validation rule group, new column alertbyorgunits needs values
+        executeSql( "UPDATE validationrulegroup SET alertbyorgunits=false WHERE alertbyorgunits IS NULL" );
+
         upgradeDataValuesWithAttributeOptionCombo();
         upgradeMapViewsToAnalyticalObject();
 

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java	2014-03-28 01:51:34 +0000
@@ -71,8 +71,8 @@
 import org.hisp.dhis.system.util.Filter;
 import org.hisp.dhis.system.util.FilterUtils;
 import org.hisp.dhis.user.User;
-import org.hisp.dhis.user.UserAuthorityGroup;
 import org.hisp.dhis.user.UserCredentials;
+import org.hisp.dhis.user.UserGroup;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -269,7 +269,7 @@
         Collection<ValidationResult> results = Validator.validate( sources, periods, rules,
             lastScheduledRun, constantService, expressionService, periodService, dataValueService );
         
-        log.info( "Run results: " + results.size() );
+        log.info( "Validation run result count: " + results.size() );
         
         if ( !results.isEmpty() )
         {
@@ -296,7 +296,7 @@
         
         for ( ValidationRuleGroup validationRuleGroup : getAllValidationRuleGroups() )
         {
-            if ( validationRuleGroup.hasUserRolesToAlert() )
+            if ( validationRuleGroup.hasUserGroupsToAlert() )
             {
                 rules.addAll( validationRuleGroup.getMembers() );
             }
@@ -361,11 +361,10 @@
     {
         SortedSet<ValidationResult> results = new TreeSet<ValidationResult>( validationResults );
 
-        Map<List<ValidationResult>, Set<User>> messageMap = getMessageMap( results );
-        
-        for ( Map.Entry<List<ValidationResult>, Set<User>> entry : messageMap.entrySet() )
+        Map<SortedSet<ValidationResult>, Set<User>> messageMap = getMessageMap( results );
+
+        for ( Map.Entry<SortedSet<ValidationResult>, Set<User>> entry : messageMap.entrySet() )
         {
-            Collections.sort( entry.getKey() );
             sendAlertmessage( entry.getKey(), entry.getValue(), scheduledRunStart );
         }
     }
@@ -396,82 +395,90 @@
      * to assemble into a message, and the value is the set of users who
      * should receive this message.
      * 
-     * @param results all the validation run results
+     * @param results all the validation run results, in a sorted set
      * @return map of result sets to users
      */
-    private Map<List<ValidationResult>, Set<User>> getMessageMap( Set<ValidationResult> results )
+    private Map<SortedSet<ValidationResult>, Set<User>> getMessageMap( SortedSet<ValidationResult> results )
     {
-        Map<User, Set<ValidationRule>> userRulesMap = getUserRulesMap();
-
-        Map<List<ValidationResult>, Set<User>> messageMap = new HashMap<List<ValidationResult>, Set<User>>();
-
-        for ( User user : userRulesMap.keySet() )
+        Map<User, SortedSet<ValidationResult>> userResults = getUserResults( results );
+
+        Map<SortedSet<ValidationResult>, Set<User>> messageMap = new HashMap<SortedSet<ValidationResult>, Set<User>>();
+
+        for (Map.Entry<User, SortedSet<ValidationResult>> userResultEntry : userResults.entrySet() )
         {
-            // For users receiving alerts, find the subset of results from run.
-
-            Collection<ValidationRule> userRules = userRulesMap.get( user );
-            List<ValidationResult> userResults = new ArrayList<ValidationResult>();
-
-            for ( ValidationResult result : results )
-            {
-                if ( userRules.contains( result.getValidationRule() ) )
-                {
-                    userResults.add( result );
-                }
-            }
-
-            // Group this user with other users having the same result subset.
-
-            if ( !userResults.isEmpty() )
-            {
-                Set<User> messageReceivers = messageMap.get( userResults );
-                if ( messageReceivers == null )
-                {
-                    messageReceivers = new HashSet<User>();
-                    messageMap.put( userResults, messageReceivers );
-                }
-                messageReceivers.add( user );
-            }
+            Set<User> users = messageMap.get( userResultEntry.getValue() );
+
+            if ( users == null )
+            {
+                users = new HashSet<User>();
+
+                messageMap.put( userResultEntry.getValue(), users );
+            }
+            users.add( userResultEntry.getKey() );
         }
-                
+
         return messageMap;
     }
 
     /**
-     * Constructs a Map where the key is each user who is configured to
-     * receive alerts, and the value is a list of rules they should receive
-     * results for.
-     * 
-     * @return Map from users to sets of rules
+     * Returns a map where the key is a user and the value is a naturally-sorted
+     * list of results they should receive.
+     *
+     * @param results all the validation run results, in a sorted set
+     * @return map of users to results
      */
-    private Map<User, Set<ValidationRule>> getUserRulesMap()
+    private Map<User, SortedSet<ValidationResult>> getUserResults( SortedSet<ValidationResult> results )
     {
-        Map<User, Set<ValidationRule>> userRulesMap = new HashMap<User, Set<ValidationRule>>();
+        Map<User, SortedSet<ValidationResult>> userResults = new HashMap<User, SortedSet<ValidationResult>>();
 
-        for ( ValidationRuleGroup validationRuleGroup : getAllValidationRuleGroups() )
+        for ( ValidationResult result : results )
         {
-            Collection<UserAuthorityGroup> userRolesToAlert = validationRuleGroup.getUserAuthorityGroupsToAlert();
-            
-            if ( userRolesToAlert != null && !userRolesToAlert.isEmpty() )
+            for ( ValidationRuleGroup ruleGroup : result.getValidationRule().getGroups() )
             {
-                for ( UserAuthorityGroup role : userRolesToAlert )
+                if ( ruleGroup.hasUserGroupsToAlert() )
                 {
-                    for ( UserCredentials userCredentials : role.getMembers() )
+                    for ( UserGroup userGroup : ruleGroup.getUserGroupsToAlert() )
                     {
-                        User user = userCredentials.getUser();
-                        Set<ValidationRule> userRules = userRulesMap.get( user );
-                        if ( userRules == null )
+                        for ( User user : userGroup.getMembers() )
                         {
-                            userRules = new HashSet<ValidationRule>();
-                            userRulesMap.put( user, userRules );
+                            if ( !ruleGroup.isAlertByOrgUnits() || canUserAccessSource( user, result.getSource() ) )
+                            {
+                                SortedSet<ValidationResult> resultSet = userResults.get ( user );
+
+                                if ( resultSet == null )
+                                {
+                                    resultSet = new TreeSet<ValidationResult>();
+
+                                    userResults.put( user, resultSet );
+                                }
+                                resultSet.add( result );
+                            }
                         }
-                        userRules.addAll( validationRuleGroup.getMembers() );
                     }
                 }
             }
         }
-        
-        return userRulesMap;
+        return userResults;
+    }
+
+    /**
+     * Determines whether a user can access an organisation unit,
+     * based on the organisation units to which the user has been assigned.
+     *
+     * @param user user to test
+     * @param source organisation unit to which the user may have access
+     * @return whether the user has acceess to the organisation unit
+     */
+    private boolean canUserAccessSource( User user, OrganisationUnit source )
+    {
+        for ( OrganisationUnit o : user.getOrganisationUnits() )
+        {
+            if ( source == o || source.getAncestors().contains( o ) )
+            {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
@@ -482,7 +489,7 @@
      * @param users users to receive these results
      * @param scheduledRunStart date/time when the scheduled run started
      */
-    private void sendAlertmessage( List<ValidationResult> results, Set<User> users, Date scheduledRunStart )
+    private void sendAlertmessage( SortedSet<ValidationResult> results, Set<User> users, Date scheduledRunStart )
     {
         StringBuilder builder = new StringBuilder();
 
@@ -522,7 +529,7 @@
      * @param results results to analyze
      * @return Mapping between importance type and result counts.
      */
-    private Map<String, Integer> countResultsByImportanceType ( List<ValidationResult> results )
+    private Map<String, Integer> countResultsByImportanceType ( Set<ValidationResult> results )
     {
         Map<String, Integer> importanceCountMap = new HashMap<String, Integer>();
         

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/ValidationResultToAlertFilter.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/ValidationResultToAlertFilter.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/ValidationResultToAlertFilter.java	2014-03-28 01:51:34 +0000
@@ -36,6 +36,6 @@
     @Override
     public boolean retain( ValidationResult result )
     {
-        return result != null && result.getValidationRule() != null && result.getValidationRule().hasUserRolesToAlert();
+        return result != null && result.getValidationRule() != null && result.getValidationRule().hasUserGroupsToAlert();
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/validation/hibernate/ValidationRuleGroup.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/validation/hibernate/ValidationRuleGroup.hbm.xml	2014-03-24 18:52:45 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/validation/hibernate/ValidationRuleGroup.hbm.xml	2014-03-28 01:51:34 +0000
@@ -19,16 +19,18 @@
 
     <property name="description" type="text" />
 
+    <property name="alertByOrgUnits" column="alertbyorgunits" />
+
     <set name="members" table="validationrulegroupmembers">
       <key column="validationgroupid" foreign-key="fk_validationrulegroupmembers_validationrulegroupid" />
       <many-to-many class="org.hisp.dhis.validation.ValidationRule" column="validationruleid"
         foreign-key="fk_validationrulegroup_validationruleid" />
     </set>
 
-    <set name="userAuthorityGroupsToAlert" table="validationrulegroupuserrolestoalert">
-      <key column="validationgroupid" foreign-key="fk_validationrulegroupuserrolestoalert_validationgroupid" />
-      <many-to-many class="org.hisp.dhis.user.UserAuthorityGroup" column="userroleid"
-        foreign-key="fk_validationrulegroupuserrolestoalert_userroleid" />
+    <set name="userGroupsToAlert" table="validationrulegroupusergroupstoalert">
+      <key column="validationgroupid" foreign-key="fk_validationrulegroupusergroupstoalert_validationgroupid" />
+      <many-to-many class="org.hisp.dhis.user.UserGroup" column="usergroupid"
+        foreign-key="fk_validationrulegroupusergroupstoalert_usergroupid" />
     </set>
 
     <!-- Access properties -->

=== modified file 'dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java'
--- dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java	2014-03-28 01:51:34 +0000
@@ -115,7 +115,7 @@
         emptyTable( "datadictionaryindicators" );
         emptyTable( "datadictionary" );
 
-        emptyTable( "validationrulegroupuserrolestoalert" );
+        emptyTable( "validationrulegroupusergroupstoalert" );
         emptyTable( "validationrulegroupmembers" );
         emptyTable( "validationrulegroup" );
         emptyTable( "validationrule" );

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/AddValidationRuleGroupAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/AddValidationRuleGroupAction.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/AddValidationRuleGroupAction.java	2014-03-28 01:51:34 +0000
@@ -30,7 +30,7 @@
 
 import java.util.Set;
 
-import org.hisp.dhis.user.UserService;
+import org.hisp.dhis.user.UserGroupService;
 import org.hisp.dhis.validation.ValidationRuleGroup;
 import org.hisp.dhis.validation.ValidationRuleService;
 
@@ -54,11 +54,11 @@
         this.validationRuleService = validationRuleService;
     }
 
-    private UserService userService;
+    private UserGroupService userGroupService;
 
-    public void setUserService( UserService userService )
+    public void setUserService( UserGroupService userGroupService )
     {
-        this.userService = userService;
+        this.userGroupService = userGroupService;
     }
 
     // -------------------------------------------------------------------------
@@ -86,13 +86,20 @@
         this.groupMembers = groupMembers;
     }
 
-    private Set<String> userRolesToAlert;
-
-    public void setUserRolesToAlert( Set<String> userRolesToAlert )
-    {
-        this.userRolesToAlert = userRolesToAlert;
-    }
-    
+    private Set<String> userGroupsToAlert;
+
+    public void setUserGroupsToAlert( Set<String> userGroupsToAlert )
+    {
+        this.userGroupsToAlert = userGroupsToAlert;
+    }
+
+    private boolean alertByOrgUnits;
+
+    public void setAlertByOrgUnits( boolean alertByOrgUnits )
+    {
+        this.alertByOrgUnits = alertByOrgUnits;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -111,15 +118,17 @@
                 group.getMembers().add( validationRuleService.getValidationRule( Integer.valueOf( id ) ) );
             }
         }
-        group.getUserAuthorityGroupsToAlert().clear();
+        group.getUserGroupsToAlert().clear();
 
-        if ( userRolesToAlert != null )
+        if ( userGroupsToAlert != null )
         {
-            for ( String id : userRolesToAlert )
+            for ( String id : userGroupsToAlert )
             {
-                group.getUserAuthorityGroupsToAlert().add( userService.getUserAuthorityGroup( Integer.valueOf( id ) ) );
+                group.getUserGroupsToAlert().add( userGroupService.getUserGroup( Integer.valueOf( id ) ) );
             }
         }
+
+        group.setAlertByOrgUnits( alertByOrgUnits );
        
         validationRuleService.addValidationRuleGroup( group );
         

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/ShowUpdateValidationRuleGroupFormAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/ShowUpdateValidationRuleGroupFormAction.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/ShowUpdateValidationRuleGroupFormAction.java	2014-03-28 01:51:34 +0000
@@ -34,6 +34,8 @@
 
 import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
 import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserGroup;
+import org.hisp.dhis.user.UserGroupService;
 import org.hisp.dhis.user.UserService;
 import org.hisp.dhis.validation.ValidationRule;
 import org.hisp.dhis.validation.ValidationRuleGroup;
@@ -61,11 +63,11 @@
         this.validationRuleService = validationRuleService;
     }
     
-    private UserService userService;
+    private UserGroupService userGroupService;
 
-    public void setUserService( UserService userService )
+    public void setUserGroupService( UserGroupService userGroupService )
     {
-        this.userService = userService;
+        this.userGroupService = userGroupService;
     }
 
     // -------------------------------------------------------------------------
@@ -104,18 +106,25 @@
         return groupMembers;
     }
 
-    private List<UserAuthorityGroup> availableUserRolesToAlert = new ArrayList<UserAuthorityGroup>();
+    private List<UserGroup> availableUserGroupsToAlert = new ArrayList<UserGroup>();
     
-    public List<UserAuthorityGroup> getAvailableUserRolesToAlert()
-    {
-        return availableUserRolesToAlert;
-    }
-
-    private List<UserAuthorityGroup> userRolesToAlert = new ArrayList<UserAuthorityGroup>();
-
-    public List<UserAuthorityGroup> getUserRolesToAlert()
-    {
-        return userRolesToAlert;
+    public List<UserGroup> getAvailableUserGroupsToAlert()
+    {
+        return availableUserGroupsToAlert;
+    }
+
+    private List<UserGroup> userGroupsToAlert = new ArrayList<UserGroup>();
+
+    public List<UserGroup> getUserGroupsToAlert()
+    {
+        return userGroupsToAlert;
+    }
+
+    private boolean alertByOrgUnits;
+
+    public boolean getAlertByOrgUnits()
+    {
+        return alertByOrgUnits;
     }
    
     // -------------------------------------------------------------------------
@@ -130,11 +139,13 @@
 
         Collections.sort( groupMembers, IdentifiableObjectNameComparator.INSTANCE );
         
-        availableUserRolesToAlert = new ArrayList<UserAuthorityGroup>( userService.getAllUserAuthorityGroups() );
+        availableUserGroupsToAlert = new ArrayList<UserGroup>( userGroupService.getAllUserGroups() );
 
-        userRolesToAlert = new ArrayList<UserAuthorityGroup>( validationRuleGroup.getUserAuthorityGroupsToAlert() );
+        userGroupsToAlert = new ArrayList<UserGroup>( validationRuleGroup.getUserGroupsToAlert() );
         
-        Collections.sort( userRolesToAlert, IdentifiableObjectNameComparator.INSTANCE );
+        Collections.sort( userGroupsToAlert, IdentifiableObjectNameComparator.INSTANCE );
+
+        alertByOrgUnits = validationRuleGroup.isAlertByOrgUnits();
 
         return SUCCESS;
     }

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/UpdateValidationRuleGroupAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/UpdateValidationRuleGroupAction.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/validationrulegroup/UpdateValidationRuleGroupAction.java	2014-03-28 01:51:34 +0000
@@ -30,7 +30,7 @@
 
 import java.util.Set;
 
-import org.hisp.dhis.user.UserService;
+import org.hisp.dhis.user.UserGroupService;
 import org.hisp.dhis.validation.ValidationRuleGroup;
 import org.hisp.dhis.validation.ValidationRuleService;
 
@@ -54,11 +54,11 @@
         this.validationRuleService = validationRuleService;
     }
     
-    private UserService userService;
+    private UserGroupService userGroupService;
 
-    public void setUserService( UserService userService )
+    public void setUserGroupService( UserGroupService userGroupService )
     {
-        this.userService = userService;
+        this.userGroupService = userGroupService;
     }
 
     // -------------------------------------------------------------------------
@@ -93,13 +93,20 @@
         this.groupMembers = groupMembers;
     }
 
-    private Set<String> userRolesToAlert;
-
-    public void setUserRolesToAlert( Set<String> userRolesToAlert )
-    {
-        this.userRolesToAlert = userRolesToAlert;
-    }
-    
+    private Set<String> userGroupsToAlert;
+
+    public void setUserGroupsToAlert( Set<String> userGroupsToAlert )
+    {
+        this.userGroupsToAlert = userGroupsToAlert;
+    }
+
+    private boolean alertByOrgUnits;
+
+    public void setAlertByOrgUnits( boolean alertByOrgUnits )
+    {
+        this.alertByOrgUnits = alertByOrgUnits;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -120,16 +127,18 @@
             }
         }
         
-        group.getUserAuthorityGroupsToAlert().clear();
+        group.getUserGroupsToAlert().clear();
 
-        if ( userRolesToAlert != null )
+        if ( userGroupsToAlert != null )
         {
-            for ( String id : userRolesToAlert )
+            for ( String id : userGroupsToAlert )
             {
-                group.getUserAuthorityGroupsToAlert().add( userService.getUserAuthorityGroup( Integer.valueOf( id ) ) );
+                group.getUserGroupsToAlert().add( userGroupService.getUserGroup( Integer.valueOf( id ) ) );
             }
         }
-        
+
+        group.setAlertByOrgUnits( alertByOrgUnits );
+
         validationRuleService.updateValidationRuleGroup( group );
         
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml	2013-12-17 09:33:58 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml	2014-03-28 01:51:34 +0000
@@ -77,7 +77,7 @@
     class="org.hisp.dhis.validationrule.action.validationrulegroup.AddValidationRuleGroupAction"
     scope="prototype">
     <property name="validationRuleService" ref="org.hisp.dhis.validation.ValidationRuleService" />
-    <property name="userService" ref="org.hisp.dhis.user.UserService" />
+    <property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
   </bean>
 
   <bean id="org.hisp.dhis.validationrule.action.validationrulegroup.GetValidationRuleGroupAction"
@@ -102,14 +102,14 @@
     class="org.hisp.dhis.validationrule.action.validationrulegroup.ShowUpdateValidationRuleGroupFormAction"
     scope="prototype">
     <property name="validationRuleService" ref="org.hisp.dhis.validation.ValidationRuleService" />
-    <property name="userService" ref="org.hisp.dhis.user.UserService" />
+    <property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
   </bean>
 
   <bean id="org.hisp.dhis.validationrule.action.validationrulegroup.UpdateValidationRuleGroupAction"
     class="org.hisp.dhis.validationrule.action.validationrulegroup.UpdateValidationRuleGroupAction"
     scope="prototype">
     <property name="validationRuleService" ref="org.hisp.dhis.validation.ValidationRuleService" />
-    <property name="userService" ref="org.hisp.dhis.user.UserService" />
+    <property name="userGroupService" ref="org.hisp.dhis.user.UserGroupService" />
   </bean>
 
   <bean id="org.hisp.dhis.validationrule.action.validationrulegroup.ValidateValidationRuleGroupAction"

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties	2014-03-04 00:22:37 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties	2014-03-28 01:51:34 +0000
@@ -64,7 +64,10 @@
 available=Available
 selected=Selected
 validation_rules=Validation rules
-user_roles_to_alert=User roles to alert
+user_groups_to_alert=User groups to alert
+alert_by_org_units=Only organisation unit related users are alerted
+yes=Yes
+no=No
 available_validation_rules=Available validation rules
 edit_validation_rule_group=Edit validation rule group
 all_validation_rules= All validation rules
@@ -146,7 +149,7 @@
 annual_sample_count=Annual sample count
 high_outliers=High outliers
 low_outliers=Low outliers
-number_of_user_roles_to_alert=Number of user roles to alert
+number_of_user_groups_to_alert=Number of user groups to alert
 send_alerts=Send alerts
 visible_when_rule_is_violated=visible when rule is violated
 instruction=Instruction
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleGroupForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleGroupForm.vm	2014-03-25 08:05:13 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleGroupForm.vm	2014-03-28 01:51:34 +0000
@@ -12,10 +12,10 @@
 				return option;
 			}
 		});
-		jQuery("#availableUserRolesToAlert").dhisAjaxSelect({
-			source: "../dhis-web-commons-ajax-json/getUserRoles.action",
-			iterator: "userRoles",
-			connectedTo: 'userRolesToAlert',
+		jQuery("#availableUserGroupsToAlert").dhisAjaxSelect({
+			source: "../dhis-web-commons-ajax-json/getUserGroups.action",
+			iterator: "userGroups",
+			connectedTo: 'userGroupsToAlert',
 			handler: function(item) {
 				var option = jQuery("<option />");
 				option.text( item.name );
@@ -83,25 +83,37 @@
     </tr>
 
     <tr>
-		<td><label>$i18n.getString( "user_roles_to_alert" )</label></td>		
+		<td><label>$i18n.getString( "user_groups_to_alert" )</label></td>
     	<td>
-            <select id="availableUserRolesToAlert" name="availableUserRolesToAlert" multiple="multiple" style="height: 200px; width: 100%;"></select>
+            <select id="availableUserGroupsToAlert" name="availableUserGroupsToAlert" multiple="multiple" style="height: 200px; width: 100%;"></select>
         </td>
 
         <td style="text-align:center">
-        	<input type="button" value="&gt;" title="$i18n.getString( 'move_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'availableUserRolesToAlert' );"/><br/>
-            <input type="button" value="&lt;" title="$i18n.getString( 'remove_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'userRolesToAlert' );"/><br/>
-			<input type="button" value="&gt;&gt;" title="$i18n.getString('move_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'availableUserRolesToAlert' );"/><br/>
-			<input type="button" value="&lt;&lt;" title="$i18n.getString('remove_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'userRolesToAlert' );"/>
+        	<input type="button" value="&gt;" title="$i18n.getString( 'move_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'availableUserGroupsToAlert' );"/><br/>
+            <input type="button" value="&lt;" title="$i18n.getString( 'remove_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'userGroupsToAlert' );"/><br/>
+			<input type="button" value="&gt;&gt;" title="$i18n.getString('move_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'availableUserGroupsToAlert' );"/><br/>
+			<input type="button" value="&lt;&lt;" title="$i18n.getString('remove_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'userGroupsToAlert' );"/>
         </td>
 
         <td>
-            <select id="userRolesToAlert" name="userRolesToAlert" multiple="multiple" style="height: 200px; width: 100%; margin-top: 22px" />
+            <select id="userGroupsToAlert" name="userGroupsToAlert" multiple="multiple" style="height: 200px; width: 100%; margin-top: 22px" />
         </td>      
     </tr>
 </table>
 
-<p>
+<table>
+    <tr>
+        <td><label for="alertByOrgUnits">$i18n.getString( "alert_by_org_units" )</label></td>
+        <td>
+            <select type="text" id="alertByOrgUnits" name="alertByOrgUnits">
+                <option value="false">$i18n.getString( "no" )</option>
+                <option value="true">$i18n.getString( "yes" )</option>
+            </select>
+        </td>
+    </tr>
+</table>
+
+    <p>
 	<input type="submit" value="$i18n.getString( "add" )" style="width:10em" />
 	<input type="button" value="$i18n.getString( "cancel" )" onclick="window.location.href='showValidationRuleGroupForm.action'" style="width:10em" />
 </p>

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/addValidationRuleGroupForm.js'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/addValidationRuleGroupForm.js	2013-10-13 18:23:51 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/addValidationRuleGroupForm.js	2014-03-28 01:51:34 +0000
@@ -9,7 +9,7 @@
         'beforeValidateHandler' : function()
         {
             selectAllById( 'groupMembers' );
-            selectAllById( 'userRolesToAlert' );
+            selectAllById( 'userGroupsToAlert' );
         },
         'rules' : getValidationRules( "validationRuleGroup" )
     } );

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/updateValidationRuleGroupForm.js'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/updateValidationRuleGroupForm.js	2013-10-16 20:03:41 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/updateValidationRuleGroupForm.js	2014-03-28 01:51:34 +0000
@@ -9,7 +9,7 @@
         'beforeValidateHandler' : function()
         {
             selectAllById( 'groupMembers' );
-            selectAllById( 'userRolesToAlert' );
+            selectAllById( 'userGroupsToAlert' );
         },
         'rules' : getValidationRules( "validationRuleGroup" )
     } );

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/validationRuleGroup.js'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/validationRuleGroup.js	2013-12-06 13:37:28 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/validationRuleGroup.js	2014-03-28 01:51:34 +0000
@@ -12,7 +12,7 @@
     setInnerHTML('nameField', json.validationRuleGroup.name);
     setInnerHTML('descriptionField', json.validationRuleGroup.description);
     setInnerHTML('memberCountField', json.validationRuleGroup.memberCount);
-    setInnerHTML('userRolesToAlertCountField', json.validationRuleGroup.userRolesToAlertCount);
+    setInnerHTML('userGroupsToAlertCountField', json.validationRuleGroup.userGroupsToAlertCount);
 
     showDetails();
   });
@@ -40,13 +40,13 @@
       $("<option></option>").attr("value", id).text(availableValidationRules[id]));
   }
 
-  for( var id in availableUserRolesToAlert ) {
-    $("#availableUserRolesToAlert").append($("<option></option>").attr("value", id).text(availableUserRolesToAlert[id]));
+  for( var id in availableUserGroupsToAlert ) {
+    $("#availableUserGroupsToAlert").append($("<option></option>").attr("value", id).text(availableUserGroupsToAlert[id]));
   }
 
-  for( var id in selectedUserRolesToAlert ) {
+  for( var id in selectedUserGroupsToAlert ) {
     $("#availableValidationRules").append(
-      $("<option></option>").attr("value", id).text(selectedUserRolesToAlert[id]));
+      $("<option></option>").attr("value", id).text(selectedUserGroupsToAlert[id]));
   }
 }
 
@@ -114,66 +114,66 @@
   filterAvailableValidationRules();
 }
 
-function filterAvailableUserRolesToAlert() {
-  var filter = document.getElementById('availableUserRolesToAlertFilter').value;
-  var list = document.getElementById('availableUserRolesToAlert');
-
-  list.options.length = 0;
-
-  for( var id in availableUserRolesToAlert ) {
-    var value = availableUserRolesToAlert[id];
-
-    if( value.toLowerCase().indexOf(filter.toLowerCase()) != -1 ) {
-      list.add(new Option(value, id), null);
-    }
-  }
-}
-
-function filterSelectedUserRolesToAlert() {
-  var filter = document.getElementById('selectedUserRolesToAlertFilter').value;
-  var list = document.getElementById('selectedUserRolesToAlert');
-
-  list.options.length = 0;
-
-  for( var id in selectedUserRolesToAlert ) {
-    var value = selectedUserRolesToAlert[id];
-
-    if( value.toLowerCase().indexOf(filter.toLowerCase()) != -1 ) {
-      list.add(new Option(value, id), null);
-    }
-  }
-}
-
-function addSelectedUserRolesToAlert() {
-  var list = document.getElementById('selectedUserRolesToAlert');
-
-  while( list.selectedIndex != -1 ) {
-    var id = list.options[list.selectedIndex].value;
-
-    list.options[list.selectedIndex].selected = false;
-
-    selectedUserRolesToAlert[id] = availableUserRolesToAlert[id];
-
-    delete availableUserRolesToAlert[id];
-  }
-
-  filterAvailableUserRolesToAlert();
-  filterSelectedUserRolesToAlert();
-}
-
-function removeSelectedUserRolesToAlert() {
-  var list = document.getElementById('selectedUserRolesToAlert');
-
-  while( list.selectedIndex != -1 ) {
-    var id = list.options[list.selectedIndex].value;
-
-    list.options[list.selectedIndex].selected = false;
-
-    availableUserRolesToAlert[id] = selectedUserRolesToAlert[id];
-
-    delete selectedUserRolesToAlert[id];
-  }
-
-  filterAvailableUserRolesToAlert();
-  filterSelectedUserRolesToAlert();
+function filterAvailableUserGroupsToAlert() {
+  var filter = document.getElementById('availableUserGroupsToAlertFilter').value;
+  var list = document.getElementById('availableUserGroupsToAlert');
+
+  list.options.length = 0;
+
+  for( var id in availableUserGroupsToAlert ) {
+    var value = availableUserGroupsToAlert[id];
+
+    if( value.toLowerCase().indexOf(filter.toLowerCase()) != -1 ) {
+      list.add(new Option(value, id), null);
+    }
+  }
+}
+
+function filterSelectedUserGroupsToAlert() {
+  var filter = document.getElementById('selectedUserGroupsToAlertFilter').value;
+  var list = document.getElementById('selectedUserGroupsToAlert');
+
+  list.options.length = 0;
+
+  for( var id in selectedUserGroupsToAlert ) {
+    var value = selectedUserGroupsToAlert[id];
+
+    if( value.toLowerCase().indexOf(filter.toLowerCase()) != -1 ) {
+      list.add(new Option(value, id), null);
+    }
+  }
+}
+
+function addSelectedUserGroupsToAlert() {
+  var list = document.getElementById('selectedUserGroupsToAlert');
+
+  while( list.selectedIndex != -1 ) {
+    var id = list.options[list.selectedIndex].value;
+
+    list.options[list.selectedIndex].selected = false;
+
+    selectedUserGroupsToAlert[id] = availableUserGroupsToAlert[id];
+
+    delete availableUserGroupsToAlert[id];
+  }
+
+  filterAvailableUserGroupsToAlert();
+  filterSelectedUserGroupsToAlert();
+}
+
+function removeSelectedUserGroupsToAlert() {
+  var list = document.getElementById('selectedUserGroupsToAlert');
+
+  while( list.selectedIndex != -1 ) {
+    var id = list.options[list.selectedIndex].value;
+
+    list.options[list.selectedIndex].selected = false;
+
+    availableUserGroupsToAlert[id] = selectedUserGroupsToAlert[id];
+
+    delete selectedUserGroupsToAlert[id];
+  }
+
+  filterAvailableUserGroupsToAlert();
+  filterSelectedUserGroupsToAlert();
 }

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/jsonValidationRuleGroup.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/jsonValidationRuleGroup.vm	2013-10-13 18:35:46 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/jsonValidationRuleGroup.vm	2014-03-28 01:51:34 +0000
@@ -4,6 +4,7 @@
     "name": "$!encoder.jsonEncode( ${validationRuleGroup.name} )",
     "description": "$!encoder.jsonEncode( ${validationRuleGroup.description} )",
     "memberCount": "${validationRuleGroup.members.size()}",
-    "userRolesToAlertCount": "$!{validationRuleGroup.userAuthorityGroupsToAlert.size()}"
+    "userGroupsToAlertCount": "$!{validationRuleGroup.userGroupsToAlert.size()}",
+    "alertByOrgUnits": $!{validationRuleGroup.alertByOrgUnits}"
   }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleGroupForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleGroupForm.vm	2013-10-13 18:20:54 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleGroupForm.vm	2014-03-28 01:51:34 +0000
@@ -12,10 +12,10 @@
 				return option;
 			}
 		});
-		jQuery("#availableUserRolesToAlert").dhisAjaxSelect({
-			source: "../dhis-web-commons-ajax-json/getUserRoles.action",
-			iterator: "userRoles",
-			connectedTo: 'userRolesToAlert',
+		jQuery("#availableUserGroupsToAlert").dhisAjaxSelect({
+			source: "../dhis-web-commons-ajax-json/getUserGroups.action",
+			iterator: "userGroups",
+			connectedTo: 'userGroupsToAlert',
 			handler: function(item) {
 				var option = jQuery("<option />");
 				option.text( item.name );
@@ -90,28 +90,40 @@
     </tr>
 
     <tr>
-		<td><label>$i18n.getString( "user_roles_to_alert" )</label></td>		
+		<td><label>$i18n.getString( "user_groups_to_alert" )</label></td>
     	<td>
-            <select id="availableUserRolesToAlert" name="availableUserRoles" multiple="multiple" style="height: 200px; width: 100%;"></select>
+            <select id="availableUserGroupsToAlert" name="availableUserGroups" multiple="multiple" style="height: 200px; width: 100%;"></select>
         </td>
 
         <td style="text-align:center">
-        	<input type="button" value="&gt;" title="$i18n.getString( 'move_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'availableUserRolesToAlert' );"/><br/>
-            <input type="button" value="&lt;" title="$i18n.getString( 'remove_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'userRolesToAlert' );"/><br/>
-			<input type="button" value="&gt;&gt;" title="$i18n.getString('move_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'availableUserRolesToAlert' );"/><br/>
-			<input type="button" value="&lt;&lt;" title="$i18n.getString('remove_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'userRolesToAlert' );"/>
+        	<input type="button" value="&gt;" title="$i18n.getString( 'move_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'availableUserGroupsToAlert' );"/><br/>
+            <input type="button" value="&lt;" title="$i18n.getString( 'remove_selected' )" style="width:50px" onclick="dhisAjaxSelect_moveAllSelected( 'userGroupsToAlert' );"/><br/>
+			<input type="button" value="&gt;&gt;" title="$i18n.getString('move_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'availableUserGroupsToAlert' );"/><br/>
+			<input type="button" value="&lt;&lt;" title="$i18n.getString('remove_all')" style="width:50px" onclick="dhisAjaxSelect_moveAll( 'userGroupsToAlert' );"/>
         </td>
 
         <td>
-            <select id="userRolesToAlert" name="userRolesToAlert" multiple="multiple" style="height: 200px; width: 100%; margin-top: 22px" />
-			#foreach( $userRole in $userRolesToAlert )
-				<option value="$userRole.id">$encoder.htmlEncode( $userRole.displayName )</option>
+            <select id="userGroupsToAlert" name="userGroupsToAlert" multiple="multiple" style="height: 200px; width: 100%; margin-top: 22px" />
+			#foreach( $userGroup in $userGroupsToAlert )
+				<option value="$userGroup.id">$encoder.htmlEncode( $userGroup.displayName )</option>
 			#end
             </select>
         </td>      
     </tr>
 </table>
 
+<table>
+    <tr>
+        <td><label for="alertByOrgUnits">$i18n.getString( "alert_by_org_units" )</label></td>
+        <td>
+            <select type="text" id="alertByOrgUnits" name="alertByOrgUnits">
+                <option value="false">$i18n.getString( "no" )</option>
+                <option value="true"#if( $validationRuleGroup.alertByOrgUnits == true ) selected="selected"#end>$i18n.getString( "yes" )</option>
+            </select>
+        </td>
+    </tr>
+</table>
+
 <p>
 	<input type="submit" value="$i18n.getString( "save" )" style="width:10em" />
 	<input type="button" value="$i18n.getString( "cancel" )" onclick="window.location.href='showValidationRuleGroupForm.action'" style="width:10em" />

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/validationRuleGroup.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/validationRuleGroup.vm	2014-03-25 08:05:13 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/validationRuleGroup.vm	2014-03-28 01:51:34 +0000
@@ -66,7 +66,7 @@
           <p><label>$i18n.getString( "name" ):</label><br><span id="nameField"></span></p>
           <p><label>$i18n.getString( "description" ):</label><br><span id="descriptionField"></span></p>
           <p><label>$i18n.getString( "number_of_members" ):</label><br><span id="memberCountField"></span></p>
-          <p><label>$i18n.getString( "number_of_user_roles_to_alert" ):</label><br><span id="userRolesToAlertCountField"></span></p>
+          <p><label>$i18n.getString( "number_of_user_groups_to_alert" ):</label><br><span id="userGroupsToAlertCountField"></span></p>
       </div>
 
 			<div id="warningArea">