← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 8142: Impl new option in data set for only allowing completion of forms if all validation rules pass. I...

 

Merge authors:
  Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 8142 [merge]
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2012-09-19 18:14:28 +0200
message:
  Impl new option in data set for only allowing completion of forms if all validation rules pass. Improved performance of validation in data entry.
added:
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/responseSearch.vm
renamed:
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitByCodeAction.java => dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitsByNameAction.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.ajax.js
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/orgunittreesearch.vm
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/ouwt.js
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties
  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/responseMetaData.vm
  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/validationResult.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitsByNameAction.java


--
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/dataset/DataSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java	2012-09-19 16:14:28 +0000
@@ -153,6 +153,11 @@
      */
     private boolean fieldCombinationRequired;
     
+    /**
+     * Property indicating that all validation rules must pass before the form can be completed.
+     */
+    private boolean validCompleteOnly;
+    
     // -------------------------------------------------------------------------
     // Contructors
     // -------------------------------------------------------------------------
@@ -567,6 +572,19 @@
         this.fieldCombinationRequired = fieldCombinationRequired;
     }
 
+    @JsonProperty
+    @JsonView( {DetailedView.class, ExportView.class} )
+    @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE )
+    public boolean isValidCompleteOnly()
+    {
+        return validCompleteOnly;
+    }
+
+    public void setValidCompleteOnly( boolean validCompleteOnly )
+    {
+        this.validCompleteOnly = validCompleteOnly;
+    }
+
     @Override
     public void mergeWith( IdentifiableObject other )
     {

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java	2012-08-13 09:06:44 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java	2012-09-19 16:14:28 +0000
@@ -103,7 +103,7 @@
             categoryOptionCombos.addAll( dataElement.getCategoryCombo().getOptionCombos() );
         }
 
-        log.info( "Starting min-max analysis, no of data elements: " + elements.size() + ", no of org units: " + organisationUnits.size() );
+        log.debug( "Starting min-max analysis, no of data elements: " + elements.size() + ", no of org units: " + organisationUnits.size() );
         
         return dataAnalysisStore.getMinMaxViolations( elements, categoryOptionCombos, periods, organisationUnits, MAX_OUTLIERS );
     }
