← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 9043: merged with multiorg-branch

 

Merge authors:
  Morten Olav Hansen (mortenoh)
------------------------------------------------------------
revno: 9043 [merge]
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2012-11-15 11:52:24 +0100
message:
  merged with multiorg-branch
added:
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/multiOrgSectionForm.vm
modified:
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/lists.js
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/ouwt.js
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetDataValuesForDataSetAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/LoadFormAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/PageInitAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/RegisterCompleteDataSetAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/UndoCompleteDataSetAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/menu.vm
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseDataValues.vm
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.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-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/lists.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/lists.js	2012-04-14 18:32:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/lists.js	2012-11-09 21:25:34 +0000
@@ -74,17 +74,9 @@
  * @param listId the id of the list.
  */
 function clearListById( listId ) {
-    var list = document.getElementById( listId );
-    clearList( list );
-}
-
-/**
- * Clears the list.
- * 
- * @param list the list.
- */
-function clearList( list ) {
-    list.options.length = 0;
+    // var list = document.getElementById( listId );
+    // clearList( list );
+    $('#' + listId).children().remove();
 }
 
 /**

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/ouwt.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/ouwt.js	2012-10-31 10:15:09 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/ouwt.js	2012-11-12 10:22:34 +0000
@@ -37,6 +37,7 @@
     var rootUnselectAllowed = false;
     var autoSelectRoot = true;
     var realRoot = true;
+    var includeChildren = false;
 
     this.setListenerFunction = function ( listenerFunction_, skipInitialCall )
     {
@@ -71,6 +72,11 @@
         autoSelectRoot = autoSelect;
     };
 
+    this.setIncludeChildren = function( children )
+    {
+        includeChildren = children;
+    };
+
     this.load = function ()
     {
         function sync_and_reload()
@@ -283,6 +289,11 @@
         $.post( organisationUnitTreePath + "clearselected.action" ).complete( this.responseReceived );
     };
 
+    this.getSelected = function()
+    {
+        return JSON.parse( sessionStorage[getTagId( "Selected" )] );
+    };
+
     this.select = function ( unitId )
     {
         var $linkTag = $( "#" + getTagId( unitId ) ).find( "a" ).eq( 0 );
@@ -398,6 +409,7 @@
         }
 
         var selected = [];
+        var children = [];
 
         if ( sessionStorage[getTagId( "Selected" )] != null )
         {
@@ -418,12 +430,18 @@
         }
         else
         {
+            // we only support includeChildren for single selects
+            if( includeChildren )
+            {
+                children = organisationUnits[selected].c;
+            }
+
             var name = organisationUnits[selected].n;
             ids.push( +selected );
             names.push( name );
         }
 
-        listenerFunction( ids, names );
+        listenerFunction( ids, names, children );
     };
 
     function getTagId( unitId )

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetDataValuesForDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetDataValuesForDataSetAction.java	2012-02-21 18:45:10 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/GetDataValuesForDataSetAction.java	2012-11-12 12:47:02 +0000
@@ -41,8 +41,10 @@
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodType;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
+import java.util.Set;
 
 /**
  * @author Lars Helge Overland
@@ -114,18 +116,30 @@
         this.organisationUnitId = organisationUnitId;
     }
 
+    private boolean multiOrganisationUnit;
+
+    public void setMultiOrganisationUnit( boolean multiOrganisationUnit )
+    {
+        this.multiOrganisationUnit = multiOrganisationUnit;
+    }
+
+    public boolean isMultiOrganisationUnit()
+    {
+        return multiOrganisationUnit;
+    }
+
     // -------------------------------------------------------------------------
     // Output
     // -------------------------------------------------------------------------
 
-    private Collection<DataValue> dataValues;
+    private Collection<DataValue> dataValues = new ArrayList<DataValue>();
 
     public Collection<DataValue> getDataValues()
     {
         return dataValues;
     }
 
-    private Collection<MinMaxDataElement> minMaxDataElements;
+    private Collection<MinMaxDataElement> minMaxDataElements = new ArrayList<MinMaxDataElement>();
 
     public Collection<MinMaxDataElement> getMinMaxDataElements()
     {
@@ -167,20 +181,32 @@
     public String execute()
     {
         OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( organisationUnitId );
+        Set<OrganisationUnit> children = organisationUnit.getChildren();
+
         DataSet dataSet = dataSetService.getDataSet( dataSetId );
         Period period = PeriodType.createPeriodExternalId( periodId );
 
         // ---------------------------------------------------------------------
-        // Data values
-        // ---------------------------------------------------------------------
-
-        dataValues = dataValueService.getDataValues( organisationUnit, period, dataSet.getDataElements() );
-
-        // ---------------------------------------------------------------------
-        // Min-max data elements
-        // ---------------------------------------------------------------------
-
-        minMaxDataElements = minMaxDataElementService.getMinMaxDataElements( organisationUnit, dataSet.getDataElements() );
+        // Data values & Min-max data elements
+        // ---------------------------------------------------------------------
+
+        if ( !multiOrganisationUnit )
+        {
+            dataValues = dataValueService.getDataValues( organisationUnit, period, dataSet.getDataElements() );
+            minMaxDataElements = minMaxDataElementService.getMinMaxDataElements( organisationUnit, dataSet.getDataElements() );
+        }
+        else
+        {
+            for ( OrganisationUnit ou : children )
+            {
+                // make sure that the orgUnit have this dataSet (the same data elements can be contained in another dataSet)
+                if ( ou.getDataSets().contains( dataSet ) )
+                {
+                    dataValues.addAll( dataValueService.getDataValues( ou, period, dataSet.getDataElements() ) );
+                    minMaxDataElements.addAll( minMaxDataElementService.getMinMaxDataElements( ou, dataSet.getDataElements() ) );
+                }
+            }
+        }
 
         // ---------------------------------------------------------------------
         // Data set completeness info
@@ -188,16 +214,44 @@
 
         if ( dataSet != null && period != null && organisationUnit != null )
         {
-            CompleteDataSetRegistration registration = registrationService.getCompleteDataSetRegistration( dataSet, period, organisationUnit );
-
-            if ( registration != null )
+            if ( !multiOrganisationUnit )
+            {
+                CompleteDataSetRegistration registration = registrationService.getCompleteDataSetRegistration( dataSet, period, organisationUnit );
+
+                if ( registration != null )
+                {
+                    complete = true;
+                    date = registration.getDate();
+                    storedBy = registration.getStoredBy();
+                }
+
+                locked = dataSetService.isLocked( dataSet, period, organisationUnit, null );
+            }
+            else
             {
                 complete = true;
-                date = registration.getDate();
-                storedBy = registration.getStoredBy();
-            }            
-
-            locked = dataSetService.isLocked( dataSet, period, organisationUnit, null );
+
+                // if this is multiOrg, and one of the children is locked. Then just lock everything down.
+                for ( OrganisationUnit ou : children )
+                {
+                    if ( ou.getDataSets().contains( dataSet ) )
+                    {
+                        locked = dataSetService.isLocked( dataSet, period, organisationUnit, null );
+
+                        if ( locked )
+                        {
+                            break;
+                        }
+
+                        CompleteDataSetRegistration registration = registrationService.getCompleteDataSetRegistration( dataSet, period, ou );
+
+                        if ( complete && registration == null )
+                        {
+                            complete = false;
+                        }
+                    }
+                }
+            }
         }
 
         return SUCCESS;

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/LoadFormAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/LoadFormAction.java	2012-10-02 14:18:38 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/LoadFormAction.java	2012-11-09 12:16:58 +0000
@@ -37,6 +37,8 @@
 import org.hisp.dhis.dataset.Section;
 import org.hisp.dhis.dataset.comparator.SectionOrderComparator;
 import org.hisp.dhis.i18n.I18n;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
 
 import java.util.*;
 
@@ -71,6 +73,13 @@
         this.dataSetService = dataSetService;
     }
 
+    private OrganisationUnitService organisationUnitService;
+
+    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
+    {
+        this.organisationUnitService = organisationUnitService;
+    }
+
     private I18n i18n;
 
     public void setI18n( I18n i18n )
@@ -100,10 +109,24 @@
         this.dataSetId = dataSetId;
     }
 
+    private Integer multiOrganisationUnit;
+
+    public void setMultiOrganisationUnit( Integer multiOrganisationUnit )
+    {
+        this.multiOrganisationUnit = multiOrganisationUnit;
+    }
+
     // -------------------------------------------------------------------------
     // Output
     // -------------------------------------------------------------------------
 
+    private List<OrganisationUnit> organisationUnits = new ArrayList<OrganisationUnit>();
+
+    public List<OrganisationUnit> getOrganisationUnits()
+    {
+        return organisationUnits;
+    }
+
     private Map<DataElementCategoryCombo, List<DataElement>> orderedDataElements = new HashMap<DataElementCategoryCombo, List<DataElement>>();
 
     public Map<DataElementCategoryCombo, List<DataElement>> getOrderedDataElements()
@@ -283,6 +306,21 @@
 
         String displayMode = dataSet.getDataSetType();
 
+        if ( multiOrganisationUnit != null && multiOrganisationUnit != 0 ) // for multiOrg, we only support section forms
+        {
+            OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( multiOrganisationUnit );
+
+            for ( OrganisationUnit child : organisationUnit.getChildren() )
+            {
+                if ( child.getDataSets().contains( dataSet ) )
+                {
+                    organisationUnits.add( child );
+                }
+            }
+
+            getSectionForm( dataElements, dataSet );
+            displayMode = "multiorg_section";
+        }
         if ( displayMode.equals( DataSet.TYPE_SECTION ) )
         {
             getSectionForm( dataElements, dataSet );
@@ -334,7 +372,7 @@
                 i18n, dataSet );
 
             dataElementsNotInForm = new ArrayList<DataElement>( dataSet.getDataElements() );
-            dataElementsNotInForm.removeAll( dataEntryFormService.getDataElementsInDataEntryForm( dataSet ) );        
+            dataElementsNotInForm.removeAll( dataEntryFormService.getDataElementsInDataEntryForm( dataSet ) );
             Collections.sort( dataElementsNotInForm, IdentifiableObjectNameComparator.INSTANCE );
         }
 

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/PageInitAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/PageInitAction.java	2012-02-16 19:58:55 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/PageInitAction.java	2012-11-09 21:52:42 +0000
@@ -47,6 +47,14 @@
         this.selectionManager = selectionManager;
     }
 
+    // we might refactor this into a system property, hard-coding to true for now
+    private boolean multiOrganisationUnit = true;
+
+    public boolean isMultiOrganisationUnit()
+    {
+        return multiOrganisationUnit;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/RegisterCompleteDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/RegisterCompleteDataSetAction.java	2012-11-14 14:21:10 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/RegisterCompleteDataSetAction.java	2012-11-14 17:12:21 +0000
@@ -27,8 +27,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.Date;
-
+import com.opensymphony.xwork2.Action;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.dataset.CompleteDataSetRegistration;
@@ -42,7 +41,8 @@
 import org.hisp.dhis.period.PeriodType;
 import org.hisp.dhis.user.CurrentUserService;
 
-import com.opensymphony.xwork2.Action;
+import java.util.Date;
+import java.util.Set;
 
 /**
  * @author Lars Helge Overland
@@ -116,6 +116,13 @@
         this.organisationUnitId = organisationUnitId;
     }
 
+    private boolean multiOrganisationUnit;
+
+    public void setMultiOrganisationUnit( boolean multiOrganisationUnit )
+    {
+        this.multiOrganisationUnit = multiOrganisationUnit;
+    }
+
     private int statusCode;
 
     public int getStatusCode()
@@ -129,11 +136,10 @@
 
     public String execute()
     {
-        CompleteDataSetRegistration registration = new CompleteDataSetRegistration();
-
         DataSet dataSet = dataSetService.getDataSet( dataSetId );
         Period period = PeriodType.createPeriodExternalId( periodId );
         OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( organisationUnitId );
+        Set<OrganisationUnit> children = organisationUnit.getChildren();
 
         String storedBy = currentUserService.getCurrentUsername();
 
@@ -141,15 +147,54 @@
         // Check locked status
         // ---------------------------------------------------------------------
 
-        if ( dataSetService.isLocked( dataSet, period, organisationUnit, null ) )
-        {
-            return logError( "Entry locked for combination: " + dataSet + ", " + period + ", " + organisationUnit, 2 );
+        if ( !multiOrganisationUnit )
+        {
+            if ( dataSetService.isLocked( dataSet, period, organisationUnit, null ) )
+            {
+                return logError( "Entry locked for combination: " + dataSet + ", " + period + ", " + organisationUnit, 2 );
+            }
+        }
+        else
+        {
+            for ( OrganisationUnit ou : children )
+            {
+                if ( ou.getDataSets().contains( dataSet ) && dataSetService.isLocked( dataSet, period, ou, null ) )
+                {
+                    return logError( "Entry locked for combination: " + dataSet + ", " + period + ", " + ou, 2 );
+                }
+            }
         }
 
         // ---------------------------------------------------------------------
         // Register as completed dataSet
         // ---------------------------------------------------------------------
 
+        if ( !multiOrganisationUnit )
+        {
+            registerCompleteDataSet( dataSet, period, organisationUnit, storedBy );
+        }
+        else
+        {
+            for ( OrganisationUnit ou : children )
+            {
+                if ( ou.getDataSets().contains( dataSet ) )
+                {
+                    registerCompleteDataSet( dataSet, period, ou, storedBy );
+                }
+            }
+        }
+
+        return SUCCESS;
+    }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private void registerCompleteDataSet( DataSet dataSet, Period period, OrganisationUnit organisationUnit, String storedBy )
+    {
+        CompleteDataSetRegistration registration = new CompleteDataSetRegistration();
+
         if ( registrationService.getCompleteDataSetRegistration( dataSet, period, organisationUnit ) == null )
         {
             registration.setDataSet( dataSet );
@@ -161,19 +206,13 @@
             registration.setPeriodName( format.formatPeriod( registration.getPeriod() ) );
 
             boolean notify = dataSet != null && dataSet.getNotificationRecipients() != null;
-            
+
             registrationService.saveCompleteDataSetRegistration( registration, notify );
 
             log.info( "DataSet registered as complete: " + registration );
         }
-
-        return SUCCESS;
     }
 
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
     private String logError( String message, int statusCode )
     {
         log.info( message );

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/UndoCompleteDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/UndoCompleteDataSetAction.java	2012-02-21 18:45:10 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/UndoCompleteDataSetAction.java	2012-11-12 12:47:02 +0000
@@ -39,6 +39,8 @@
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodType;
 
+import java.util.Set;
+
 /**
  * @author Lars Helge Overland
  */
