← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 17126: Implemented blueprint follow-up-analysis-bu-org-unit: Added orgunit selection tree to followup an...

 

Merge authors:
  Halvdan Hoem Grelland (halvdanhg)
------------------------------------------------------------
revno: 17126 [merge]
committer: Halvdan Hoem Grelland <halvdanhg@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2014-10-15 16:28:22 +0200
message:
  Implemented blueprint follow-up-analysis-bu-org-unit: Added orgunit selection tree to followup analysis. Now fetches datavalues based on selected parent orgunit source. Separated FollowupAnalysisService from DataAnalysisService since interfaces no longer match. Separated followup analysis display logic from datanalysis to accommodate changes.
removed:
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followUpAnalysisForm.vm
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/DefaultFollowupAnalysisService.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetFollowupAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupAnalysisForm.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupResult.vm
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.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/resources/struts.xml
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/index.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/dataAnalysis.js
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/menu.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/searchResult.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/dataanalysis/DataAnalysisStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java	2014-10-15 13:58:41 +0000
@@ -93,11 +93,14 @@
      */
     Collection<DeflatedDataValue> getDeflatedDataValues( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo,
         Collection<Period> periods, Map<Integer, Integer> lowerBoundMap, Map<Integer, Integer> upperBoundMap );
-    
+
     /**
-     * Returns a collection of DeflatedDataValues which are marked for followup.
-     * 
+     * Returns a collection of DeflatedDataValues which are marked for followup and
+     * whose source OrganisationUnit is equal or subordinate to the given OrganisationUnit.
+     *
+     * @param organisationUnit the source OrganisationUnit.
+     * @param limit the maximum number of DeflatedDataValues to return.
      * @return a collection of DeflatedDataValues.
      */
-    Collection<DeflatedDataValue> getDataValuesMarkedForFollowup();
+    Collection<DeflatedDataValue> getFollowupDataValues( OrganisationUnit organisationUnit, int limit );
 }

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java	2014-10-15 14:08:47 +0000
@@ -0,0 +1,42 @@
+package org.hisp.dhis.dataanalysis;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.datavalue.DeflatedDataValue;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+
+import java.util.Collection;
+
+/**
+ * @author Halvdan Hoem Grelland
+ */
+public interface FollowupAnalysisService
+{
+    public Collection<DeflatedDataValue> getFollowupDataValues( OrganisationUnit organisationUnit, int limit );
+}