@@ -111,13 +111,13 @@
     public void generateMinMaxValues( Collection<OrganisationUnit> organisationUnits,
         Collection<DataElement> dataElements, Double stdDevFactor )
     {
-        log.info( "Starting min-max value generation, no of data elements: " + dataElements.size() + ", no of org units: " + organisationUnits.size() );
+        log.debug( "Starting min-max value generation, no of data elements: " + dataElements.size() + ", no of org units: " + organisationUnits.size() );
 
         Set<Integer> orgUnitIds = new HashSet<Integer>( ConversionUtils.getIdentifiers( OrganisationUnit.class, organisationUnits ) ); 
 
         minMaxDataElementService.removeMinMaxDataElements( dataElements, organisationUnits );
 
-        log.info( "Deleted existing min-max values" );
+        log.debug( "Deleted existing min-max values" );
 
         BatchHandler<MinMaxDataElement> batchHandler = batchHandlerFactory.createBatchHandler( MinMaxDataElementBatchHandler.class ).init();
         

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2012-09-19 16:14:28 +0000
@@ -387,6 +387,7 @@
         executeSql( "update indicatortype set indicatornumber = false where indicatornumber is null" );
         executeSql( "update dataset set mobile = false where mobile is null" );
         executeSql( "update dataset set allowfutureperiods = false where allowfutureperiods is null" );
+        executeSql( "update dataset set validcompleteonly = false where validcompleteonly is null" );
         executeSql( "update dataelement set zeroissignificant = false where zeroissignificant is null" );
         executeSql( "update organisationunit set haspatients = false where haspatients is null" );
         executeSql( "update dataset set expirydays = 0 where expirydays is null" );

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml	2012-09-19 16:14:28 +0000
@@ -72,6 +72,8 @@
 	<property name="allowFuturePeriods" />
 
 	<property name="fieldCombinationRequired" />
+	
+	<property name="validCompleteOnly" />
 
   </class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.ajax.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.ajax.js	2011-08-19 09:04:34 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.ajax.js	2012-09-19 16:14:28 +0000
@@ -202,70 +202,65 @@
         this.params = params;
         this.jQuerySelectionString = jQuerySelectionString;
 
-        jQuery
-                .postJSON(
-                        '../dhis-web-commons-ajax-json/getOperands.action',
-                        this.params,
-                        function( json )
-                        {
-                            if ( json.operands.length == 0 )
-                            {
-                                setInnerHTML( 'formulaText', "<i style='color:red'>No dataelements to select</i>" );
-                                return;
-                            }
-
-                            jQuery.each( json.operands, function( i, item )
-                            {
-                                target.append( '<option value="[' + item.operandId + ']">' + item.operandName
-                                        + '</option>' );
-                            } );
-
-                            if ( params.usePaging )
-                            {
-                                var numberOfPages = json.paging.numberOfPages;
-                                var currentPage = json.paging.currentPage;
-                                var pageSize = json.paging.pageSize;
-                                var startPage = json.paging.startPage;
-
-                                var html = '<div id="operandPaging_div">';
-
-                                if ( numberOfPages > 1 )
-                                {
-                                    html += 'Page: <select onchange="dataDictionary.reloadOperands( this.value )">';
-
-                                    for ( var i = 1; i <= numberOfPages; i++ )
-                                    {
-                                        html += '<option value="' + i + '"' + (currentPage == i ? 'selected=true' : '')
-                                                + '>' + i + '</option>';
-                                    }
-
-                                    html += '</select>';
-
-                                    if ( currentPage == startPage )
-                                    {
-                                        html += '<button type="button" disabled="disabled">Previous page</button>';
-                                        html += '<button type="button" onclick="dataDictionary.reloadOperands( '
-                                                + (parseInt( currentPage ) + 1) + ' )">Next page</button>';
-                                    } else if ( currentPage == numberOfPages )
-                                    {
-                                        html += '<button type="button" onclick="dataDictionary.reloadOperands( '
-                                                + (parseInt( currentPage ) - 1) + ' )">Previous page</button>';
-                                        html += '<button type="button" disabled="disabled">Next page</button>';
-                                    } else
-                                    {
-                                        html += '<button type="button" onclick="dataDictionary.reloadOperands( '
-                                                + (parseInt( currentPage ) - 1) + ')">Previous page</button>';
-                                        html += '<button type="button" onclick="dataDictionary.reloadOperands( '
-                                                + (parseInt( currentPage ) + 1) + ')">Next page</button>';
-                                    }
-                                }
-
-                                html += 'Size: <input type="text" style="width:50px" onchange="dataDictionary.changeOperandsPageSize( this.value )" value="'
-                                        + pageSize + '"/></div>';
-                                jQuery( '#operandPaging_div' ).remove();
-                                jQuery( html ).insertAfter( target );
-                            }
-                        } );
+        jQuery.postJSON(
+            '../dhis-web-commons-ajax-json/getOperands.action',
+            this.params,
+            function( json )
+            {
+                jQuery.each( json.operands, function( i, item )
+                {
+                    target.append( '<option value="[' + item.operandId + ']">' + item.operandName
+                            + '</option>' );
+                } );
+
+                if ( params.usePaging )
+                {
+                    var numberOfPages = json.paging.numberOfPages;
+                    var currentPage = json.paging.currentPage;
+                    var pageSize = json.paging.pageSize;
+                    var startPage = json.paging.startPage;
+
+                    var html = '<div id="operandPaging_div">';
+
+                    if ( numberOfPages > 1 )
+                    {
+                        html += 'Page: <select onchange="dataDictionary.reloadOperands( this.value )">';
+
+                        for ( var i = 1; i <= numberOfPages; i++ )
+                        {
+                            html += '<option value="' + i + '"' + (currentPage == i ? 'selected=true' : '')
+                                    + '>' + i + '</option>';
+                        }
+
+                        html += '</select>';
+
+                        if ( currentPage == startPage )
+                        {
+                            html += '<button type="button" disabled="disabled">Previous page</button>';
+                            html += '<button type="button" onclick="dataDictionary.reloadOperands( '
+                                    + (parseInt( currentPage ) + 1) + ' )">Next page</button>';
+                        } 
+                        else if ( currentPage == numberOfPages )
+                        {
+                            html += '<button type="button" onclick="dataDictionary.reloadOperands( '
+                                    + (parseInt( currentPage ) - 1) + ' )">Previous page</button>';
+                            html += '<button type="button" disabled="disabled">Next page</button>';
+                        } 
+                        else
+                        {
+                            html += '<button type="button" onclick="dataDictionary.reloadOperands( '
+                                    + (parseInt( currentPage ) - 1) + ')">Previous page</button>';
+                            html += '<button type="button" onclick="dataDictionary.reloadOperands( '
+                                    + (parseInt( currentPage ) + 1) + ')">Next page</button>';
+                        }
+                    }
+
+                    html += 'Size: <input type="text" style="width:50px" onchange="dataDictionary.changeOperandsPageSize( this.value )" value="'
+                            + pageSize + '"/></div>';
+                    jQuery( '#operandPaging_div' ).remove();
+                    jQuery( html ).insertAfter( target );
+                }
+            } );
     };
 }
 

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/orgunittreesearch.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/orgunittreesearch.vm	2011-07-18 10:46:40 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/orgunittreesearch.vm	2012-09-19 11:41:19 +0000
@@ -1,19 +1,27 @@
 <script type="text/javascript">