@@ -97,6 +99,13 @@
         this.organisationUnitId = organisationUnitId;
     }
 
+    private boolean multiOrganisationUnit;
+
+    public void setMultiOrganisationUnit( boolean multiOrganisationUnit )
+    {
+        this.multiOrganisationUnit = multiOrganisationUnit;
+    }
+
     private int statusCode;
 
     public int getStatusCode()
@@ -113,20 +122,59 @@
         DataSet dataSet = dataSetService.getDataSet( dataSetId );
         Period period = PeriodType.createPeriodExternalId( periodId );
         OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit( organisationUnitId );
+        Set<OrganisationUnit> children = organisationUnit.getChildren();
 
         // ---------------------------------------------------------------------
         // Check locked status
         // ---------------------------------------------------------------------
 
-        if ( dataSetService.isLocked( dataSet, period, organisationUnit, null ) )
-        {
-            return logError( "Entry locked for combination: " + dataSet + ", " + period + ", " + organisationUnit, 2 );
+        if ( !multiOrganisationUnit )
+        {
+            if ( dataSetService.isLocked( dataSet, period, organisationUnit, null ) )
+            {
+                return logError( "Entry locked for combination: " + dataSet + ", " + period + ", " + organisationUnit, 2 );
+            }
+        }
+        else
+        {
+            for ( OrganisationUnit ou : children )
+            {
+                if ( ou.getDataSets().contains( dataSet ) && dataSetService.isLocked( dataSet, period, ou, null ) )
+                {
+                    return logError( "Entry locked for combination: " + dataSet + ", " + period + ", " + ou, 2 );
+                }
+            }
         }
 
         // ---------------------------------------------------------------------
         // Un-register as completed dataSet
         // ---------------------------------------------------------------------
 
+
+        if ( !multiOrganisationUnit )
+        {
+            deregisterCompleteDataSet( dataSet, period, organisationUnit );
+        }
+        else
+        {
+            for ( OrganisationUnit ou : children )
+            {
+                if ( ou.getDataSets().contains( dataSet ) )
+                {
+                    deregisterCompleteDataSet( dataSet, period, ou );
+                }
+            }
+        }
+
+        return SUCCESS;
+    }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private void deregisterCompleteDataSet( DataSet dataSet, Period period, OrganisationUnit organisationUnit )
+    {
         CompleteDataSetRegistration registration = registrationService.getCompleteDataSetRegistration( dataSet, period, organisationUnit );
 
         if ( registration != null )
@@ -135,14 +183,8 @@
 
             log.info( "DataSet un-registered as complete: " + registration );
         }