=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/DefaultFollowupAnalysisService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/DefaultFollowupAnalysisService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/DefaultFollowupAnalysisService.java	2014-10-15 14:08:47 +0000
@@ -0,0 +1,67 @@
+package org.hisp.dhis.dataanalysis;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.hisp.dhis.datavalue.DeflatedDataValue;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+
+/**
+ * @author Halvdan Hoem Grelland
+ */
+public class DefaultFollowupAnalysisService
+    implements FollowupAnalysisService
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private DataAnalysisStore dataAnalysisStore;
+    
+    public void setDataAnalysisStore( DataAnalysisStore dataAnalysisStore )
+    {
+        this.dataAnalysisStore = dataAnalysisStore;
+    }
+
+    // -------------------------------------------------------------------------
+    // FollowupAnalysisService implementation
+    // -------------------------------------------------------------------------
+
+    public Collection<DeflatedDataValue> getFollowupDataValues( OrganisationUnit organisationUnit, int limit )
+    {
+        if( organisationUnit == null || limit < 1 )
+        {
+            return new ArrayList<>();
+        }
+
+        return dataAnalysisStore.getFollowupDataValues( organisationUnit, limit );
+    }
+}

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java	1970-01-01 00:00:00 +0000
@@ -1,65 +0,0 @@
-package org.hisp.dhis.dataanalysis;
-
-/*
- * Copyright (c) 2004-2014, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * Neither the name of the HISP project nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import java.util.Collection;
-
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.datavalue.DeflatedDataValue;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.period.Period;
-
-/**
- * @author Lars Helge Overland
- */
-public class FollowupAnalysisService
-    implements DataAnalysisService
-{
-    // -------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------
-
-    private DataAnalysisStore dataAnalysisStore;
-    
-    public void setDataAnalysisStore( DataAnalysisStore dataAnalysisStore )
-    {
-        this.dataAnalysisStore = dataAnalysisStore;
-    }
-
-    // -------------------------------------------------------------------------
-    // DataAnalysisService implementation
-    // -------------------------------------------------------------------------
-
-    @Override
-    public Collection<DeflatedDataValue> analyse( Collection<OrganisationUnit> organisationUnits,
-        Collection<DataElement> dataElements, Collection<Period> periods, Double stdDevFactor )
-    {
-        return dataAnalysisStore.getDataValuesMarkedForFollowup();
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java	2014-10-13 16:57:06 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java	2014-10-15 13:58:41 +0000
@@ -42,7 +42,6 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hisp.dhis.dataanalysis.DataAnalysisService;
 import org.hisp.dhis.dataanalysis.DataAnalysisStore;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
@@ -59,6 +58,7 @@
 
 /**
  * @author Lars Helge Overland
+ * @author Halvdan Hoem Grelland
  */
 public class JdbcDataAnalysisStore
     implements DataAnalysisStore
@@ -243,12 +243,15 @@
         
         return jdbcTemplate.query( sql, new DeflatedDataValueNameMinMaxRowMapper( lowerBoundMap, upperBoundMap, null ) );
     }
-    
-    public Collection<DeflatedDataValue> getDataValuesMarkedForFollowup()
+
+    @Override
+    public Collection<DeflatedDataValue> getFollowupDataValues( OrganisationUnit organisationUnit, int limit )
     {
-        final String sql =
+        final String idLevelColumn = "idlevel" + organisationUnit.getOrganisationUnitLevel();
+
+        String sql =
             "select dv.dataelementid, dv.periodid, dv.sourceid, dv.categoryoptioncomboid, dv.value, " +
-            "dv.storedby, dv.lastupdated, dv.created, dv.comment, dv.followup, mm.minimumvalue, mm.maximumvalue, de.name as dataelementname, " +
+            "dv.storedby, dv.lastupdated, dv.created, dv.comment, dv.followup, mm.minimumvalue, mm.maximumvalue, de.name AS dataelementname, " +
             "pe.startdate, pe.enddate, pt.name AS periodtypename, ou.name AS sourcename, cc.categoryoptioncomboname " +
             "from datavalue dv " +
             "left join minmaxdataelement mm on (dv.sourceid = mm.sourceid and dv.dataelementid = mm.dataelementid and dv.categoryoptioncomboid = mm.categoryoptioncomboid) " +
@@ -257,9 +260,11 @@
             "join periodtype pt on pe.periodtypeid = pt.periodtypeid " +
             "left join organisationunit ou on ou.organisationunitid = dv.sourceid " +
             "left join _categoryoptioncomboname cc on dv.categoryoptioncomboid = cc.categoryoptioncomboid " +
-            "where dv.followup = true " +
-            statementBuilder.limitRecord( 0, DataAnalysisService.MAX_OUTLIERS );
+            "inner join _orgunitstructure ous on ous.organisationunitid = dv.sourceid " +
+            "where ous." + idLevelColumn + " = " + organisationUnit.getId() + " " +
+            "and dv.followup = true " +
+            statementBuilder.limitRecord( 0, limit );
         
-        return jdbcTemplate.query( sql, new DeflatedDataValueNameMinMaxRowMapper() );        
+        return jdbcTemplate.query( sql, new DeflatedDataValueNameMinMaxRowMapper() );
     }
 }

=== 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-10-15 04:17:05 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2014-10-15 13:58:41 +0000
@@ -556,7 +556,7 @@
     <property name="batchHandlerFactory" ref="batchHandlerFactory" />
   </bean>
 
-  <bean id="org.hisp.dhis.dataanalysis.FollowupAnalysisService" class="org.hisp.dhis.dataanalysis.FollowupAnalysisService">
+  <bean id="org.hisp.dhis.dataanalysis.FollowupAnalysisService" class="org.hisp.dhis.dataanalysis.DefaultFollowupAnalysisService">
     <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.DataAnalysisStore" />
   </bean>
 
@@ -575,12 +575,6 @@
           </key>
           <ref bean="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" />
         </entry>