-	jQuery(document).ready(function(){
+    jQuery(document).ready(function(){
 		jQuery("#searchIcon").click(function(){
 			jQuery("#searchSpan").toggle();
 			jQuery("#searchField").focus();
 		});
+		
+		jQuery("#searchField").autocomplete({
+		    source: "../dhis-web-commons/ouwt/getOrganisationUnitsByName.action",
+		    select: function(event,ui) {
+		        jQuery("#searchField").val(ui.item.value);
+		        selection.findByName();
+		    }
+		});
 	});
-
+	
 	var i18n_find = '$encoder.jsEscape( $i18n.getString( "find" ) , "'")';
 </script>
 
-<img id="searchIcon" src="../images/search.png" style="cursor: pointer" title="$i18n.getString( 'locate_organisation_unit_by_code_or_name' )">
+<img id="searchIcon" src="../images/search.png" style="cursor: pointer" title="$i18n.getString( 'locate_organisation_unit_by_name' )">
 
-<span id="searchSpan" style="display:none">
-	<input type="text" id="searchField" name="key" style="width:130px" onchange="selection.findByCode()" />
-	<input type="button" value="Find" onclick="selection.findByCode()" />
+<span id="searchSpan" style="width:100%;display:none;">
+	<input type="text" id="searchField" name="key" style="width:160px" />
+	<input type="button" value="Find" onclick="selection.findByName()" />
 </span>
 
 <div id="orgUnitTreeContainer">

=== 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-09-15 21:52:33 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/ouwt.js	2012-09-19 11:41:19 +0000
@@ -424,7 +424,7 @@
         return 'orgUnit' + unitId;
     }
 
-    this.findByCode = function ()
+    this.findByName = function()
     {
         var name = $( '#searchField' ).val();
 

=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/responseSearch.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/responseSearch.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ouwt/responseSearch.vm	2012-09-19 11:41:19 +0000
@@ -0,0 +1,6 @@
+#set( $size = $organisationUnits.size() )
+[
+#foreach( $unit in $organisationUnits )
+{"value":"$encoder.htmlEncode( $unit.name )"}#if( $velocityCount < $size ),#end
+#end
+]
\ No newline at end of file

=== renamed file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitByCodeAction.java' => 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitsByNameAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitByCodeAction.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/ouwt/action/GetOrganisationUnitsByNameAction.java	2012-09-19 11:41:19 +0000
@@ -27,32 +27,25 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
-import org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager;
 
 import com.opensymphony.xwork2.Action;
 
 /**
  * @author Chau Thu Tran
  */
-public class GetOrganisationUnitByCodeAction
+public class GetOrganisationUnitsByNameAction
     implements Action
 {
-    private static final Log log = LogFactory.getLog( GetOrganisationUnitByCodeAction.class );
+    private static final int MAX = 14;
     
-    // --------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
     // Dependencies
-    // --------------------------------------------------------------------------
-
-    private OrganisationUnitSelectionManager selectionManager;
-    
-    public void setSelectionManager( OrganisationUnitSelectionManager selectionManager )
-    {
-        this.selectionManager = selectionManager;
-    }
+    // -------------------------------------------------------------------------
 
     private OrganisationUnitService organisationUnitService;
 
@@ -61,47 +54,38 @@
         this.organisationUnitService = organisationUnitService;
     }
 
-    // --------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
     // Input
-    // --------------------------------------------------------------------------
-
-    private String code;
-
-    public void setCode( String code )
-    {
-        this.code = code;
-    }
-
-    private String message;
-
-    public String getMessage()
-    {
-        return message;
-    }
-
-    // --------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
+
+    private String term;
+
+    public void setTerm( String term )
+    {
+        this.term = term;
+    }
+
+    // -------------------------------------------------------------------------
+    // Output
+    // -------------------------------------------------------------------------
+
+    private List<OrganisationUnit> organisationUnits;
+
+    public List<OrganisationUnit> getOrganisationUnits()
+    {
+        return organisationUnits;
+    }
+
+    // -------------------------------------------------------------------------
     // Implementation Action
-    // --------------------------------------------------------------------------
+    // -------------------------------------------------------------------------
 
     @Override
     public String execute()
         throws Exception
     {
-        log.debug( "Searching organisation unit for code: " + code );
-        
-        OrganisationUnit unit = organisationUnitService.getOrganisationUnitByNameIgnoreCase( code );
-        
-        if ( unit != null )
-        {
-            log.debug( "Found organisation unit: " + unit );
-            
-            selectionManager.setSelectedOrganisationUnit( unit );
-            
-            message = String.valueOf( unit.getId() );
-            
-            return SUCCESS;
-        }
-        
-        return INPUT;
+        organisationUnits = new ArrayList<OrganisationUnit>( organisationUnitService.getOrganisationUnitsBetweenByName( term, 0, MAX ) );
+        
+        return SUCCESS;
     }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2012-09-15 22:53:29 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2012-09-19 11:41:19 +0000
@@ -191,11 +191,8 @@
     </property>
   </bean>
 
-  <bean id="org.hisp.dhis.ouwt.action.GetOrganisationUnitByCodeAction" class="org.hisp.dhis.ouwt.action.GetOrganisationUnitByCodeAction"
+  <bean id="org.hisp.dhis.ouwt.action.GetOrganisationUnitsByNameAction" class="org.hisp.dhis.ouwt.action.GetOrganisationUnitsByNameAction"
     scope="prototype">
-    <property name="selectionManager">
-      <ref local="org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager" />
-    </property>
     <property name="organisationUnitService">
       <ref bean="org.hisp.dhis.organisationunit.OrganisationUnitService" />
     </property>

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml	2012-09-03 19:53:34 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml	2012-09-19 11:41:19 +0000
@@ -231,13 +231,11 @@
       <param name="onExceptionReturn">plainTextError</param>
     </action>
 
-    <action name="getOrganisationUnitByCode" class="org.hisp.dhis.ouwt.action.GetOrganisationUnitByCodeAction">
+    <action name="getOrganisationUnitsByName" class="org.hisp.dhis.ouwt.action.GetOrganisationUnitsByNameAction">
       <result name="success" type="velocity-json">
-        /dhis-web-commons/ajax/jsonResponseSuccess.vm
-      </result>
-      <result name="input" type="velocity-json">
-        /dhis-web-commons/ajax/jsonResponseInput.vm
-      </result>
+        /dhis-web-commons/ouwt/responseSearch.vm
+      </result>
+      <param name="onExceptionReturn">plainTextError</param>
     </action>
 
     <action name="loadOrganisationUnitTree" class="org.hisp.dhis.commons.action.NoAction">

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties	2012-09-12 15:48:31 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/i18n_global.properties	2012-09-19 11:41:19 +0000
@@ -26,7 +26,7 @@
 org_unit_tree=Organisation Unit Tree
 specify_organisationunit=Please specify an organisation unit
 cannot_clear_selected_orgunits=Cannot clear the selected organisation units
-locate_organisation_unit_by_code_or_name=Locate organisation unit by code or name
+locate_organisation_unit_by_name=Locate organisation unit by name
 error_occurred=An error has occurred.
 select_organisationunit=You must select an OrganisationUnit from the tree.
 

=== 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-03-05 12:23:01 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/struts.xml	2012-09-19 16:14:28 +0000
@@ -78,7 +78,7 @@
     </action>
 
     <action name="validate" class="org.hisp.dhis.de.action.ValidationAction">
-      <result name="success" type="velocity">/dhis-web-dataentry/validationResult.vm</result>
+      <result name="success" type="outputStreamResult"></result>
       <result name="input" type="velocity">/dhis-web-dataentry/validationResult.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-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js	2012-09-19 16:14:28 +0000
@@ -1110,69 +1110,44 @@
 // Data completeness
 // -----------------------------------------------------------------------------
 
-function validateCompleteDataSet()
+function registerCompleteDataSet()
 {
-    var confirmed = confirm( i18n_confirm_complete );
-
-	if ( !validateCompulsoryCombinations() )
+	var confirmed = confirm( i18n_confirm_complete );
+	
+	if ( !confirmed )
 	{
 		return false;
 	}
 	
-    if ( confirmed )
-    {
-        var params = storageManager.getCurrentCompleteDataSetParams();
-
-        $.ajax( { url: 'getValidationViolations.action',
-        	data: params,
-        	dataType: 'json',
-        	success: function( data )
+	validate( true, function() {	
+	    var params = storageManager.getCurrentCompleteDataSetParams();
+	
+		storageManager.saveCompleteDataSet( params );
+	
+	    $.ajax( {
+	    	url: 'registerCompleteDataSet.action',
+	    	data: params,
+	        dataType: 'json',
+	    	success: function(data)
 	        {
-	            registerCompleteDataSet( data );
+	            if ( data.status == 2 )
+	            {
+	                log( 'Data set is locked' );
+	                setHeaderMessage( i18n_register_complete_failed_dataset_is_locked );
+	            }
+	            else
+	            {
+	                disableCompleteButton();
+	
+	                storageManager.clearCompleteDataSet( params );
+	            }
 	        },
-	        error: function()
-	        {
-	            // no response from server, fake a positive result and save it
-	            registerCompleteDataSet( { 'response' : 'success' } );
-	        }
-    	} );
-    }
-}
-
-function registerCompleteDataSet( json )
-{
-    var params = storageManager.getCurrentCompleteDataSetParams();
-
-	storageManager.saveCompleteDataSet( params );
-
-    $.ajax( {
-    	url: 'registerCompleteDataSet.action',
-    	data: params,
-        dataType: 'json',
-    	success: function(data)
-        {
-            if( data.status == 2 )
-            {
-                log( 'DataSet is locked' );
-                setHeaderMessage( i18n_register_complete_failed_dataset_is_locked );
-            }
-            else
-            {
-                disableCompleteButton();
-
-                storageManager.clearCompleteDataSet( params );
-
-                if ( json.response == 'input' )
-                {
-                    validate();
-                }
-            }
-        },
-	    error: function()
-	    {
-	    	disableCompleteButton();
-	    }
-    } );
+		    error: function()
+		    {
+		    	disableCompleteButton();
+		    }
+	    } );
+	} );
 }
 
 function undoCompleteDataSet()
@@ -1248,8 +1223,10 @@
 // Validation
 // -----------------------------------------------------------------------------
 
-function displayValidationDialog()
+function displayValidationDialog( data )
 {
+	$( '#validationDiv' ).html( data );
+	
     $( '#validationDiv' ).dialog( {
         modal : true,
         title : 'Validation',
@@ -1258,39 +1235,76 @@
     } );
 }
 
-function validate()
+/**
+ * Validates form. First looks for compulsory data element combinations and returns
+ * false if violated. Second looks for validation rules and returns false if
+ * violated and if completion is only allowed for valid forms. Returns true otherwise.
+ * 
+ * @param ignoreSuccessfulValidation whether the pop-up should not be skipped if
+ *        validation is successful.
+ */
+function validate( ignoreSuccessfulValidation, successCallback )
 {
-	if ( !validateCompulsoryCombinations() )
+	var compulsoryCombinationsValid = validateCompulsoryCombinations();
+	
+	// Check for compulsory combinations and return false if violated
+	
+	if ( !compulsoryCombinationsValid )
 	{
+    	var html = '<h3>' + i18n_validation_result + '</h3>' +
+        	'<p class="bold">' + i18n_all_values_for_data_element_must_be_filled + '</p>';
+		
+    	displayValidationDialog( html );
+	
 		return false;
 	}
+
+	// Check for validation rules and whether complete is only allowed if valid
 	
-    var periodId = $( '#selectedPeriodId' ).val();
-    var dataSetId = $( '#selectedDataSetId' ).val();
-
-    $( '#validationDiv' ).load( 'validate.action', {
-        periodId : periodId,
-        dataSetId : dataSetId,
-        organisationUnitId : currentOrganisationUnitId
-    }, 
+	var successHtml = '<h3>' + i18n_validation_result + '</h3>' +
+		'<p class="bold">' + i18n_successful_validation + '</p>';
+
+	var validCompleteOnly = dataSets[currentDataSetId].validCompleteOnly;
+
+    var params = storageManager.getCurrentCompleteDataSetParams();
+    
+    $( '#validationDiv' ).load( 'validate.action', params, 
     function( response, status, xhr )
     {
-        if ( status == 'error' )
+    	var success = null;
+    	
+        if ( status == 'error' && !ignoreSuccessfulValidation )
         {
             window.alert( i18n_operation_not_available_offline );
+            success = true;  // Accept if offline
         }
         else
         {
-            displayValidationDialog();
+        	var hasViolations = isDefined( response ) && $.trim( response ).length > 0;
+        	var success = !( hasViolations && validCompleteOnly );
+        	
+        	if ( hasViolations )
+        	{
+        		displayValidationDialog( response );
+        	}
+        	else if ( !ignoreSuccessfulValidation )
+        	{
+        		displayValidationDialog( successHtml );
+        	}        	
+        }
+        
+        if ( success && $.isFunction( successCallback ) )
+        {
+        	successCallback.call();
         }
     } );
 }
 
 function validateCompulsoryCombinations()
 {
-	var validationRequired = dataSets[currentDataSetId].fieldCombinationRequired;
+	var fieldCombinationRequired = dataSets[currentDataSetId].fieldCombinationRequired;
 	
-    if ( validationRequired )
+    if ( fieldCombinationRequired )
     {
         var violations = false;
 		
@@ -1309,10 +1323,8 @@
                 {
                     if ( $.trim( $( this ).val() ).length == 0 )
                     {
-                        violations = true;
-						
-                        $selector.css( 'background-color', COLOR_RED );
-						
+                        violations = true;						
+                        $selector.css( 'background-color', COLOR_RED );						
                         return false;
                     }
                 } );
@@ -1321,13 +1333,8 @@
 		
         if ( violations )
         {
-        	$( '#validationDiv' ).html( '<h3>' + i18n_validation_result + '</h3>' +
-                '<p class="bold">' + i18n_all_values_for_data_element_must_be_filled + '</p>' );
-				
-            displayValidationDialog();
-			
             return false;
-		}
+        }
     }
 	
 	return true;

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm	2012-09-19 16:14:28 +0000
@@ -25,7 +25,7 @@
 #foreach( $dataSet in $dataSets )
 "${dataSet.id}":{"name":"$encoder.jsonEncode( ${dataSet.displayName} )","periodType":"$encoder.jsonEncode( ${dataSet.periodType.name} )",
 "version":"${dataSet.version}","type":"${dataSet.getDataSetType()}","expiryDays":"${dataSet.expiryDays}",
-"allowFuturePeriods":${dataSet.allowFuturePeriods},"fieldCombinationRequired":${dataSet.fieldCombinationRequired}
+"allowFuturePeriods":${dataSet.allowFuturePeriods},"fieldCombinationRequired":${dataSet.fieldCombinationRequired},"validCompleteOnly":${dataSet.validCompleteOnly}
 }#if( $velocityCount < $size ),#end
 #end },
 

=== 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-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm	2012-09-19 16:14:28 +0000
@@ -39,6 +39,7 @@
 var i18n_show_all_sections = '$encoder.jsEscape( $i18n.getString( "show_all_sections" ) , "'")';
 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" ) , "'")';
 </script>
 
 <h3>$i18n.getString( "data_entry" ) #openHelp( "dataEntry" )</h3>
@@ -50,7 +51,7 @@
 </div>
 
 <div id="actions">	
-    <input type="button" value="$i18n.getString( 'run_validation' )" onclick="validate()" id="validationButton" style="width:150px;" disabled="disabled"/>
+    <input type="button" value="$i18n.getString( 'run_validation' )" onclick="validate( false )" id="validationButton" style="width:150px;" disabled="disabled"/>
 </div>
 
 <div id="selectionBox" class="inputCriteria" style="width:504px;height:93px;">
@@ -90,9 +91,9 @@
 <div id="validationDiv" class="page"></div>
 
 <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="validateCompleteDataSet()" style="width:120px">
+<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()" style="width:120px">
+<input type="button" 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;">

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/validationResult.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/validationResult.vm	2011-07-28 07:34:34 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/validationResult.vm	2012-09-19 16:14:28 +0000
@@ -1,22 +1,22 @@
-<h3>$encoder.htmlEncode( $i18n.getString( "validation_result" ) )</h3>
+<h3>$i18n.getString( "validation_result" )</h3>
 
 #if( $results.size() == 0 && $dataValues.size() == 0 )  
-    <p class="bold">$encoder.htmlEncode( $i18n.getString( "successful_validation" ) )</p>
+    <p class="bold">$i18n.getString( "successful_validation" )</p>
 #else
-    <p class="bold">$encoder.htmlEncode( $i18n.getString( "unsuccessful_validation" ) )</p>
+    <p class="bold">$i18n.getString( "unsuccessful_validation" )</p>
 #end
 
 #if( $results.size() > 0)
-    <p class="bold">$encoder.htmlEncode( $i18n.getString( "the_following_values_violate_rules" ) )</p>
+    <p class="bold">$i18n.getString( "the_following_values_violate_rules" )</p>
     <table class="listTable" width="100%">
         <tr>
-            <th style="width:110px">$encoder.htmlEncode( $i18n.getString( "validation_rule" ) )</th>                
-            <th>$encoder.htmlEncode( $i18n.getString( "expression" ) )</th>
-            <th>$encoder.htmlEncode( $i18n.getString( "description" ) )</th>
-            <th>$encoder.htmlEncode( $i18n.getString( "value" ) )</th>
-            <th>$encoder.htmlEncode( $i18n.getString( "operator" ) )</th>
-            <th>$encoder.htmlEncode( $i18n.getString( "value" ) )</th>
-            <th>$encoder.htmlEncode( $i18n.getString( "description" ) )</th>
+            <th style="width:110px">$i18n.getString( "validation_rule" )</th>                
+            <th>$i18n.getString( "expression" )</th>
+            <th>$i18n.getString( "description" )</th>
+            <th>$i18n.getString( "value" )</th>
+            <th>$i18n.getString( "operator" )</th>
+            <th>$i18n.getString( "value" )</th>
+            <th>$i18n.getString( "description" )</th>
         </tr>
         #set( $mark = false )   
         #foreach( $result in $results )

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java	2012-09-19 16:14:28 +0000
@@ -148,6 +148,13 @@
     {
         this.fieldCombinationRequired = fieldCombinationRequired;
     }
+    
+    private boolean validCompleteOnly;
+
+    public void setValidCompleteOnly( boolean validCompleteOnly )
+    {
+        this.validCompleteOnly = validCompleteOnly;
+    }
 
     private Collection<String> dataElementsSelectedList = new HashSet<String>();
 
@@ -203,6 +210,7 @@
         dataSet.setIndicators( indicators );
         dataSet.setAllowFuturePeriods( allowFuturePeriods );
         dataSet.setFieldCombinationRequired( fieldCombinationRequired );
+        dataSet.setValidCompleteOnly( validCompleteOnly );
 
         dataSetService.addDataSet( dataSet );
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java	2012-09-19 16:14:28 +0000
@@ -167,6 +167,13 @@
         this.fieldCombinationRequired = fieldCombinationRequired;
     }
 
+    private boolean validCompleteOnly;
+
+    public void setValidCompleteOnly( boolean validCompleteOnly )
+    {
+        this.validCompleteOnly = validCompleteOnly;
+    }
+
     private Collection<String> dataElementsSelectedList = new HashSet<String>();
 
     public void setDataElementsSelectedList( Collection<String> dataElementsSelectedList )
@@ -232,6 +239,7 @@
         dataSet.setIndicators( indicators );
         dataSet.setAllowFuturePeriods( allowFuturePeriods );
         dataSet.setFieldCombinationRequired( fieldCombinationRequired );
+        dataSet.setValidCompleteOnly( validCompleteOnly );
 
         dataSetService.updateDataSet( dataSet );
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties	2012-09-19 16:14:28 +0000
@@ -101,4 +101,5 @@
 indicator_not_exist=Indicator does not exist
 cat_combo_not_exist=Category combo does not exist
 all_fields_for_data_element_required=All fields for data elements required
-form_details=Form details
\ No newline at end of file
+form_details=Form details
+complete_allowed_only_if_validation_passes=Complete allowed only if validation passes
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm	2012-09-19 16:14:28 +0000
@@ -122,7 +122,16 @@
       	  	<option value="true">$i18n.getString( "yes" )</option>
   	      </select>
 	    </td>
-      </tr>	   
+      </tr>
+      <tr>
+        <td><label>$i18n.getString( "complete_allowed_only_if_validation_passes" )</label></td>
+        <td>
+          <select id="validCompleteOnly" name="validCompleteOnly" style="min-width:20em; margin:0;">
+            <option value="false">$i18n.getString( "no" )</option>
+            <option value="true">$i18n.getString( "yes" )</option>
+          </select>
+        </td>
+      </tr>
     </tbody>
   </table>
   <br/>&nbsp;

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm	2012-09-18 16:20:20 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm	2012-09-19 16:14:28 +0000
@@ -123,6 +123,15 @@
   	      </select>
 	    </td>
       </tr>
+      <tr>
+        <td><label>$i18n.getString( "complete_allowed_only_if_validation_passes" )</label></td>
+        <td>
+          <select id="validCompleteOnly" name="validCompleteOnly" style="min-width:20em; margin:0;">
+            <option value="false">$i18n.getString( "no" )</option>
+            <option value="true"#if( $dataSet.validCompleteOnly == true ) selected="selected"#end>$i18n.getString( "yes" )</option>
+          </select>
+        </td>
+      </tr>
       <tr><td>&nbsp;</td><td>&nbsp;</td></tr>
     </tbody>
   </table>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm	2012-09-18 12:10:07 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm	2012-09-19 08:34:26 +0000
@@ -57,16 +57,16 @@
     <tbody>
       <tr>
         <td><label>$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-        <td><input type="text" id="nameField" name="nameField" value='$!dataEntryForm.name' style="width:20em"></td>
+        <td><input type="text" id="nameField" name="nameField" value='$!dataEntryForm.name' style="width:30em"></td>
       </tr>
       <tr>
         <td><label>$i18n.getString( "dataset" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
-        <td><input type="text" value="$dataSet.name" style="width:20em" disabled /></td>
+        <td><input type="text" value="$dataSet.name" style="width:30em" disabled /></td>
       </tr>
       <tr>
         <td><label>$i18n.getString( "style" )</label></td>
         <td>
-        <select id="style" name="style" style="width:20em">
+        <select id="style" name="style" style="width:30em">
           <option value="regular"#if( !$dataEntryForm.style || "regular" == $dataEntryForm.style ) selected=selected#end>$i18n.getString( "regular" )</option>
           <option value="comfortable"#if( "comfortable" == $dataEntryForm.style ) selected=selected#end>$i18n.getString( "comfortable" )</option>
           <option value="compact"#if( "compact" == $dataEntryForm.style ) selected=selected#end>$i18n.getString( "compact" )</option>