Fixes bug 25951:Auxiliary inputs are executed when FIC is called in CHANGE mode
authorAugusto Mauch <augusto.mauch@openbravo.com>
Thu, 13 Mar 2014 13:47:53 +0100
changeset 22704 2ac8f9165769
parent 22703 7858157f0182
child 22705 15994dc74cd8
Fixes bug 25951:Auxiliary inputs are executed when FIC is called in CHANGE mode

Before this change, the FIC did not execute the auxiliary inputs when it was called in CHANGE mode. This was done to prevent resetting auxiliary inputs that ha
d been modified in callouts.

This made impossible to use auxiliary inputs in display logic, because they would not be updated until the records was refreshed. To fix this while allowing to
overwrite auxiliary inputs from callouts, this has been done:
- The list of auxiliary inputs modified in callouts is persisted. This list is reset when the FIC is called in a mode other than CHANGE (originally in this cas
e all the auxiliary inputs were being updated, regardless of whether they had been modified by a callout).
- If the FIC is called in CHANGE mode, then only the auxiliary inputs that have not been modified by callouts are recalculated.
- The auxiliary inputs are now executed after the callouts are run, in order to be able to use the updated data in the auxiliary input calculation.
modules/org.openbravo.client.application/src/org/openbravo/client/application/window/FormInitializationComponent.java
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/FormInitializationComponent.java	Thu Mar 13 16:45:59 2014 +0530
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/window/FormInitializationComponent.java	Thu Mar 13 13:47:53 2014 +0100
@@ -174,6 +174,15 @@
         gridVisibleProperties = convertJSONArray(jsContent.getJSONArray("_gridVisibleProperties"));
       }
 
+      List<String> overwrittenAuxiliaryInputs = new ArrayList<String>();
+      // The provided overwrittenAuxiliaryInputs only have to be persisted when calling the FIC in
+      // CHANGE mode. In the rest of the modes all auxiliary inputs are computed regardless of
+      // whether a callout have modified them in a previous request
+      if (jsContent.has("overwrittenAuxiliaryInputs") && "CHANGE".equals(mode)) {
+        overwrittenAuxiliaryInputs = convertJSONArray(jsContent
+            .getJSONArray("overwrittenAuxiliaryInputs"));
+      }
+
       // If the table is based in a datasource, don't try to create a BaseOBObject
       if (!dataSourceBasedTable) {
         // create the row from the json content then
@@ -239,7 +248,7 @@
 
       // Computation of the Auxiliary Input values
       long t4 = System.currentTimeMillis();
-      computeAuxiliaryInputs(mode, tab, columnValues);
+      computeAuxiliaryInputs(mode, tab, columnValues, overwrittenAuxiliaryInputs);
 
       // Computation of Column Values (using UIDefinition, so including combo values and all
       // relevant additional information)
@@ -248,17 +257,19 @@
           changedColumn, jsContent, changeEventCols, calloutsToCall, lastfieldChanged,
           visibleProperties, gridVisibleProperties);
 