-        <entry>
-          <key>
-            <value>followup</value>
-          </key>
-          <ref bean="org.hisp.dhis.dataanalysis.FollowupAnalysisService" />
-        </entry>
       </map>
     </property>
   </bean>

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java	2014-10-10 16:14:09 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java	2014-10-13 15:29:28 +0000
@@ -210,7 +210,7 @@
 
         DataAnalysisService service = serviceProvider.provide( key );
 
-        if ( service != null ) // Follow-up analysis has no input params
+        if ( service != null )
         {
             dataValues = service.analyse( orgUnits, dataElements, periods, standardDeviation );
 

=== added file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetFollowupAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetFollowupAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetFollowupAction.java	2014-10-15 14:08:47 +0000
@@ -0,0 +1,84 @@
+package org.hisp.dhis.validationrule.action.dataanalysis;
+
+import com.opensymphony.xwork2.Action;
+import org.hisp.dhis.dataanalysis.DataAnalysisService;
+import org.hisp.dhis.dataanalysis.FollowupAnalysisService;
+import org.hisp.dhis.datavalue.DeflatedDataValue;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.oust.manager.SelectionTreeManager;
+import org.hisp.dhis.util.SessionUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Halvdan Hoem Grelland
+ */
+public class GetFollowupAction
+    implements Action
+{
+    private static final String KEY_ANALYSIS_DATA_VALUES = "analysisDataValues";
+
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private FollowupAnalysisService followupAnalysisService;
+
+    public void setFollowupAnalysisService( FollowupAnalysisService followupAnalysisService )
+    {
+        this.followupAnalysisService = followupAnalysisService;
+    }
+
+    private SelectionTreeManager selectionTreeManager;
+
+    public void setSelectionTreeManager( SelectionTreeManager selectionTreeManager )
+    {
+        this.selectionTreeManager = selectionTreeManager;
+    }
+
+    // -------------------------------------------------------------------------
+    // Output
+    // -------------------------------------------------------------------------
+
+    private Collection<DeflatedDataValue> dataValues = new ArrayList<>();
+
+    public Collection<DeflatedDataValue> getDataValues()
+    {
+        return dataValues;
+    }
+
+    private boolean maxExceeded;
+
+    public boolean getMaxExceeded()
+    {
+        return maxExceeded;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute() throws Exception
+    {
+        OrganisationUnit orgUnit = selectionTreeManager.getReloadedSelectedOrganisationUnit();
+
+        if( orgUnit != null )
+        {
+            dataValues = followupAnalysisService.getFollowupDataValues( orgUnit, DataAnalysisService.MAX_OUTLIERS + 1 ); // +1 to detect overflow
+
+            maxExceeded = dataValues.size() > DataAnalysisService.MAX_OUTLIERS;
+        }
+        else
+        {
+            dataValues = new ArrayList<>();
+
+            maxExceeded = false;
+        }
+
+        SessionUtils.setSessionVar( KEY_ANALYSIS_DATA_VALUES, dataValues );
+
+        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	2014-06-20 10:57:40 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml	2014-10-13 16:03:06 +0000
@@ -201,4 +201,11 @@
     <property name="selectionTreeManager" ref="org.hisp.dhis.oust.manager.SelectionTreeManager" />
   </bean>
 
+  <bean id="org.hisp.dhis.validationrule.action.dataanalysis.GetFollowupAction"
+    class="org.hisp.dhis.validationrule.action.dataanalysis.GetFollowupAction"
+    scope="prototype">
+    <property name="followupAnalysisService" ref="org.hisp.dhis.dataanalysis.FollowupAnalysisService" />
+    <property name="selectionTreeManager" ref="org.hisp.dhis.oust.manager.SelectionTreeManager" />
+  </bean>
+
 </beans>

=== 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-08-28 12:01:44 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties	2014-10-15 13:58:41 +0000
@@ -91,8 +91,6 @@
 intro_minmaxoutlier_analysis=Analyze potential outlier values based on min and max values. Outlier values can be examined and marked for follow-up.
 intro_gap_analysis=Perform analysis of potential missing values, referred to as gaps. Missing values can be entered or marked for follow-up.
 intro_followup_analysis=View or edit data values marked for further follow-up during data entry or analysis.
-available_data_elements=Available data elements
-followup_analysis=Follow-up Analysis
 value_must_be_a_number=Value must be a number
 value_is_lower_than_min_value=Value is lower than minimum value
 value_is_higher_than_max_value=Value is higher than maximum value
@@ -157,3 +155,4 @@
 skip_if_any_value_is_missing=Skip if any value is missing
 skip_if_all_values_are_missing=Skip if all values are missing
 never_skip=Never skip
+no_organisation_unit_selected=No organisation unit selected

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml	2014-07-26 19:08:32 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml	2014-10-13 16:03:06 +0000
@@ -180,11 +180,21 @@
       <param name="requiredAuthorities">F_RUN_VALIDATION</param>
     </action>
 
-    <action name="viewFollowUpAnalysisForm" class="org.hisp.dhis.validationrule.action.NoAction">
+    <action name="viewFollowupAnalysisForm" class="org.hisp.dhis.validationrule.action.NoAction">
       <result name="success" type="velocity">/main.vm</result>
-      <param name="page">/dhis-web-validationrule/followUpAnalysisForm.vm</param>
+      <param name="page">/dhis-web-validationrule/followupAnalysisForm.vm</param>
       <param name="menu">/dhis-web-validationrule/menu.vm</param>
-      <param name="javascripts">javascript/dataAnalysis.js</param>
+      <param name="javascripts">
+        ../dhis-web-commons/oust/oust.js,
+        ../dhis-web-commons/javascripts/lists.js,
+        javascript/dataAnalysis.js
+      </param>
+      <interceptor-ref name="organisationUnitTreeStack" />
+      <param name="requiredAuthorities">F_RUN_VALIDATION</param>
+    </action>
+
+    <action name="getFollowup" class="org.hisp.dhis.validationrule.action.dataanalysis.GetFollowupAction">
+      <result name="success" type="velocity">/dhis-web-validationrule/followupResult.vm</result>
       <param name="requiredAuthorities">F_RUN_VALIDATION</param>
     </action>
 

=== removed file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followUpAnalysisForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followUpAnalysisForm.vm	2013-10-08 19:10:40 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followUpAnalysisForm.vm	1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-<script type="text/javascript">
-	jQuery(document).ready(function() {
-		getFollowUpAnalysis();
-	});
-
-	var i18n_analysing_please_wait = '$encoder.jsEscape( $i18n.getString( "analysing_data" ) , "'")';
-</script>
-
-<h3>$i18n.getString( "followup_analysis" ) #openHelp( "followupAnalysis" )</h3>
-
-<span id="message"></span>
-<div id="analysisResult"></div>

=== added file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupAnalysisForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupAnalysisForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupAnalysisForm.vm	2014-10-14 15:37:28 +0000
@@ -0,0 +1,56 @@
+<script type="text/javascript">
+  var i18n_analysing_please_wait = '$encoder.jsEscape( $i18n.getString( "analysing_data" ) , "'")';
+  var i18n_no_organisation_unit_selected = '$encoder.jsEscape( $i18n.getString( "no_organisation_unit_selected" ), "'" )';
+
+  var NUM_RESULT_VALUES = 0; ## Document global, used in followupResult.vm
+
+  $( document ).ready( function() {
+    selectionTreeSelection.setMultipleSelectionAllowed( false );
+    selectionTreeSelection.setListenerFunction( getFollowupAnalysis );
+    selectionTree.clearSelectedOrganisationUnits();
+    selectionTree.buildSelectionTree();
+
+    $( "#info" ).html( i18n_no_organisation_unit_selected );
+    $( "#downloadButtons input:button" ).attr( "disabled", true );
+    $( "#controls" ).show();
+  });
+</script>
+
+<h3>$i18n.getString( "followup_analysis" ) #openHelp( "followupAnalysis" )</h3>
+<div style="position: relative; bottom: 10px;">
+  <div>
+      <table>
+        <tr>
+          <th>$i18n.getString( "select_parent_organisation_unit" )</th>
+        </tr>
+        <tr>
+          <td>
+            <div id="selectionTree" style="width: 350px;height:150px;overflow:auto;"></div>
+          </td>
+        </tr>
+      </table>
+  </div>
+  <div id="controls">
+    <div id="info"></div>
+    <div id="downloadButtons">
+      <input type="button" value="$i18n.getString( 'get_report_as_pdf' )" style="width:140px" onclick="exportAnalysisResult( 'pdf' )">
+      <input type="button" value="$i18n.getString( 'get_report_as_xls' )" style="width:140px" onclick="exportAnalysisResult( 'xls' )">
+      <input type="button" value="$i18n.getString( 'get_report_as_csv' )" style="width:140px" onclick="exportAnalysisResult( 'cvs' )">
+    </div>
+  </div>
+</div>
+<div id="analysisResult"></div>
+
+<style>
+  #controls
+  {
+    padding-top: 14px;
+    margin-left: 380px;
+    position: absolute;
+    bottom: 0;
+  }
+  #info
+  {
+    width: initial;
+  }
+</style>

=== added file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupResult.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupResult.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/followupResult.vm	2014-10-15 13:10:24 +0000
@@ -0,0 +1,96 @@
+<script type="text/javascript">
+  var i18n_values_found = '$encoder.jsEscape( $i18n.getString( "values_found" ), "'")';
+  var i18n_max_values_exceeded = '$encoder.jsEscape( $i18n.getString( "max_values_exceeded" ), "'" )';
+  var i18n_no_values_found = '$encoder.jsEscape( $i18n.getString( "no_values_found" ), "'" )';
+  var i18n_value_must_be_a_number = '$encoder.jsEscape( $i18n.getString( "value_must_be_a_number" ) , "'" )';
+  var i18n_value_is_lower_than_min_value = '$encoder.jsEscape( $i18n.getString( "value_is_lower_than_min_value" ) , "'" )';
+  var i18n_value_is_higher_than_max_value = '$encoder.jsEscape( $i18n.getString( "value_is_higher_than_max_value" ) , "'" )';
+  var i18n_mark_value_for_followup = '$encoder.jsEscape( $i18n.getString( "mark_value_for_followup" ) , "'" )';
+  var i18n_unmark_value_for_followup = '$encoder.jsEscape( $i18n.getString( "unmark_value_for_followup" ) , "'" )';
+
+  $( document ).ready( function() {
+    tableSorter( 'listTable' );
+    setTableStyles();
+
+    NUM_RESULT_VALUES = $dataValues.size();
+
+    var maxExceeded = $maxExceeded;
+
+    if( NUM_RESULT_VALUES == 0 )
+    {
+      $( "#analysisResult" ).hide();
+      $( "#downloadButtons input:button" ).attr( "disabled", true );
+      $( "#info" ).show();
+      if( selectedOrganisationUnit.length === 0 )
+      {
+        $( "#info" ).html( i18n_no_organisation_unit_selected );
+      }
+      else
+      {
+        $( "#info" ).html( i18n_no_values_found );
+      }
+    }
+    else if ( maxExceeded )
+    {
+      $( "#info" ).html( i18n_max_values_exceeded );
+      $( "#downloadButtons input:button" ).attr( "disabled", false );
+      $( "#analysisResult" ).show();
+      $( "#controls" ).show();
+    }
+    else
+    {
+      $( "#info" ).html( NUM_RESULT_VALUES + " " + i18n_values_found );
+      $( "#downloadButtons input:button" ).attr( "disabled", false );
+      $( "#analysisResult" ).show();
+      $( "#controls" ).show();
+    }
+  });
+</script>
+
+<table class="listTable" id="listTable" style="width:100%;">
+  <thead>
+    <tr>
+      <th>$i18n.getString( "data_element" )</th>
+      <th>$i18n.getString( "organisation_unit" )</th>
+      <th class="{sorter: false}">$i18n.getString( "period" )</th>
+      <th style="text-align:center" class="{sorter: false}">$i18n.getString( "min" )</th>
+      <th style="width: 100px; text-align:center" class="{sorter: false}">$i18n.getString( "value" )</th>
+      <th style="text-align:center" class="{sorter: false}">$i18n.getString( "max" )</th>
+      <th style="text-align:center" class="{sorter: false}">$i18n.getString( "mark" )</th>
+    </tr>
+  </thead>
+  #set( $count = 0 )
+  <tbody id="list">
+  #foreach( $value in $dataValues )
+  #set( $count = $count + 1 )
+  <tr>
+    <td><span id="value-${count}-name">$encoder.htmlEncode( $value.dataElementName ) $encoder.htmlEncode( $value.categoryOptionComboNameParsed )</span></td>
+
+    <td>$encoder.htmlEncode( $value.sourceName )</td>
+
+    <td value="$format.formatDate($value.period.startDate)">$format.formatPeriod( $value.period )</td>
+
+    <td style="text-align:center">$value.min</td>
+
+    <td style="width:100px; text-align:center;">$encoder.htmlEncode( $value.value )
+      <input type="hidden" id="value-${count}-de" value="$value.dataElementId">
+      <input type="hidden" id="value-${count}-pe" value="$value.periodId">
+      <input type="hidden" id="value-${count}-ou" value="$value.sourceId">
+      <input type="hidden" id="value-${count}-coc" value="$value.categoryOptionComboId">
+      <input type="hidden" id="value-${count}-min" value="$value.min">
+      <input type="hidden" id="value-${count}-max" value="$value.max">
+    </td>
+
+    <td style="text-align:center">$value.max</td>
+
+    <td style="text-align:center">
+        #if ( $value.followup )
+          <img id="value-${count}-followUp" src="../images/marked.png" onclick="markFollowup($count)" style="cursor:pointer">
+        #else
+          <img id="value-${count}-followUp" src="../images/unmarked.png" onclick="markFollowup($count)" style="cursor:pointer">
+        #end
+    </td>
+  </tr>
+  #end
+  </tbody>
+</table>
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/index.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/index.vm	2014-07-26 19:08:32 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/index.vm	2014-10-13 16:03:06 +0000
@@ -6,5 +6,5 @@
     #introListImgItem( "showRunValidationForm.action" "validation_rule_analysis" "validationanalysis" )
     #introListImgItem( "viewAnalysisForm.action?key=stddevoutlier" "stddevoutlier_analysis" "validationanalysis" )
     #introListImgItem( "viewAnalysisForm.action?key=minmaxoutlier" "minmaxoutlier_analysis" "validationanalysis" )
-    #introListImgItem( "viewFollowUpAnalysisForm.action" "followup_analysis" "validationanalysis" )
+    #introListImgItem( "viewFollowupAnalysisForm.action" "followup_analysis" "validationanalysis" )
 </ul>
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/dataAnalysis.js'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/dataAnalysis.js	2014-08-18 08:54:32 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/dataAnalysis.js	2014-10-15 13:10:24 +0000
@@ -20,11 +20,11 @@
         {
             if ( json.response == "success" )
             {
-            	analyseData();
+                analyseData();
             }
             else
             {
-            	setHeaderDelayMessage( json.message );
+                setHeaderDelayMessage( json.message );
                 $( '#startButton').removeAttr( 'disabled' );
             }
         } );
@@ -35,13 +35,13 @@
 {
     if ( $( "#fromDate" ).val().length == 0 )
     {
-    	setHeaderDelayMessage( i18n_specify_a_start_date );
+        setHeaderDelayMessage( i18n_specify_a_start_date );
         return false;
     }
 
     if ( $( "#toDate" ).val().length == 0 )
     {
-    	setHeaderDelayMessage( i18n_specify_an_ending_date );
+        setHeaderDelayMessage( i18n_specify_an_ending_date );
         return false;
     }
 
@@ -49,7 +49,7 @@
 
     if ( dataSets.options.length == 0 )
     {
-    	setHeaderDelayMessage( i18n_specify_dataset );
+        setHeaderDelayMessage( i18n_specify_dataset );
         return false;
     }
 
@@ -75,27 +75,13 @@
         $( "div#analysisResult" ).show();
         $( "div#analysisResult" ).html( data );
 
-        $( '#startButton').removeAttr( 'disabled' );
-    } );
-}
-
-function getFollowUpAnalysis()
-{
-    setHeaderWaitMessage( i18n_analysing_please_wait );
-
-    var url = "getAnalysis.action?key=followup";
-
-    $.get( url, function( data )
-    {
-        hideHeaderMessage();
-        $( "div#analysisResult" ).show();
-        $( "div#analysisResult" ).html( data );
+        $( "#startButton" ).removeAttr( 'disabled' );
     } );
 }
 
 function displayAnalysisInput()
 {
-	$( 'div#analysisInput' ).show();
+    $( 'div#analysisInput' ).show();
     $( 'div#analysisResult' ).empty().hide();
 }
 
@@ -105,31 +91,46 @@
     window.location.href = url;
 }
 