-
-        return SUCCESS;
     }
 
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
     private String logError( String message, int statusCode )
     {
         log.info( message );

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml	2012-09-24 21:54:54 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml	2012-11-09 12:16:58 +0000
@@ -37,6 +37,7 @@
     <property name="dataEntryFormService" ref="org.hisp.dhis.dataentryform.DataEntryFormService" />
     <property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
     <property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
+    <property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
   </bean>
 
   <bean id="org.hisp.dhis.de.action.SaveValueAction" class="org.hisp.dhis.de.action.SaveValueAction" scope="prototype">

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/struts.xml	2012-10-31 06:45:06 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/struts.xml	2012-11-12 09:31:08 +0000
@@ -15,7 +15,7 @@
       <param name="menu">/dhis-web-dataentry/menu.vm</param>
       <param name="javascripts">../dhis-web-commons/ouwt/ouwt.js,javascript/form.js,javascript/entry.js,javascript/history.js</param>
       <param name="stylesheets">style/dhis-web-dataentry.css</param>
-      <param name="offline">true</param>
+      <!-- <param name="offline">true</param> -->
     </action>
 
     <action name="getMetaData" class="org.hisp.dhis.de.action.GetMetaDataAction">
@@ -29,6 +29,7 @@
     <action name="loadForm" class="org.hisp.dhis.de.action.LoadFormAction">
       <result name="custom" type="velocity">/dhis-web-dataentry/customForm.vm</result>
       <result name="section" type="velocity">/dhis-web-dataentry/sectionForm.vm</result>
+      <result name="multiorg_section" type="velocity">/dhis-web-dataentry/multiOrgSectionForm.vm</result>
       <result name="default" type="velocity">/dhis-web-dataentry/defaultForm.vm</result>
       <result name="input" type="velocity">/dhis-web-dataentry/responseVoid.vm</result>
     </action>

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js	2012-11-14 12:20:31 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js	2012-11-14 17:12:21 +0000
@@ -47,6 +47,12 @@
 // Instance of the StorageManager
 var storageManager = new StorageManager();
 
+// Is this form a multiOrg form?
+var multiOrganisationUnit = false;
+
+// local cache of organisationUnits (used for name lookup)
+var organisationUnits = [];
+
 var COLOR_GREEN = '#b9ffb9';
 var COLOR_YELLOW = '#fffe8c';
 var COLOR_RED = '#ff8a8a';
@@ -82,6 +88,7 @@
     $( '#orgUnitTree' ).one( 'ouwtLoaded', function()
     {
         log( 'Ouwt loaded' );
+        organisationUnits = JSON.parse( localStorage['organisationUnits'] );
         loadMetaData();
     } );
 
@@ -92,8 +99,7 @@
 	        if ( storageManager.hasLocalData() )
 	        {
 	            var message = i18n_need_to_sync_notification
-	            	+ ' <button id="sync_button" type="button">' + i18n_sync_now
-	            	+ '</button>';
+	            	+ ' <button id="sync_button" type="button">' + i18n_sync_now + '</button>';
 
 	            setHeaderMessage( message );
 
@@ -295,8 +301,7 @@
             error: function( jqXHR, textStatus, errorThrown )
             {
                 var message = i18n_sync_failed
-                    + ' <button id="sync_button" type="button">' + i18n_sync_now
-                    + '</button>';
+                    + ' <button id="sync_button" type="button">' + i18n_sync_now + '</button>';
 
                 setHeaderMessage( message );
 
@@ -314,8 +319,12 @@
     $( '[name="entryfield"]' ).each( function( i )
     {
         var id = $( this ).attr( 'id' );
-        var dataElementId = id.split( '-' )[0];
-        var optionComboId = id.split( '-' )[1];
+
+        var split = splitFieldId( id );
+        var dataElementId = split.dataElementId;
+        var optionComboId = split.optionComboId;
+        currentOrganisationUnitId = split.organisationUnitId;
+
         var type = getDataElementType( dataElementId );
 
         $( this ).unbind( 'focus' );
@@ -359,8 +368,10 @@
     $( '[name="entryselect"]' ).each( function( i )
     {
         var id = $( this ).attr( 'id' );
-        var dataElementId = id.split( '-' )[0];
-        var optionComboId = id.split( '-' )[1];
+        var split = splitFieldId( id );
+
+        var dataElementId = split.dataElementId;
+        var optionComboId = split.optionComboId;
 
         $( this ).unbind( 'focus' );
         $( this ).unbind( 'change' );
@@ -411,6 +422,21 @@
     } );
 }
 
+function resetSectionFilters()
+{
+    $( '#selectionBox' ).css( 'height', '93px' );
+    $( '#filterDataSetSectionTr' ).hide();
+    $( '.formSection' ).show();
+}
+
+function clearSectionFilters()
+{
+    $( '#filterDataSetSection' ).children().remove();
+    $( '#selectionBox' ).css( 'height', '93px' );
+    $( '#filterDataSetSectionTr' ).hide();
+    $( '.formSection' ).show();
+}
+
 function clearPeriod()
 {
     clearListById( 'selectedPeriodId' );
@@ -429,9 +455,11 @@
     $( '#infoDiv' ).hide();
 }
 
-function loadForm( dataSetId )
+function loadForm( dataSetId, multiOrg )
 {
-    if ( storageManager.formExists( dataSetId ) )
+    currentOrganisationUnitId = selection.getSelected();
+
+    if ( !multiOrg && storageManager.formExists( dataSetId ) )
     {
         log( 'Loading form locally: ' + dataSetId );
 
@@ -439,8 +467,14 @@
 
         $( '#contentDiv' ).html( html );
 
-        enableSectionFilter();
-        insertDynamicOptions();
+        multiOrganisationUnit = !!$('.formSection').data('multiorg');
+
+        if(!multiOrganisationUnit)
+        {
+            enableSectionFilter();
+            insertDynamicOptions();
+        }
+
         loadDataValues();
     }
     else
@@ -449,12 +483,23 @@
 
         $( '#contentDiv' ).load( 'loadForm.action', 
         {
-            dataSetId : dataSetId
+            dataSetId : dataSetId,
+            multiOrganisationUnit: multiOrg ? currentOrganisationUnitId : 0
         }, 
         function() 
         {
-            enableSectionFilter();
-            insertDynamicOptions();
+            multiOrganisationUnit = !!$('.formSection').data('multiorg');
+
+            if( !multiOrganisationUnit )
+            {
+                enableSectionFilter();
+                insertDynamicOptions();
+            }
+            else
+            {
+                $( '#currentOrganisationUnit' ).html( i18n_no_organisationunit_selected );
+            }
+
             loadDataValues()
         } );
     }
@@ -617,6 +662,27 @@
 // Supportive methods
 //------------------------------------------------------------------------------
 
+// splits a id based on the multiOrgUnit var
+function splitFieldId( id )
+{
+    var split = {};
+
+    if( multiOrganisationUnit )
+    {
+        split.organisationUnitId = id.split( '-' )[0];
+        split.dataElementId = id.split( '-' )[1];
+        split.optionComboId = id.split( '-' )[2];
+    }
+    else
+    {
+        split.organisationUnitId = currentOrganisationUnitId;
+        split.dataElementId = id.split( '-' )[0];
+        split.optionComboId = id.split( '-' )[1];
+    }
+
+    return split;
+}
+
 function refreshZebraStripes( $tbody )
 {
     $tbody.find( 'tr:not([colspan]):visible:even' ).find( 'td:first-child' ).removeClass( 'reg alt' ).addClass( 'alt' );
@@ -668,9 +734,9 @@
  * Returns an array containing associative array elements with id and name
  * properties. The array is sorted on the element name property.
  */
-function getSortedDataSetList()
+function getSortedDataSetList( orgUnit )
 {
-    var associationSet = organisationUnitAssociationSetMap[currentOrganisationUnitId];
+    var associationSet = orgUnit !== undefined ? organisationUnitAssociationSetMap[orgUnit] : organisationUnitAssociationSetMap[currentOrganisationUnitId];
     var orgUnitDataSets = dataSetAssociationSets[associationSet];
 
     var dataSetList = [];
@@ -694,7 +760,36 @@
     return dataSetList;
 }
 
-function organisationUnitSelected( orgUnits, orgUnitNames )
+function getSortedDataSetListForOrgUnits( orgUnits )
+{
+    var dataSetList = [];
+
+    $.each(orgUnits, function(idx, item) {
+        dataSetList.push.apply( dataSetList, getSortedDataSetList(item) )
+    });
+
+    var filteredDataSetList = [];
+
+    $.each(dataSetList, function(idx, item) {
+        var formType = dataSets[item.id].type;
+        var found = false;
+
+        $.each(filteredDataSetList, function(i, el) {
+
+            if(item.name == el.name)
+                found = true;
+        });
+
+        if( !found && formType == 'section' )
+        {
+            filteredDataSetList.push(item);
+        }
+    })
+
+    return filteredDataSetList;
+}
+
+function organisationUnitSelected( orgUnits, orgUnitNames, children )
 {
 	if ( metaDataIsLoaded == false )
 	{
@@ -729,7 +824,23 @@
         }
     }
 
-    if ( dataSetValid && dataSetId != null )
+    if ( children )
+    {
+        var childrenDataSets = getSortedDataSetListForOrgUnits( children );
+
+        if( childrenDataSets && childrenDataSets.length > 0 )
+        {
+            $('#selectedDataSetId').append('<optgroup label="Childrens DataSets">')
+
+            $.each(childrenDataSets, function(idx, item) {
+                $('<option />').attr('data-multiorg', true).attr('value', item.id).html(item.name).appendTo('#selectedDataSetId');
+            });
+
+            $('#selectDataSetId').append('</optgroup>')
+        }
+    }
+
+    if ( !multiOrganisationUnit && dataSetValid && dataSetId != null )
     {
         $( '#selectedDataSetId' ).val( dataSetId );
 
@@ -742,6 +853,8 @@
     }
     else
     {
+        multiOrganisationUnit = false;
+
         clearSectionFilters();
         clearPeriod();
     }
@@ -829,7 +942,9 @@
         {
             showLoader();
             $( '#selectedPeriodId' ).val( periodId );
-            loadForm( dataSetId );
+
+            var isMultiOrganisationUnitForm = !!$('#selectedDataSetId :selected').data('multiorg');
+            loadForm( dataSetId, isMultiOrganisationUnitForm );
         }
         else
         {
@@ -863,7 +978,8 @@
         }
         else
         {
-            loadForm( dataSetId );
+            var isMultiOrganisationUnitForm = !!$('#selectedDataSetId :selected').data('multiorg');
+            loadForm( dataSetId, isMultiOrganisationUnitForm );
         }
     }
 }
@@ -878,6 +994,7 @@
     $( '#undoButton' ).attr( 'disabled', 'disabled' );
     $( '#infoDiv' ).css( 'display', 'none' );
 
+    currentOrganisationUnitId = selection.getSelected();
     insertDataValues();
     displayEntryFormCompleted();
 }
@@ -917,7 +1034,8 @@
 	    {
 	        periodId : periodId,
 	        dataSetId : dataSetId,
-	        organisationUnitId : currentOrganisationUnitId
+	        organisationUnitId : currentOrganisationUnitId,
+            multiOrganisationUnit: multiOrganisationUnit
 	    },
 	    dataType: 'json',
 	    error: function() // offline
@@ -953,8 +1071,9 @@
 	            }
 	            else // Insert for potential dynamic input fields
 	            {
-	                var dataElementId = value.id.split( '-' )[0];
-	                var optionComboId = value.id.split( '-' )[1];
+                    var split = splitFieldId( value.id );
+	                var dataElementId = split.dataElementId;
+	                var optionComboId = split.optionComboId;
 	                
 	                var selectElementId = '#' + getDynamicSelectElementId( dataElementId );
 	                
@@ -1051,7 +1170,16 @@
 {
     addEventListeners();
 
-    $( '#validationButton' ).removeAttr( 'disabled' );
+    if(!multiOrganisationUnit)
+    {
+        $( '#validationButton' ).removeAttr( 'disabled' );
+        $( '#validateButton' ).removeAttr( 'disabled' );
+    }
+    else
+    {
+        $( '#validationButton' ).attr( 'disabled', true );
+        $( '#validateButton' ).attr( 'disabled', true );
+    }
 
     dataEntryFormIsLoaded = true;
     hideLoader();
@@ -1063,12 +1191,16 @@
 {
     var id = e.target.id;
 
-    var dataElementId = id.split( '-' )[0];
-    var optionComboId = id.split( '-' )[1];
+    var split = splitFieldId( id );
+    var dataElementId = split.dataElementId;
+    var optionComboId = split.optionComboId;
+    currentOrganisationUnitId = split.organisationUnitId;
 
     var dataElementName = getDataElementName( dataElementId );
     var optionComboName = getOptionComboName( optionComboId );
+    var organisationUnitName = organisationUnits[currentOrganisationUnitId].n;
 
+    $( '#currentOrganisationUnit' ).html( organisationUnitName );
     $( '#currentDataElement' ).html( dataElementName + ' ' + optionComboName );
 
     $( '#' + dataElementId + '-cell' ).addClass( 'currentRow' );
@@ -1078,7 +1210,8 @@
 {
     var id = e.target.id;
 
-    var dataElementId = id.split( '-' )[0];
+    var split = splitFieldId( id );
+    var dataElementId = split.dataElementId;
 
     $( '#' + dataElementId + '-cell' ).removeClass( 'currentRow' );
 }
@@ -1149,7 +1282,9 @@
 	
 	validate( true, function() {	
 	    var params = storageManager.getCurrentCompleteDataSetParams();
-	
+        params['organisationUnitId'] = selection.getSelected();
+        params['multiOrganisationUnit'] = multiOrganisationUnit;
+
 		storageManager.saveCompleteDataSet( params );
 	
 	    $.ajax( {
@@ -1182,6 +1317,8 @@
 {
     var confirmed = confirm( i18n_confirm_undo );
     var params = storageManager.getCurrentCompleteDataSetParams();
+    params['organisationUnitId'] = selection.getSelected();
+    params['multiOrganisationUnit'] = multiOrganisationUnit;
 
     if ( confirmed )
     {
@@ -1333,7 +1470,9 @@
         $( '[name="entryfield"]' ).add( '[name="entryselect"]' ).each( function( i )
         {
             var id = $( this ).attr( 'id' );
-            var dataElementId = id.split( '-' )[0];		
+
+            var split = splitFieldId( id );
+            var dataElementId = split.dataElementId;
             var hasValue = $.trim( $( this ).val() ).length > 0;
             
             if ( hasValue )

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/menu.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/menu.vm	2012-03-05 12:23:01 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/menu.vm	2012-11-09 21:52:42 +0000
@@ -1,13 +1,17 @@
 <script type="text/javascript">
 jQuery(document).ready(function() {
-	selection.setListenerFunction( organisationUnitSelected );
+    selection.setListenerFunction( organisationUnitSelected );
+
+    #if( $multiOrganisationUnit )
+    selection.setIncludeChildren( true );
+    #end
 });
 </script>
 
 <style type="text/css">
 #leftBarContents div#orgUnitTree {
 	height: 430px;
-}
+}
 </style>
 
 <br>

=== added file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/multiOrgSectionForm.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/multiOrgSectionForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/multiOrgSectionForm.vm	2012-11-13 13:37:08 +0000
@@ -0,0 +1,104 @@
+#set( $marker = 0 )
+#set( $tabIndex = 1 )
+#set( $hasAccess = $auth.hasAccess( "dhis-web-dataentry", "saveValue" ) )
+
+#foreach( $section in $sections )
+
+#if( $marker == 1 )
+  #set( $marker = 0 )
+#else
+  #set( $marker = 1 )
+#end
+
+<table class="formSection" data-multiorg="true">
+<tr>
+  <td>
+    <div class="cent"><h3>$encoder.htmlEncode( $section.name )</h3></div>
+  </td>
+</tr>
+<tr>
+  <td>
+    <div>
+    <table cellspacing="0">
+    #set( $categoryComboId = $sectionCombos.get( $section.id ) )
+    #set( $colCount = $numberOfTotalColumns.get( $categoryComboId ) )
+    #set( $categories = $orderedCategories.get( $categoryComboId ) )
+    #set( $optionsMap = $orderedOptionsMap.get( $categoryComboId ) )
+    #set( $colRepeat = $catColRepeat.get( $categoryComboId ) )
+    #set( $isDefaultCategory = $categories.get( 0 ).name == "default" )
+
+    #if( $isDefaultCategory )
+        #set( $rowSpan = $optionsMap.size() )
+    #else
+        #set( $rowSpan = $optionsMap.size() + 1)
+    #end
+
+    <tr>
+        <td rowspan="$rowSpan"></td>
+        #foreach( $dataElement in $section.dataElements )
+        <th colspan="$colCount">$dataElement.name</th>
+        #end
+    </tr>
+
+    #if( !$isDefaultCategory )
+        #foreach( $category in $categories )
+            #set( $categoryOptions = $optionsMap.get( $category.id ) )
+            #set( $colCount = $colCount / $categoryOptions.size() )
+            <tr colspan="$colCount">
+            #set( $cols = $colRepeat.get( $category.id ) )
+
+            #foreach( $dataElement in $section.dataElements )
+                #foreach( $col in $cols )
+                    #foreach( $categoryOption in $categoryOptions )
+                        <th colspan="$colCount"><span align="center">${encoder.htmlEncode( $categoryOption.name )}</span></th>
+                    #end
+                #end
+            #end
+            </tr>
+        #end
+    #end
+
+    #set( $count = 0 )
+    #set( $mark = 0 )
+    #set( $optionCombos = $orderedCategoryOptionCombos.get( $categoryComboId )  )
+    #foreach( $optionCombo in $optionCombos )<span id="${optionCombo.id}-optioncombo" class="hidden">${encoder.htmlEncode( $optionCombo.name )}</span>
+    #end
+
+    #foreach( $organisationUnit in $organisationUnits )
+        #if( $mark == 1 )
+        #set( $mark = 0 )
+        #else
+        #set( $mark = 1 )
+        #end
+        #set( $count = $count + 1 )
+        #set( $dataEntryId = "${organisationUnit.id}-${dataElement.id}-${optionCombo.id}-val" )
+        <tr>
+            <td #if( $mark == 1 )class="alt"#else class="reg"#end>${encoder.htmlEncode( $organisationUnit.name )}</td>
+
+            #foreach( $dataElement in $section.dataElements )
+                #foreach( $optionCombo in $optionCombos )
+                #set( $dataEntryId = "${organisationUnit.id}-${dataElement.id}-${optionCombo.id}-val" )
+                #set( $greyedField = false )
+                #set( $greyedField = $greyedFields.get( "$dataElement.id:$optionCombo.id" ) )
+                #if( $dataElement.type == "bool" )
+                <td><select name="entryselect" id="$dataEntryId" tabindex="$tabIndex"#if( $greyedField || !$hasAccess ) disabled="disabled"#end>
+                  <option value="">[$i18n.getString( "no_value" )]</option>
+                  <option value="true">$i18n.getString( "yes" )</option>
+                  <option value="false">$i18n.getString( "no" )</option>
+                </select></td>
+                #else
+                <td><input name="entryfield" id="$dataEntryId" type="text" tabindex="$tabIndex"#if( $greyedField || !$hasAccess ) disabled="disabled"#end></td>
+                #end
+                </td>
+                #set( $tabIndex = $tabIndex + 1 )
+                #end
+           #end
+        </tr>
+    #end
+	</table>
+    </div>
+    </td>
+  </tr>
+</table>
+<br>
+#end

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseDataValues.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseDataValues.vm	2011-11-21 12:44:20 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseDataValues.vm	2012-11-12 10:22:34 +0000
@@ -3,17 +3,25 @@
 { "dataValues": [
   #foreach( $value in $dataValues )
   {
+    #if( $multiOrganisationUnit )
+    "id":"${value.source.id}-${value.dataElement.id}-${value.optionCombo.id}",
+    #else
     "id":"${value.dataElement.id}-${value.optionCombo.id}",
+    #end
     "val":"$!{value.value}"
-  }#if( $velocityCount < $size1 ),#end
+  }#if( $velocityCount < $size1 ),#end
   #end ],
   "minMaxDataElements": [
   #foreach( $element in $minMaxDataElements )
   {
+    #if( $multiOrganisationUnit )
+    "id":"${element.source.id}-${element.dataElement.id}-${element.optionCombo.id}",
+    #else
     "id":"${element.dataElement.id}-${element.optionCombo.id}",
+    #end
     "min":"${element.min}",
     "max":"${element.max}"
-  }#if( $velocityCount < $size2 ),#end
+  }#if( $velocityCount < $size2 ),#end
   #end ],
   "locked":${locked},
   "complete":${complete},

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm	2012-10-15 08:33:30 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm	2012-11-12 11:43:09 +0000
@@ -40,6 +40,7 @@
 var i18n_all_values_for_data_element_must_be_filled = '$encoder.jsEscape( $i18n.getString( "all_values_for_data_element_must_be_filled" ) , "'")';
 var i18n_validation_result = '$encoder.jsEscape( $i18n.getString( "validation_result" ) , "'")';
 var i18n_successful_validation = '$encoder.jsEscape( $i18n.getString( "successful_validation" ) , "'")';
+var i18n_no_organisationunit_selected = '$encoder.jsEscape( $i18n.getString( "no_organisationunit_selected" ) , "'")';
 </script>
 
 <h3>$i18n.getString( "data_entry" ) #openHelp( "dataEntry" )</h3>
@@ -93,7 +94,7 @@
 <div id="completenessDiv" class="page inputCriteria" style="display:none;width:386px;height:29px;">
 <input type="button" id="completeButton" name="completeButton" value="$i18n.getString( 'complete' )" onclick="registerCompleteDataSet()" style="width:120px">
 <input type="button" id="undoButton" name="undoButton" value="$i18n.getString( 'incomplete' )" onclick="undoCompleteDataSet()" style="width:120px">
-<input type="button" value="$i18n.getString( 'run_validation' )" onclick="validate( false )" style="width:120px">
+<input type="button" id="validateButton" value="$i18n.getString( 'run_validation' )" onclick="validate( false )" style="width:120px">
 </div>
 
 <div id="infoDiv" class="page inputCriteria" style="display:none;width:386px;height:20px;">