-      if (mode.equals("NEW")) {
-        // In the case of NEW mode, we compute auxiliary inputs again to take into account that
-        // auxiliary inputs could depend on a default value
-        computeAuxiliaryInputs(mode, tab, columnValues);
-      }
-
       // Execution of callouts
       long t6 = System.currentTimeMillis();
       List<String> changedCols = executeCallouts(mode, tab, columnValues, changedColumn,
           calloutsToCall, lastfieldChanged, calloutMessages, changeEventCols, jsExcuteCode,
-          hiddenInputs);
+          hiddenInputs, overwrittenAuxiliaryInputs);
+
+      // Compute the auxiliary inputs after executing the callout to ensure they use the updated
+      // parameters
+      if (mode.equals("NEW") || mode.equals("CHANGE")) {
+        // In the case of NEW mode, we compute auxiliary inputs again to take into account that
+        // auxiliary inputs could depend on a default value
+        computeAuxiliaryInputs(mode, tab, columnValues, overwrittenAuxiliaryInputs);
+      }
 
       if (changedCols.size() > 0) {
         RequestContext.get().setRequestParameter("donotaddcurrentelement", "true");
@@ -276,7 +287,8 @@
       // Construction of the final JSONObject
       long t9 = System.currentTimeMillis();
       JSONObject finalObject = buildJSONObject(mode, tab, columnValues, row, changeEventCols,
-          calloutMessages, attachments, jsExcuteCode, hiddenInputs, noteCount);
+          calloutMessages, attachments, jsExcuteCode, hiddenInputs, noteCount,
+          overwrittenAuxiliaryInputs);
       analyzeResponse(tab, columnValues);
       long t10 = System.currentTimeMillis();
       log.debug("Elapsed time: " + (System.currentTimeMillis() - iniTime) + "(" + (t2 - t1) + ","
@@ -387,7 +399,7 @@
   private JSONObject buildJSONObject(String mode, Tab tab, Map<String, JSONObject> columnValues,
       BaseOBObject row, List<String> changeEventCols, List<JSONObject> calloutMessages,
       List<JSONObject> attachments, List<String> jsExcuteCode, Map<String, Object> hiddenInputs,
-      int noteCount) {
+      int noteCount, List<String> overwrittenAuxiliaryInputs) {
     JSONObject finalObject = new JSONObject();
     try {
       if (mode.equals("NEW") || mode.equals("CHANGE")) {
@@ -427,6 +439,7 @@
             columnValues.get("inp" + Sqlc.TransformaNombreColumna(auxIn.getName())));
       }
       finalObject.put("auxiliaryInputValues", jsonAuxiliaryInputValues);
+      finalObject.put("overwrittenAuxiliaryInputs", new JSONArray(overwrittenAuxiliaryInputs));
 
       if (mode.equals("NEW") || mode.equals("EDIT") || mode.equals("SETSESSION")) {
         // We also include information related to validation dependencies
@@ -844,15 +857,15 @@
 
   }
 
-  private void computeAuxiliaryInputs(String mode, Tab tab, Map<String, JSONObject> columnValues) {
-    if (mode.equals("CHANGE")) {
-      // Auxiliary Inputs are not computed in CHANGE mode, only in the initial request in NEW or
-      // EDIT mode. This is done to prevent accidental overwriting of auxiliary input values which
-      // have been set by callouts
-      // See issue 17239 for more information
-      return;
-    }
+  private void computeAuxiliaryInputs(String mode, Tab tab, Map<String, JSONObject> columnValues,
+      List<String> overwrittenAuxiliaryInputs) {
     for (AuxiliaryInput auxIn : getAuxiliaryInputList(tab.getId())) {
+      if (mode.equals("CHANGE")) {
+        // Don't compute the auxiliary inputs that have been overwritten by callouts
+        if (overwrittenAuxiliaryInputs.contains(auxIn.getName())) {
+          continue;
+        }
+      }
       Object value = computeAuxiliaryInput(auxIn, tab.getWindow().getId());
       log.debug("Final Computed Value. Name: " + auxIn.getName() + " Value: " + value);
       JSONObject jsonObj = new JSONObject();
@@ -1290,7 +1303,7 @@
   private List<String> executeCallouts(String mode, Tab tab, Map<String, JSONObject> columnValues,
       String changedColumn, List<String> calloutsToCall, List<String> lastfieldChanged,
       List<JSONObject> messages, List<String> dynamicCols, List<String> jsExecuteCode,
-      Map<String, Object> hiddenInputs) {
+      Map<String, Object> hiddenInputs, List<String> overwrittenAuxiliaryInputs) {
 
     // In CHANGE mode, we will add the initial callout call for the changed column, if there is
     // one
@@ -1312,14 +1325,14 @@
       return new ArrayList<String>();
     }
     return runCallouts(columnValues, tab, calledCallouts, calloutsToCall, lastfieldChanged,
-        messages, dynamicCols, jsExecuteCode, hiddenInputs);
+        messages, dynamicCols, jsExecuteCode, hiddenInputs, overwrittenAuxiliaryInputs);
 
   }
 
   private List<String> runCallouts(Map<String, JSONObject> columnValues, Tab tab,
       List<String> calledCallouts, List<String> calloutsToCall, List<String> lastfieldChangedList,
       List<JSONObject> messages, List<String> dynamicCols, List<String> jsExecuteCode,
-      Map<String, Object> hiddenInputs) {
+      Map<String, Object> hiddenInputs, List<String> overwrittenAuxiliaryInputs) {
     HashMap<String, Object> calloutInstances = new HashMap<String, Object>();
 
     // flush&commit to release lock in db which otherwise interfere with callouts which run in their
@@ -1544,6 +1557,11 @@
                         obj.put("value", el);
                         obj.put("classicValue", el);
                         columnValues.put(name, obj);
+                        // Add the auxiliary input to the list of auxiliary inputs modified by
+                        // callouts
+                        if (!overwrittenAuxiliaryInputs.contains(aux.getName())) {
+                          overwrittenAuxiliaryInputs.add(aux.getName());
+                        }
                       }
                     }
                     if (!columnValues.containsKey(name)) {
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Thu Mar 13 16:45:59 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/ob-view-form.js	Thu Mar 13 13:47:53 2014 +0100
@@ -746,6 +746,7 @@
     var columnValues = data.columnValues,
         calloutMessages = data.calloutMessages,
         auxInputs = data.auxiliaryInputValues,
+        overwrittenAuxiliaryInputs = data.overwrittenAuxiliaryInputs,
         prop, value, i, j, dynamicCols = data.dynamicCols,
         sessionAttributes = data.sessionAttributes,
         editValues, item, section, retHiddenInputs = data.hiddenInputs;
@@ -816,6 +817,10 @@
       }
     }
 
+    if (overwrittenAuxiliaryInputs) {
+      this.overwrittenAuxiliaryInputs = overwrittenAuxiliaryInputs;
+    }
+
     if (sessionAttributes) {
       this.sessionAttributes = sessionAttributes;
     }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Thu Mar 13 16:45:59 2014 +0530
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Thu Mar 13 13:47:53 2014 +0100
@@ -2269,6 +2269,9 @@
       isc.addProperties(contextInfo, form.auxInputs);
       isc.addProperties(contextInfo, form.hiddenInputs);
       isc.addProperties(contextInfo, form.sessionAttributes);
+      if (form.overwrittenAuxiliaryInputs) {
+        contextInfo.overwrittenAuxiliaryInputs = form.overwrittenAuxiliaryInputs;
+      }
     }
 
     if (this.parentView) {