-function markFollowUp( valueId )
-{	
+function markFollowup( valueId )
+{
     var dataElementId = $( '#value-' + valueId + '-de' ).val();
     var categoryOptionComboId = $( '#value-' + valueId + '-coc' ).val();
     var periodId = $( '#value-' + valueId + '-pe' ).val();
     var sourceId = $( '#value-' + valueId + '-ou' ).val();
     
     $.ajax( {
-    	url: 'markForFollowup.action',
-    	data: { dataElementId:dataElementId, periodId:periodId, sourceId:sourceId, categoryOptionComboId:categoryOptionComboId },
-    	type: 'POST',
-    	dataType: 'json',
-    	success: function( json )
-		{
-            var $image = $( '#value-' + valueId + '-followUp' );
-			
-            if ( json.message == "marked" )
-		    {
-		        $image.attr( "src", "../images/marked.png" );
-		        $image.attr( "title", i18n_unmark_value_for_followup );
-		    }
-		    else if ( json.message == "unmarked" )
-		    {
-		        $image.attr( "src", "../images/unmarked.png" );
-		        $image.attr( "title", i18n_mark_value_for_followup );   
-		    }
-		} } );
+      url: 'markForFollowup.action',
+      data: { dataElementId:dataElementId, periodId:periodId, sourceId:sourceId, categoryOptionComboId:categoryOptionComboId },
+      type: 'POST',
+      dataType: 'json',
+      success: function( json )
+      {
+        var $image = $( '#value-' + valueId + '-followUp' );
+
+        if ( json.message == "marked" )
+        {
+            $image.attr( "src", "../images/marked.png" );
+            $image.attr( "title", i18n_unmark_value_for_followup );
+        }
+        else if ( json.message == "unmarked" )
+        {
+            $image.attr( "src", "../images/unmarked.png" );
+            $image.attr( "title", i18n_mark_value_for_followup );
+        }
+      }
+    } );
+}
+
+function getFollowupAnalysis()
+{
+    setHeaderWaitMessage( i18n_analysing_please_wait );
+
+    var url = "getFollowup.action";
+
+    $.get( url, function( data )
+    {
+        hideHeaderMessage();
+        $( "div#analysisResult" ).show();
+        $( "div#analysisResult" ).html( data );
+    } );
 }

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/menu.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/menu.vm	2014-07-26 19:08:32 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/menu.vm	2014-10-13 16:03:06 +0000
@@ -10,5 +10,5 @@
 	<li><a href="showRunValidationForm.action">$i18n.getString( "validation_rule_analysis" )&nbsp;</a></li>
     <li><a href="viewAnalysisForm.action?key=stddevoutlier">$i18n.getString( "stddevoutlier_analysis" )&nbsp;</a></li>
     <li><a href="viewAnalysisForm.action?key=minmaxoutlier">$i18n.getString( "minmaxoutlier_analysis" )&nbsp;</a></li>
-    <li><a href="viewFollowUpAnalysisForm.action">$i18n.getString( "followup_analysis" )&nbsp;</a></li>
+    <li><a href="viewFollowupAnalysisForm.action">$i18n.getString( "followup_analysis" )&nbsp;</a></li>
 </ul>

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/searchResult.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/searchResult.vm	2014-06-20 10:57:40 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/searchResult.vm	2014-10-13 15:33:08 +0000
@@ -65,9 +65,9 @@
 		
 		<td style="text-align:center">
 		#if ( $value.followup )
-			<img id="value-${count}-followUp" src="../images/marked.png" onclick="markFollowUp($count)" style="cursor:pointer">
+			<img id="value-${count}-followUp" src="../images/marked.png" onclick="markFollowup($count)" style="cursor:pointer">
 		#else
-		    <img id="value-${count}-followUp" src="../images/unmarked.png" onclick="markFollowUp($count)" style="cursor:pointer">
+		    <img id="value-${count}-followUp" src="../images/unmarked.png" onclick="markFollowup($count)" style="cursor:pointer">
 		#end
 		</td>		
 	</tr>