=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataapproval/DataApprovalLevelService.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataapproval/DataApprovalLevelService.java 2014-04-03 16:03:26 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataapproval/DataApprovalLevelService.java 2014-04-04 03:49:52 +0000 @@ -46,9 +46,10 @@ /** * Gets a list of the data approval levels for which the user has - * permission to approve, un. + * permission to perform at least one operation (approve, unapprove, + * accept, unaccept) for some selection of data at this approval level. * - * @return List of all data approval levels, ordered from 1 to n. + * @return List of selected user data approval levels, in ascending order. */ List getUserDataApprovalLevels(); === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataapproval/DefaultDataApprovalLevelService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataapproval/DefaultDataApprovalLevelService.java 2014-04-03 16:03:26 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataapproval/DefaultDataApprovalLevelService.java 2014-04-04 03:49:52 +0000 @@ -29,13 +29,19 @@ */ import org.hisp.dhis.dataelement.CategoryOptionGroup; +import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.organisationunit.OrganisationUnitLevel; import org.hisp.dhis.organisationunit.OrganisationUnitService; import org.hisp.dhis.security.SecurityService; +import org.hisp.dhis.user.CurrentUserService; +import org.hisp.dhis.user.User; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * @author Jim Grace @@ -62,6 +68,13 @@ this.organisationUnitService = organisationUnitService; } + private CurrentUserService currentUserService; + + public void setCurrentUserService( CurrentUserService currentUserService ) + { + this.currentUserService = currentUserService; + } + private SecurityService securityService; public void setSecurityService( SecurityService securityService ) @@ -102,8 +115,73 @@ public List getUserDataApprovalLevels() { - //TODO: Write the logic to filter the list according to the user. - return getAllDataApprovalLevels(); + List userDataApprovalLevels = new ArrayList(); + + User user = currentUserService.getCurrentUser(); + + boolean mayApprove = user.getUserCredentials().isAuthorized( DataApproval.AUTH_APPROVE ); + boolean mayApproveAtLowerLevels = user.getUserCredentials().isAuthorized( DataApproval.AUTH_APPROVE_LOWER_LEVELS ); + boolean mayAcceptAtLowerLevels = user.getUserCredentials().isAuthorized( DataApproval.AUTH_ACCEPT_LOWER_LEVELS ); + + if ( mayApprove || mayApproveAtLowerLevels || mayAcceptAtLowerLevels ) + { + Set userOrgUnitLevels = new HashSet(); + + for ( OrganisationUnit orgUnit : user.getOrganisationUnits() ) + { + int orgUnitLevel = orgUnit.getLevel() != 0 ? + orgUnit.getLevel() : organisationUnitService.getLevelOfOrganisationUnit( orgUnit.getUid() ); + + userOrgUnitLevels.add( orgUnitLevel ); + + System.out.println("User assigned to org unit level " + orgUnitLevel ); + } + + boolean assignedAtLevel = false; + boolean approvableAtLevel = false; + boolean approvableAtAllLowerLevels = false; + + for ( DataApprovalLevel approvalLevel : getAllDataApprovalLevels() ) + { + Boolean canReadThisLevel = ( approvalLevel.getCategoryOptionGroupSet() == null || securityService.canRead( approvalLevel.getCategoryOptionGroupSet() ) ); + + // + // Test using assignedAtLevel and approvableAtLevel values from the previous (higher) level: + // + Boolean addBecauseOfPreviousLevel = false; + + if ( canReadThisLevel && ( approvableAtLevel // Approve at previous higher level implies unapprove at current level. + || ( assignedAtLevel && mayAcceptAtLowerLevels ) ) ) // Assigned at previous level and mayAcceptAtLowerLevels means may accept here. + { + addBecauseOfPreviousLevel = true; + } + + if ( assignedAtLevel && mayApproveAtLowerLevels ) + { + approvableAtAllLowerLevels = true; + } + + // + // Get new values of assignedAtLevel and approvableAtLevel for the current approval level. + // + assignedAtLevel = canReadThisLevel && userOrgUnitLevels.contains( approvalLevel.getOrgUnitLevel() ); + + approvableAtLevel = canReadThisLevel && ( ( mayApprove && assignedAtLevel ) || approvableAtAllLowerLevels ); + + System.out.println( approvalLevel.getName() + " read " + canReadThisLevel + " assigned " + assignedAtLevel + " approvable " + approvableAtLevel ); + + // + // Test using assignedAtLevel and approvableAtLevel values from the current level: + // + if ( approvableAtLevel || addBecauseOfPreviousLevel ) + { + userDataApprovalLevels.add( approvalLevel ); + } + + } + } + + return userDataApprovalLevels; } public List getDataApprovalLevelsByOrgUnitLevel( int orgUnitLevel ) === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml' --- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml 2014-03-30 04:37:39 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml 2014-04-04 03:49:52 +0000 @@ -421,6 +421,7 @@ + === modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataapproval/DataApprovalLevelServiceTest.java' --- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataapproval/DataApprovalLevelServiceTest.java 2014-04-03 16:03:26 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataapproval/DataApprovalLevelServiceTest.java 2014-04-04 03:49:52 +0000 @@ -33,12 +33,17 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.hisp.dhis.DhisSpringTest; +import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.dataelement.CategoryOptionGroupSet; import org.hisp.dhis.dataelement.DataElementCategoryService; +import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.organisationunit.OrganisationUnitService; +import org.hisp.dhis.user.UserService; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -91,6 +96,11 @@ private DataApprovalLevel level4C; private DataApprovalLevel level4D; + private OrganisationUnit organisationUnitA; + private OrganisationUnit organisationUnitB; + private OrganisationUnit organisationUnitC; + private OrganisationUnit organisationUnitD; + // ------------------------------------------------------------------------- // Set up/tear down // ------------------------------------------------------------------------- @@ -98,6 +108,8 @@ @Override public void setUpTest() throws Exception { + identifiableObjectManager = (IdentifiableObjectManager) getBean( IdentifiableObjectManager.ID ); + userService = (UserService) getBean( UserService.ID ); // --------------------------------------------------------------------- // Add supporting data @@ -136,6 +148,16 @@ level4B = new DataApprovalLevel( "4B", 4, setB ); level4C = new DataApprovalLevel( "4C", 4, setC ); level4D = new DataApprovalLevel( "4D", 4, setD ); + + organisationUnitA = createOrganisationUnit( 'A' ); + organisationUnitB = createOrganisationUnit( 'B', organisationUnitA ); + organisationUnitC = createOrganisationUnit( 'C', organisationUnitB ); + organisationUnitD = createOrganisationUnit( 'D', organisationUnitC ); + + organisationUnitService.addOrganisationUnit( organisationUnitA ); + organisationUnitService.addOrganisationUnit( organisationUnitB ); + organisationUnitService.addOrganisationUnit( organisationUnitC ); + organisationUnitService.addOrganisationUnit( organisationUnitD ); } // ------------------------------------------------------------------------- @@ -411,4 +433,182 @@ assertEquals( "1 - Set B", levels.get( 3 ).getName() ); assertEquals( "1 - Set C", levels.get( 4 ).getName() ); } + + @Test + public void testGetUserDataApprovalLevelsNoAuthorities() throws Exception + { + Set units = new HashSet(); + units.add( organisationUnitB ); + createUserAndInjectSecurityContext( units, false ); + + List levels; + + System.out.println("\n--- NoAuthorities" ); + levels = dataApprovalLevelService.getUserDataApprovalLevels(); + assertEquals( 0, levels.size() ); + + dataApprovalLevelService.addDataApprovalLevel( level4B ); + dataApprovalLevelService.addDataApprovalLevel( level4A ); + dataApprovalLevelService.addDataApprovalLevel( level4 ); + dataApprovalLevelService.addDataApprovalLevel( level3B ); + dataApprovalLevelService.addDataApprovalLevel( level3A ); + dataApprovalLevelService.addDataApprovalLevel( level3 ); + dataApprovalLevelService.addDataApprovalLevel( level2B ); + dataApprovalLevelService.addDataApprovalLevel( level2A ); + dataApprovalLevelService.addDataApprovalLevel( level2 ); + dataApprovalLevelService.addDataApprovalLevel( level1B ); + dataApprovalLevelService.addDataApprovalLevel( level1A ); + dataApprovalLevelService.addDataApprovalLevel( level1 ); + + levels = dataApprovalLevelService.getUserDataApprovalLevels(); + assertEquals( 0, levels.size() ); + } + + @Test + public void testGetUserDataApprovalLevelsApproveHere() throws Exception + { + Set units = new HashSet(); + units.add( organisationUnitB ); + createUserAndInjectSecurityContext( units, false, DataApproval.AUTH_APPROVE ); + + List levels; + + dataApprovalLevelService.addDataApprovalLevel( level4B ); + dataApprovalLevelService.addDataApprovalLevel( level4A ); + dataApprovalLevelService.addDataApprovalLevel( level4 ); + dataApprovalLevelService.addDataApprovalLevel( level3B ); + dataApprovalLevelService.addDataApprovalLevel( level3A ); + dataApprovalLevelService.addDataApprovalLevel( level3 ); + dataApprovalLevelService.addDataApprovalLevel( level2B ); + dataApprovalLevelService.addDataApprovalLevel( level2A ); + dataApprovalLevelService.addDataApprovalLevel( level2 ); + dataApprovalLevelService.addDataApprovalLevel( level1B ); + dataApprovalLevelService.addDataApprovalLevel( level1A ); + dataApprovalLevelService.addDataApprovalLevel( level1 ); + + System.out.println("\n--- ApproveHere" ); + levels = dataApprovalLevelService.getUserDataApprovalLevels(); + for ( DataApprovalLevel level : levels ) + { + System.out.println("Here " + level.getName() ); + } + assertEquals( 4, levels.size() ); + assertEquals( "2", levels.get( 0 ).getName() ); + assertEquals( "2 - Set A", levels.get( 1 ).getName() ); + assertEquals( "2 - Set B", levels.get( 2 ).getName() ); + assertEquals( "3", levels.get( 3 ).getName() ); + } + + @Test + public void testGetUserDataApprovalLevelsApproveLower() throws Exception + { + Set units = new HashSet(); + units.add( organisationUnitB ); + createUserAndInjectSecurityContext( units, false, DataApproval.AUTH_APPROVE_LOWER_LEVELS ); + + List levels; + + dataApprovalLevelService.addDataApprovalLevel( level4B ); + dataApprovalLevelService.addDataApprovalLevel( level4A ); + dataApprovalLevelService.addDataApprovalLevel( level4 ); + dataApprovalLevelService.addDataApprovalLevel( level3B ); + dataApprovalLevelService.addDataApprovalLevel( level3A ); + dataApprovalLevelService.addDataApprovalLevel( level3 ); + dataApprovalLevelService.addDataApprovalLevel( level2B ); + dataApprovalLevelService.addDataApprovalLevel( level2A ); + dataApprovalLevelService.addDataApprovalLevel( level2 ); + dataApprovalLevelService.addDataApprovalLevel( level1B ); + dataApprovalLevelService.addDataApprovalLevel( level1A ); + dataApprovalLevelService.addDataApprovalLevel( level1 ); + + System.out.println("\n--- ApproveLower" ); + levels = dataApprovalLevelService.getUserDataApprovalLevels(); + for ( DataApprovalLevel level : levels ) + { + System.out.println("Lower " + level.getName() ); + } + assertEquals( 8, levels.size() ); + assertEquals( "2 - Set A", levels.get( 0 ).getName() ); + assertEquals( "2 - Set B", levels.get( 1 ).getName() ); + assertEquals( "3", levels.get( 2 ).getName() ); + assertEquals( "3 - Set A", levels.get( 3 ).getName() ); + assertEquals( "3 - Set B", levels.get( 4 ).getName() ); + assertEquals( "4", levels.get( 5 ).getName() ); + assertEquals( "4 - Set A", levels.get( 6 ).getName() ); + assertEquals( "4 - Set B", levels.get( 7 ).getName() ); + } + + @Test + public void testGetUserDataApprovalLevelsApproveHereAndLower() throws Exception + { + Set units = new HashSet(); + units.add( organisationUnitB ); + createUserAndInjectSecurityContext( units, false, DataApproval.AUTH_APPROVE, DataApproval.AUTH_APPROVE_LOWER_LEVELS ); + + List levels; + + dataApprovalLevelService.addDataApprovalLevel( level4B ); + dataApprovalLevelService.addDataApprovalLevel( level4A ); + dataApprovalLevelService.addDataApprovalLevel( level4 ); + dataApprovalLevelService.addDataApprovalLevel( level3B ); + dataApprovalLevelService.addDataApprovalLevel( level3A ); + dataApprovalLevelService.addDataApprovalLevel( level3 ); + dataApprovalLevelService.addDataApprovalLevel( level2B ); + dataApprovalLevelService.addDataApprovalLevel( level2A ); + dataApprovalLevelService.addDataApprovalLevel( level2 ); + dataApprovalLevelService.addDataApprovalLevel( level1B ); + dataApprovalLevelService.addDataApprovalLevel( level1A ); + dataApprovalLevelService.addDataApprovalLevel( level1 ); + + System.out.println("\n--- HereAndLower" ); + levels = dataApprovalLevelService.getUserDataApprovalLevels(); + for ( DataApprovalLevel level : levels ) + { + System.out.println("HereAndLower " + level.getName() ); + } + assertEquals( 9, levels.size() ); + assertEquals( "2", levels.get( 0 ).getName() ); + assertEquals( "2 - Set A", levels.get( 1 ).getName() ); + assertEquals( "2 - Set B", levels.get( 2 ).getName() ); + assertEquals( "3", levels.get( 3 ).getName() ); + assertEquals( "3 - Set A", levels.get( 4 ).getName() ); + assertEquals( "3 - Set B", levels.get( 5 ).getName() ); + assertEquals( "4", levels.get( 6 ).getName() ); + assertEquals( "4 - Set A", levels.get( 7 ).getName() ); + assertEquals( "4 - Set B", levels.get( 8 ).getName() ); + } + + @Test + public void testGetUserDataApprovalLevelsAcceptLower() throws Exception + { + Set units = new HashSet(); + units.add( organisationUnitB ); + createUserAndInjectSecurityContext( units, false, DataApproval.AUTH_ACCEPT_LOWER_LEVELS ); + + List levels; + + dataApprovalLevelService.addDataApprovalLevel( level4B ); + dataApprovalLevelService.addDataApprovalLevel( level4A ); + dataApprovalLevelService.addDataApprovalLevel( level4 ); + dataApprovalLevelService.addDataApprovalLevel( level3B ); + dataApprovalLevelService.addDataApprovalLevel( level3A ); + dataApprovalLevelService.addDataApprovalLevel( level3 ); + dataApprovalLevelService.addDataApprovalLevel( level2B ); + dataApprovalLevelService.addDataApprovalLevel( level2A ); + dataApprovalLevelService.addDataApprovalLevel( level2 ); + dataApprovalLevelService.addDataApprovalLevel( level1B ); + dataApprovalLevelService.addDataApprovalLevel( level1A ); + dataApprovalLevelService.addDataApprovalLevel( level1 ); + + System.out.println("\n--- AcceptLower" ); + levels = dataApprovalLevelService.getUserDataApprovalLevels(); + for ( DataApprovalLevel level : levels ) + { + System.out.println("AcceptLower " + level.getName() ); + } + assertEquals( 3, levels.size() ); + assertEquals( "2 - Set A", levels.get( 0 ).getName() ); + assertEquals( "2 - Set B", levels.get( 1 ).getName() ); + assertEquals( "3", levels.get( 2 ).getName() ); + } } === modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/InputUtils.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/InputUtils.java 2014-04-01 17:04:30 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/utils/InputUtils.java 2014-04-04 03:49:52 +0000 @@ -167,15 +167,18 @@ for ( String id : cog ) { - CategoryOptionGroup categoryOptionGroup = categoryService.getCategoryOptionGroup( id ); - - if ( categoryOptionGroup == null ) + if ( "undefined".compareTo( id ) != 0 ) { - ContextUtils.conflictResponse( response, "Illegal category option group identifier: " + cog ); - return null; + CategoryOptionGroup categoryOptionGroup = categoryService.getCategoryOptionGroup( id ); + + if ( categoryOptionGroup == null ) + { + ContextUtils.conflictResponse( response, "Illegal category option group identifier: " + cog ); + return null; + } + + groups.add( categoryOptionGroup ); } - - groups.add( categoryOptionGroup ); } } === modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataApproval.js' --- dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataApproval.js 2014-04-03 19:02:51 +0000 +++ dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataApproval.js 2014-04-04 03:49:52 +0000 @@ -58,7 +58,7 @@ $.each( json.categoryOptionGroups, function( index, group ) { html += ""; } ); - + $( "#categoryOptionGroupSection" ).show(); $( "#categoryOptionGroupId" ).html( html ); } );