[hqlpickandexecute] merge to PI
authorSandra Huguet <sandra.huguet@openbravo.com>
Tue, 25 Nov 2014 16:34:14 +0100
changeset 25462 059f88b82a8b
parent 25461 d9ad7d0cdd7c (current diff)
parent 25401 d8acdd64b6bf (diff)
child 25463 57669e40f0cc
[hqlpickandexecute] merge to PI
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-fk-filter.js
src-db/database/sourcedata/AD_AUXILIARINPUT.xml
src-db/database/sourcedata/AD_COLUMN.xml
src-db/database/sourcedata/AD_FIELD.xml
src-db/database/sourcedata/AD_TAB.xml
src-db/database/sourcedata/AD_TABLE.xml
--- a/.hgsigs	Mon Nov 24 16:43:00 2014 +0100
+++ b/.hgsigs	Tue Nov 25 16:34:14 2014 +0100
@@ -157,3 +157,4 @@
 a9d6608b6cabe9e27fa31cbf2a49a69b2d583e0a 0 iEUEABECAAYFAlPfOfMACgkQCX/oGf+2qkP8GQCY8T/ZXMymIqGubZ6h2LbjE7Uc4gCg5A/numsq2gypnrNri+wMt1HLLWA=
 c63d4e4125e832602ed1da786f756c26c7fdcd2a 0 iEYEABECAAYFAlQISYIACgkQCX/oGf+2qkMciwCgo6ZYlA+XmT9DC0n2zO7P5okbQngAoITq7wESNiiLk56/3Rzw7gGtOgMe
 d8e24b51ba03c98d057048de5e86c1c8c977276f 0 iEYEABECAAYFAlRJO3UACgkQCX/oGf+2qkMMFQCeObdVCTDlec79H4alHs8t8SDMQ9YAoO4HfqRXTDGnDg5+LnLtuBxPsQDD
+924afa1490b09bc691895099f12204b2282b0ee9 0 iEYEABECAAYFAlRhoL8ACgkQCX/oGf+2qkNHkwCfeuBMGLqmtcdy8LxqPtcu8mRAlQIAnAjqdHUhM+pTFL5tdsaY1V9buvP9
--- a/.hgtags	Mon Nov 24 16:43:00 2014 +0100
+++ b/.hgtags	Tue Nov 25 16:34:14 2014 +0100
@@ -168,3 +168,4 @@
 d7d2abe0f424775dcdf9139410ae161881be1fb8 3.0PR14Q3
 a5483762bc5de5e3e934785f3baffda3a2d96db2 3.0PR14Q3.1
 6af26661c789c5daa23e36e7367a05dfe291242e 3.0PR14Q3.2
+4ccbe7a7da1d0eed0677d7d0baf545607a192c87 3.0PR14Q3.3
--- a/modules/org.openbravo.client.application/src/org/openbravo/client/application/event/WindowPersonalizationEventHandler.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.application/src/org/openbravo/client/application/event/WindowPersonalizationEventHandler.java	Tue Nov 25 16:34:14 2014 +0100
@@ -19,18 +19,25 @@
 
 package org.openbravo.client.application.event;
 
+import java.util.List;
+
 import javax.enterprise.event.Observes;
 
 import org.apache.log4j.Logger;
+import org.hibernate.criterion.Restrictions;
 import org.openbravo.base.exception.OBException;
 import org.openbravo.base.model.Entity;
 import org.openbravo.base.model.ModelProvider;
 import org.openbravo.client.application.UIPersonalization;
+import org.openbravo.client.kernel.event.EntityDeleteEvent;
 import org.openbravo.client.kernel.event.EntityPersistenceEventObserver;
 import org.openbravo.client.kernel.event.EntityUpdateEvent;
 import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBCriteria;
+import org.openbravo.dal.service.OBDal;
 import org.openbravo.database.ConnectionProvider;
 import org.openbravo.erpCommon.utility.Utility;
+import org.openbravo.model.ad.domain.Preference;
 import org.openbravo.model.ad.ui.Tab;
 import org.openbravo.model.ad.ui.Window;
 import org.openbravo.service.db.DalConnectionProvider;
@@ -46,8 +53,7 @@
     return entities;
   }
 
-  public void onUpdate(@Observes
-  EntityUpdateEvent event) {
+  public void onUpdate(@Observes EntityUpdateEvent event) {
     if (!isValidEvent(event)) {
       return;
     }
@@ -66,4 +72,49 @@
       throw new OBException(Utility.messageBD(conn, "OBUIAPP_TabFieldMandatory", language));
     }
   }
+
+  public void onDelete(@Observes EntityDeleteEvent event) {
+    if (!isValidEvent(event)) {
+      return;
+    }
+    final UIPersonalization uiPersonalization = (UIPersonalization) event.getTargetInstance();
+    deleteDefaultViewPreferences(uiPersonalization);
+  }
+
+  /**
+   * Given an UIPersonalization, deletes the OBUIAPP_DefaultSavedView preferences that reference it
+   */
+  private void deleteDefaultViewPreferences(UIPersonalization uiPersonalization) {
+    try {
+      List<Preference> preferenceList = this
+          .getDefaultViewPreferencesForUiPersonalization(uiPersonalization);
+      // don't do a client access check, the preference to delete might belong to another client
+      // (i.e. System)
+      OBContext.setAdminMode(false);
+      for (Preference preference : preferenceList) {
+        OBDal.getInstance().remove(preference);
+      }
+    } catch (Exception e) {
+      logger.error("Error while deleting a default view preference", e);
+    } finally {
+      OBContext.restorePreviousMode();
+    }
+  }
+
+  /**
+   * Given an UIPersonalization, returns the list of OBUIAPP_DefaultSavedView preferences that
+   * reference it
+   */
+  private List<Preference> getDefaultViewPreferencesForUiPersonalization(
+      UIPersonalization uiPersonalization) {
+    OBCriteria<Preference> preferenceCriteria = OBDal.getInstance()
+        .createCriteria(Preference.class);
+    // filter out the preferences that do not store the default view
+    preferenceCriteria.add(Restrictions
+        .eq(Preference.PROPERTY_PROPERTY, "OBUIAPP_DefaultSavedView"));
+    // filter out the preferences whose default view is not the one being deleted
+    preferenceCriteria
+        .add(Restrictions.eq(Preference.PROPERTY_SEARCHKEY, uiPersonalization.getId()));
+    return preferenceCriteria.list();
+  }
 }
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-image.js	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/form/formitem/ob-formitem-image.js	Tue Nov 25 16:34:14 2014 +0100
@@ -269,8 +269,8 @@
       });
     }
     //Buttons will not be shown if the form is readonly
-    this.canvas.deleteButton.updateState(newValue && (this.form && !this.form.readOnly) && !this.readOnly);
-    this.canvas.selectorButton.updateState((this.form && !this.form.readOnly) && !this.readOnly);
+    this.canvas.deleteButton.updateState(newValue && (this.form && !this.form.readOnly) && !this.disabled);
+    this.canvas.selectorButton.updateState((this.form && !this.form.readOnly) && !this.disabled);
     return this.Super('setValue', arguments);
   },
   refreshImage: function (imageId) {
@@ -281,6 +281,20 @@
     }
     this.setValue(imageId);
     this.form.itemChangeActions();
+  },
+  //This function has been overwritten because this class needs to do specific things if the object is
+  //disabled. It is necessary to hide the delete and selector buttons when the status is disabled 
+  //and to show them when enabled.
+  
+  setDisabled: function (disabled) {
+    if (disabled) {
+      this.canvas.deleteButton.hide();
+      this.canvas.selectorButton.hide();
+    } else {
+      this.canvas.deleteButton.show();
+      this.canvas.selectorButton.show();
+    }
+    this.Super('setDisabled', arguments);
   }
 });
 
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/grid/ob-view-grid.js	Tue Nov 25 16:34:14 2014 +0100
@@ -2894,7 +2894,7 @@
     // set the default error message,
     // is possibly overridden in the next call
     if (record) {
-      record._hasValidationErrors = true;
+      this.addRecordToValidationErrorList(record);
       if (!record[isc.OBViewGrid.ERROR_MESSAGE_PROP]) {
         this.setRecordErrorMessage(rowNum, OB.I18N.getLabel('OBUIAPP_ErrorInFields'));
         // do not automatically remove this message
@@ -2926,6 +2926,45 @@
     }
   },
 
+  addRecordToValidationErrorList: function (record) {
+    if (!record) {
+      return;
+    }
+    record._hasValidationErrors = true;
+    this.recordIdsWithValidationError = this.recordIdsWithValidationError || [];
+    if (!this.recordIdsWithValidationError.contains(record[OB.Constants.ID])) {
+      this.recordIdsWithValidationError.push(record[OB.Constants.ID]);
+    }
+  },
+
+  removeRecordFromValidationErrorList: function (record) {
+    if (!record) {
+      return;
+    }
+    delete record._hasValidationErrors;
+    this.recordIdsWithValidationError = this.recordIdsWithValidationError || [];
+    this.recordIdsWithValidationError.remove(record[OB.Constants.ID]);
+  },
+
+  selectedRecordHasValidationErrors: function () {
+    var record;
+    // if the number of selected records is not 1, return false
+    if (this.getSelectedRecords().length !== 1 || !isc.isA.Array(this.recordIdsWithValidationError)) {
+      return false;
+    }
+    record = this.getSelectedRecord();
+    return this.recordIdsWithValidationError.contains(record[OB.Constants.ID]);
+  },
+
+  gridHasValidationErrors: function () {
+    if (!isc.isA.Array(this.recordIdsWithValidationError)) {
+      return false;
+    } else {
+      // return true if the list of record ids with validation errors is not empty
+      return !this.recordIdsWithValidationError.isEmpty();
+    }
+  },
+
   recordHasChanges: function (rowNum, colNum, checkEditor) {
     var record = this.getRecord(rowNum);
     // If a record has validation errors but had all the mandatory fields set,
@@ -2983,6 +3022,9 @@
       return;
     }
 
+    // the record has been sucessfully saved so it does not have validation errors
+    this.removeRecordFromValidationErrorList(record);
+
     // a new id has been computed use that now
     if (record && record._newId) {
       record.id = record._newId;
@@ -3060,6 +3102,7 @@
     for (i = 0; i < length; i++) {
       var rowNum = this.getRecordIndex(selectedRecords[i]);
       var record = selectedRecords[i];
+      this.removeRecordFromValidationErrorList(record);
       this.Super('discardEdits', [rowNum, false, false, isc.ListGrid.PROGRAMMATIC]);
       // remove the record if new
       if (record._new) {
@@ -3102,6 +3145,10 @@
         totalRows, me = this,
         record = this.getRecord(rowNum);
 
+    if (record) {
+      this.removeRecordFromValidationErrorList(record);
+    }
+
     if (!preventConfirm && ((editForm && editForm.hasChanged) || this.rowHasErrors(rowNum))) {
       me.Super('discardEdits', localArguments);
 
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-view.js	Tue Nov 25 16:34:14 2014 +0100
@@ -369,6 +369,8 @@
       if (!lazyFiltering) {
         if (!this.standardWindow.checkIfDefaultSavedView()) {
           this.viewGrid.fetchData(this.viewGrid.getCriteria());
+        } else {
+          this.dataLoadDelayedForDefaultSavedView = true;
         }
       }
       this.refreshContents = false;
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/main/ob-standard-window.js	Tue Nov 25 16:34:14 2014 +0100
@@ -548,8 +548,8 @@
 
     // find the default view, the personalizations are
     // returned in order of prio, then do sort by name
-    if (this.getClass().personalization.views) {
-      views = this.getClass().personalization.views;
+    views = this.getClass().personalization.views;
+    if (views && isc.isA.Array(views) && views.length > 0) {
       length = views.length;
 
       this.getClass().personalization.views.sort(function (v1, v2) {
@@ -598,6 +598,13 @@
           }
         }
       }
+    } else {
+      if (this.view.dataLoadDelayedForDefaultSavedView) {
+        // it might happen that the load of the initial grid data was delayed because it had a 
+        // default saved view, but then the default saved view is not returned by the WindowSettingsActionHandler.
+        // in that case, detect it and load the grid now
+        this.view.viewGrid.fetchData(this.view.viewGrid.getCriteria());
+      }
     }
 
     // restore focus as the focusitem may have been hidden now
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/toolbar/ob-toolbar.js	Tue Nov 25 16:34:14 2014 +0100
@@ -192,12 +192,25 @@
 
   REFRESH_BUTTON_PROPERTIES: {
     action: function () {
-      var refreshChildren = true;
-      if (this.view.isShowingForm) {
-        // Refresh the form and its children records
-        this.view.viewForm.refresh(null, refreshChildren);
-      } else {
-        this.view.refresh();
+      var refreshChildren = true,
+          callbackEnableButton, me = this;
+      this.view.isRefreshing = true;
+      // Disable the refresh button until the refresh is finished
+      this.setDisabled(true);
+      callbackEnableButton = function () {
+        // Enable the refresh button in the callback
+        delete me.view.isRefreshing;
+        me.setDisabled(false);
+      };
+      try {
+        if (this.view.isShowingForm) {
+          // Refresh the form and its children records
+          this.view.viewForm.refresh(callbackEnableButton, refreshChildren);
+        } else {
+          this.view.refresh(callbackEnableButton);
+        }
+      } catch (e) {
+        callbackEnableButton();
       }
     },
     disabled: false,
@@ -205,7 +218,12 @@
     sortPosition: 70,
     prompt: OB.I18N.getLabel('OBUIAPP_RefreshData'),
     updateState: function () {
-      this.setDisabled(!this.view.hasNotChanged());
+      var gridVisibleAndWithValidationErrors = false;
+      if (!this.view.isShowingForm && this.view.viewGrid.gridHasValidationErrors()) {
+        // do not allow refreshing the grid if it has validation errors
+        gridVisibleAndWithValidationErrors = true;
+      }
+      this.setDisabled(gridVisibleAndWithValidationErrors || this.view.isRefreshing || !this.view.hasNotChanged());
     },
     keyboardShortcutId: 'ToolBar_Refresh'
   },
@@ -222,12 +240,13 @@
     sortPosition: 50,
     prompt: OB.I18N.getLabel('OBUIAPP_CancelEdit'),
     updateState: function () {
+      var recordWithValidationErrorsSelected = false;
       if (this.view.isShowingForm) {
         this.setDisabled(false);
       } else {
         // Only enabled when the grid is being edited or when
         // the selected records have errors
-        this.setDisabled(!this.view.isEditingGrid && this.view.hasNotChanged());
+        this.setDisabled(!this.view.isEditingGrid && this.view.hasNotChanged() && !this.view.viewGrid.selectedRecordHasValidationErrors());
       }
     },
     keyboardShortcutId: 'ToolBar_Undo'
--- a/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/DateTimeUIDefinition.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.kernel/src/org/openbravo/client/kernel/reference/DateTimeUIDefinition.java	Tue Nov 25 16:34:14 2014 +0100
@@ -19,7 +19,6 @@
 package org.openbravo.client.kernel.reference;
 
 import java.text.FieldPosition;
-import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
@@ -62,29 +61,25 @@
       return (String) value;
     }
 
-    StringBuffer convertedValue = convertLocalTimeToUTC(value.toString());
+    StringBuffer convertedValue = convertLocalDateTimeToUTC((Date) value);
     return convertedValue.toString();
   }
 
-  private StringBuffer convertLocalTimeToUTC(String value) {
+  private StringBuffer convertLocalDateTimeToUTC(Date UTCDate) {
     StringBuffer localTimeColumnValue = null;
-    try {
-      Date UTCDate = ficDateFormat.parse(value);
-      Calendar now = Calendar.getInstance();
+    Calendar now = Calendar.getInstance();
 
-      Calendar calendar = Calendar.getInstance();
-      calendar.setTime(UTCDate);
-      calendar.set(Calendar.DATE, now.get(Calendar.DATE));
-      calendar.set(Calendar.MONTH, now.get(Calendar.MONTH));
-      calendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
+    Calendar calendar = Calendar.getInstance();
+    calendar.setTime(UTCDate);
+    calendar.set(Calendar.DATE, now.get(Calendar.DATE));
+    calendar.set(Calendar.MONTH, now.get(Calendar.MONTH));
+    calendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
 
-      int gmtMillisecondOffset = (now.get(Calendar.ZONE_OFFSET) + now.get(Calendar.DST_OFFSET));
-      calendar.add(Calendar.MILLISECOND, -gmtMillisecondOffset);
-      localTimeColumnValue = getClassicFormat().format(calendar.getTime(), new StringBuffer(),
-          new FieldPosition(0));
-    } catch (ParseException e) {
-      throw new OBException("Exception when parsing date ", e);
-    }
+    int gmtMillisecondOffset = (now.get(Calendar.ZONE_OFFSET) + now.get(Calendar.DST_OFFSET));
+    calendar.add(Calendar.MILLISECOND, -gmtMillisecondOffset);
+    localTimeColumnValue = getClassicFormat().format(calendar.getTime(), new StringBuffer(),
+        new FieldPosition(0));
+
     return localTimeColumnValue;
   }
 
--- a/modules/org.openbravo.client.myob/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.myob/ob-widget-styles.css	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.client.myob/web/org.openbravo.userinterface.smartclient/openbravo/skins/Default/org.openbravo.client.myob/ob-widget-styles.css	Tue Nov 25 16:34:14 2014 +0100
@@ -235,7 +235,7 @@
   font-size: 16px;
   background-repeat: no-repeat;
   background-position: center 6px;
-  background-image: url(../../../../../../utility/ShowImageLogo?logo=banner-production);
+  background-image: url(../../utility/ShowImageLogo?logo=banner-production);
 }
 
 .OBWidgetAboutLabels {
--- a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/ADTreeDatasourceService.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/ADTreeDatasourceService.java	Tue Nov 25 16:34:14 2014 +0100
@@ -124,6 +124,7 @@
       }
       Tree tree = getTree(table, bobProperties);
       OBCriteria<TreeNode> adTreeNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      adTreeNodeCriteria.setFilterOnActive(false);
       adTreeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
       adTreeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, bobId));
       TreeNode treeNode = (TreeNode) adTreeNodeCriteria.uniqueResult();
@@ -263,6 +264,7 @@
     String selectClause = " tn.id as treeNodeId, tn.reportSet as parentId, tn.sequenceNumber as seqNo, tn.node as nodeId, e as entity";
     OBQuery<BaseOBObject> obq = OBDal.getInstance()
         .createQuery("ADTreeNode", joinClause.toString());
+    obq.setFilterOnActive(false);
     obq.setSelectClause(selectClause);
     obq.setFilterOnReadableOrganization(false);
     int nResults = obq.count();
@@ -360,6 +362,7 @@
     joinClause.append(" and tn.reportSet = ? order by tn.sequenceNumber ");
     OBQuery<BaseOBObject> obq = OBDal.getInstance()
         .createQuery("ADTreeNode", joinClause.toString());
+    obq.setFilterOnActive(false);
     final List<Object> parameters = new ArrayList<Object>();
     parameters.add(nodeId);
     obq.setParameters(parameters);
@@ -392,6 +395,7 @@
       // Last positioned child. Pick the highest sequence number of its brothers and add 10
       // No need to recompute sequence numbers
       OBCriteria<TreeNode> maxSeqNoCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      maxSeqNoCriteria.setFilterOnActive(false);
       maxSeqNoCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
       maxSeqNoCriteria.add(Restrictions.eq(TreeNode.PROPERTY_REPORTSET, newParentId));
       maxSeqNoCriteria.setProjection(Projections.max(TreeNode.PROPERTY_SEQUENCENUMBER));
@@ -400,6 +404,7 @@
     } else {
       // Sequence numbers of the nodes that are positioned after the new one needs to be recomputed
       OBCriteria<TreeNode> nextNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      nextNodeCriteria.setFilterOnActive(false);
       nextNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
       nextNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, nextNodeId));
       TreeNode nextNode = (TreeNode) nextNodeCriteria.uniqueResult();
@@ -528,6 +533,7 @@
     Table referencedTable = OBDal.getInstance().get(Table.class, referencedTableId);
 
     OBCriteria<Tree> treeCriteria = OBDal.getInstance().createCriteria(Tree.class);
+    treeCriteria.setFilterOnActive(false);
     treeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, referencedTable));
     treeCriteria.add(Restrictions.eq(Tree.PROPERTY_CLIENT, OBContext.getOBContext()
         .getCurrentClient()));
@@ -546,6 +552,7 @@
   private Tree getTree(Table table, JSONObject bobProperties) {
     Tree tree = null;
     OBCriteria<Tree> adTreeCriteria = OBDal.getInstance().createCriteria(Tree.class);
+    adTreeCriteria.setFilterOnActive(false);
     adTreeCriteria.add(Restrictions.eq(Tree.PROPERTY_TABLE, table));
     tree = (Tree) adTreeCriteria.uniqueResult();
     return tree;
@@ -618,6 +625,7 @@
     }
 
     OBCriteria<TreeNode> treeNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+    treeNodeCriteria.setFilterOnActive(false);
     treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
     treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, nodeId));
     TreeNode treeNode = (TreeNode) treeNodeCriteria.uniqueResult();
@@ -669,6 +677,7 @@
     JSONObject json = null;
     try {
       OBCriteria<TreeNode> treeNodeCriteria = OBDal.getInstance().createCriteria(TreeNode.class);
+      treeNodeCriteria.setFilterOnActive(false);
       treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_TREE, tree));
       treeNodeCriteria.add(Restrictions.eq(TreeNode.PROPERTY_NODE, bobId));
       TreeNode treeNode = (TreeNode) treeNodeCriteria.uniqueResult();
@@ -706,6 +715,7 @@
     joinClause.append(" and tn.node = ?");
     OBQuery<BaseOBObject> obq = OBDal.getInstance()
         .createQuery("ADTreeNode", joinClause.toString());
+    obq.setFilterOnActive(false);
 
     final List<Object> parameters = new ArrayList<Object>();
     parameters.add(nodeId);
--- a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DataSourceServlet.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/DataSourceServlet.java	Tue Nov 25 16:34:14 2014 +0100
@@ -555,7 +555,10 @@
           } else if (keyValue instanceof Number && keyValue != null) {
             DecimalFormat format = formats.get(key);
             if (format == null) {
-              keyValue = keyValue.toString().replace(".", decimalSeparator);
+              // if the CSV decimal separator property is defined, used it over the character
+              // defined in Format.xml
+              keyValue = keyValue.toString().replace(".",
+                  prefDecimalSeparator != null ? prefDecimalSeparator : decimalSeparator);
             } else {
               keyValue = format.format(new BigDecimal(keyValue.toString()));
               if (prefDecimalSeparator != null) {
--- a/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/TreeDatasourceService.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.service.datasource/src/org/openbravo/service/datasource/TreeDatasourceService.java	Tue Nov 25 16:34:14 2014 +0100
@@ -746,9 +746,10 @@
     }
     String hqlCopy = new String(hqlTreeWhereClause);
     for (String key : replacements.keySet()) {
-      // Value is equals 'null' when can not find in parameters.
+      // if the key is not found in the request parameters, its value in the replacement list will
+      // be 'null'
       if (replacements.get(key).equals("'null'")) {
-        // Obtain variable without the "@"
+        // Strip the "@" from the key
         String keyWithoutAt = key.substring(1, key.length() - 1);
         hqlCopy = hqlCopy.replaceAll(key,
             "'" + (String) RequestContext.get().getSessionAttribute(keyWithoutAt) + "'");
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java	Tue Nov 25 16:34:14 2014 +0100
@@ -410,7 +410,7 @@
 
     if (parameters.containsKey(JsonConstants.TARGETRECORDID_PARAMETER)
         && parameters.get(JsonConstants.TARGETRECORDID_PARAMETER) != null
-        && parameters.get(JsonConstants.TARGETRECORDID_PARAMETER) != "null"
+        && !"null".equals(parameters.get(JsonConstants.TARGETRECORDID_PARAMETER))
         && !"true".equals(parameters.get("_directNavigation"))) {
       log.warn("Datasource request with targetRecordId but without directNavigation detected. This type of requests should be avoided because they result in a query that performs poorly. Parameters: "
           + convertParameterToString(parameters));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/isomorphic/system/helpers/printFrame.html	Tue Nov 25 16:34:14 2014 +0100
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+
+<SCRIPT>
+
+
+
+if (!window.isc && document.domain && document.domain.indexOf(".") != -1 
+	&& !(new RegExp("^(\\d{1,3}\\.){3}\\d{1,3}$").test(document.domain))) 
+{
+    
+    var set = false;
+    while (document.domain.indexOf(".") != -1) {
+        try {
+            if (window.opener && window.opener.isc) break;
+            if (window.top.isc) break;
+            
+            if (!set) { document.domain = document.domain; set = true; }
+            else { document.domain = document.domain.replace(/.*?\./, ''); }
+        } catch (e) {
+            try {
+                if (!set) { document.domain = document.domain; set = true }
+                else { document.domain = document.domain.replace(/.*?\./, ''); }
+            } catch (ee) {
+                break;
+            }
+        }
+    } 
+}
+
+// document.write out our title and skin styles file
+if (window.parent && window.parent.isc) {
+
+    // Page title, and print target ID are driven by parameters to this page.
+    // We may not have a java server, so use the client-side getParams method to pick these up
+    window.params = window.parent.isc.getParams(window);
+
+    // Write out the title so we print with the appropriate title
+    if (params.title) document.write("<TITLE>" + params.title + "</TITLE>");
+}
+</SCRIPT>
+</HEAD>
+<BODY STYLE="overflow:visible;" onload="pageLoaded()" onafterprint="printed()">
+<SCRIPT>
+if (window.parent && window.parent.isc) {
+    // note that we need the parent.isc object to resolve the skinImgDir
+    document.write('<LINK REL="STYLESHEET" TYPE="text/css" HREF=' + 
+                   window.parent.isc.Page.getURL("[SKIN]/skin_styles.css")+
+                   ">");
+}
+</SCRIPT>
+
+<SCRIPT>
+function pageLoaded() {
+    window.controllerCanvas = params.id;
+    // Sanity check: Unclear why we should get into this state but if we can't
+    // find the print canvas for this iframe, log a warning and avoid the JS error
+    if (controllerCanvas == null || parent[controllerCanvas] == null) {
+        parent.isc.logWarn("Print canvas with ID:" + controllerCanvas + 
+            " failed to render correctly.", "printing");
+    } else {
+        parent[controllerCanvas].iframeLoad();
+    }
+}
+
+function printed() {
+    parent[window.controllerCanvas].printComplete();
+}
+
+function assignHTML(HTML) {
+    getPrintElement().innerHTML = HTML;
+}
+
+function getPrintElement() {
+    return document.getElementById('printElement');
+}
+
+function doPrint(callback) {
+    // focus() required for IE - otherwise it prints the top-level window
+    focus();
+    print();
+    
+}
+
+</SCRIPT>
+
+<span id='printElement'></span>
+
+</BODY>
+</HTML>
--- a/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js	Mon Nov 24 16:43:00 2014 +0100
+++ b/modules/org.openbravo.userinterface.smartclient/web/org.openbravo.userinterface.smartclient/js/ob-smartclient.js	Tue Nov 25 16:34:14 2014 +0100
@@ -763,10 +763,16 @@
 // if not overridden then also errors handled by OB are shown in a popup
 // see https://issues.openbravo.com/view.php?id=17136
 isc.RPCManager.addClassProperties({
-  _handleError: isc.RPCManager.getPrototype().handleError,
+  _originalhandleError: isc.RPCManager.handleError,
   handleError: function (response, request) {
+    var target = window[request.componentId];
+    // refresh the toolbar buttons if possible to ensure that the refresh button is enabled
+    if (target && target.view && target.view.toolBar && isc.isA.Function(target.view.toolBar.updateButtonState)) {
+      delete target.view.isRefreshing;
+      target.view.toolBar.updateButtonState();
+    }
     if (!request.willHandleError) {
-      isc.RPCManager.handleError(response, request);
+      this._originalhandleError(response, request);
     }
   },
   _originalEvalResult: isc.RPCManager.evalResult,
--- a/src-db/database/model/functions/M_INOUT_POST.xml	Mon Nov 24 16:43:00 2014 +0100
+++ b/src-db/database/model/functions/M_INOUT_POST.xml	Tue Nov 25 16:34:14 2014 +0100
@@ -115,6 +115,7 @@
     
     v_bp_isactive c_bpartner.isactive%Type;
     v_IsQtyVariable M_Product.IsQuantityVariable%TYPE;
+    v_IsReversedDoc CHAR(1);
 
   BEGIN
   
@@ -225,7 +226,12 @@
              RAISE_APPLICATION_ERROR(-20000, '@Inline@ '||v_Message_Qty||' '||'@ProductNotNullAndMovementQtyZero@') ;
           END IF;
 	     End ;
-      if(v_isreturndoctype = 'N' AND v_isSoTrx = 'Y' and v_DocAction<>'RC') then
+      SELECT CASE WHEN COALESCE(instr(M_INOUT.Description,'*R*:'),0) = 0 THEN 'N' ELSE 'Y' END
+            INTO v_IsReversedDoc
+            FROM M_INOUT
+            WHERE M_INOUT.M_INOUT_id = v_Record_ID;
+      -- Skip MovementQtyCheck when it is reversed document
+      if(v_isreturndoctype = 'N' AND v_isSoTrx = 'Y' and v_DocAction<>'RC' AND v_IsReversedDoc='N') then
         v_message := null;
         for Cur_OrderLine in (
           select c_orderline_id, line, m_product_id
@@ -234,13 +240,13 @@
           and c_orderline_id is not null
           order by line
         ) loop
-          select COALESCE(sum(movementqty), 0)
+          select COALESCE(sum(ABS(movementqty)), 0)
           into v_qty
           from m_inoutline
           where m_inout_id = v_Record_ID
           and c_orderline_id = Cur_OrderLine.c_orderline_id;
 
-          select qtyordered, (coalesce(qtydelivered, 0) + v_qty)
+          select ABS(qtyordered), (coalesce(ABS(qtydelivered), 0) + v_qty)
           into v_QuantityOrder, v_qty
           from c_orderline
           where c_orderline_id = Cur_OrderLine.c_orderline_id;
--- a/src-test/src/org/openbravo/test/AllWebserviceTests.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/src-test/src/org/openbravo/test/AllWebserviceTests.java	Tue Nov 25 16:34:14 2014 +0100
@@ -26,6 +26,7 @@
 import org.openbravo.test.datasource.SelectorFieldPropertySelectorDSTest;
 import org.openbravo.test.datasource.TestCSVEncoding;
 import org.openbravo.test.datasource.TestComboDatasource;
+import org.openbravo.test.webservice.JSONWebServices;
 import org.openbravo.test.webservice.PerformanceTest;
 import org.openbravo.test.webservice.WSAddRecordWithComputedColumns;
 import org.openbravo.test.webservice.WSReadTest;
@@ -48,6 +49,7 @@
     SelectorFieldPropertySelectorDSTest.class, //
     ProductSelectorDataSourceTest.class, //
     TestComboDatasource.class, //
-    FKDropDownDatasource.class })
+    FKDropDownDatasource.class, //
+    JSONWebServices.class })
 public class AllWebserviceTests {
 }
--- a/src-test/src/org/openbravo/test/security/AccessLevelTest.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/src-test/src/org/openbravo/test/security/AccessLevelTest.java	Tue Nov 25 16:34:14 2014 +0100
@@ -126,7 +126,7 @@
     final Client clientZero = OBDal.getInstance().get(Client.class, "0");
     final Organization orgZero = OBDal.getInstance().get(Organization.class, "0");
     for (Entity e : entities) {
-      if (e.isDataSourceBased()) {
+      if (e.isDataSourceBased() || e.isHQLBased()) {
         // The entity is not associated with a database table, so it does not apply
         continue;
       }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src-test/src/org/openbravo/test/webservice/JSONWebServices.java	Tue Nov 25 16:34:14 2014 +0100
@@ -0,0 +1,115 @@
+/*
+ *************************************************************************
+ * The contents of this file are subject to the Openbravo  Public  License
+ * Version  1.1  (the  "License"),  being   the  Mozilla   Public  License
+ * Version 1.1  with a permitted attribution clause; you may not  use this
+ * file except in compliance with the License. You  may  obtain  a copy of
+ * the License at http://www.openbravo.com/legal/license.html 
+ * Software distributed under the License  is  distributed  on  an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific  language  governing  rights  and  limitations
+ * under the License. 
+ * The Original Code is Openbravo ERP. 
+ * The Initial Developer of the Original Code is Openbravo SLU 
+ * All portions are Copyright (C) 2014 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.test.webservice;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.Test;
+import org.openbravo.base.exception.OBException;
+
+/**
+ * Test cases for JSON dal web services
+ * 
+ * @author alostale
+ *
+ */
+public class JSONWebServices extends BaseWSTest {
+  @SuppressWarnings("serial")
+  private final Set<String> expectedProperties = new HashSet<String>() {
+    {
+      // infrastructure properties, always present in all responses
+      add("_identifier");
+      add("_entityName");
+      add("$ref");
+      add("recordTime");
+
+      // selected properties
+      add("id");
+      add("name");
+    }
+  };
+
+  /** When getting a single record by id, selected properties should be taken into account */
+  @Test
+  public void selectedPropertiesUsingId() throws JSONException {
+    JSONObject resp = new JSONObject(
+        request("Country", "100", "_selectedProperties=id,name", "GET"));
+    assertSingleRecord(resp);
+  }
+
+  /**
+   * When getting a set of records without id, selected properties should be taken into account.
+   * 
+   * See https://issues.openbravo.com/view.php?id=28214
+   */
+  @Test
+  public void selectedPropertiesNotUsingId() throws JSONException {
+    JSONObject resp = new JSONObject(request("Country", "", "_selectedProperties=id,name", "GET"));
+    JSONObject firstRecord = resp.getJSONObject("response").getJSONArray("data").getJSONObject(0);
+    assertSingleRecord(firstRecord);
+  }
+
+  private void assertSingleRecord(JSONObject resp) {
+    @SuppressWarnings("unchecked")
+    Iterator<String> it = resp.keys();
+    Set<String> receivedProperties = new HashSet<String>();
+
+    while (it.hasNext()) {
+      receivedProperties.add(it.next());
+    }
+
+    assertThat("Properties received in JSON", receivedProperties, is(equalTo(expectedProperties)));
+  }
+
+  private String request(String entityName, String id, String queryPart, String method) {
+    String wsPart = entityName + (id == null ? "" : "/" + id)
+        + (queryPart == null ? "" : "?" + queryPart);
+
+    final StringBuilder sb = new StringBuilder();
+    try {
+
+      final HttpURLConnection hc = createConnection("/org.openbravo.service.json.jsonrest/"
+          + wsPart, method);
+      hc.connect();
+      final InputStream is = hc.getInputStream();
+      BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+
+      String line;
+      while ((line = reader.readLine()) != null) {
+        sb.append(line).append("\n");
+      }
+      return sb.toString();
+    } catch (Exception e) {
+      throw new OBException("Exception when executing ws: " + wsPart, e);
+    }
+  }
+}
--- a/src/org/openbravo/erpCommon/ad_reports/ReportTrialBalance.java	Mon Nov 24 16:43:00 2014 +0100
+++ b/src/org/openbravo/erpCommon/ad_reports/ReportTrialBalance.java	Tue Nov 25 16:34:14 2014 +0100
@@ -531,6 +531,10 @@
         advisePopUp(request, response, "WARNING",
             Utility.messageBD(this, "ProcessStatus-W", vars.getLanguage()),
             Utility.messageBD(this, "NoDataFound", vars.getLanguage()));
+      } else if (data.length > 65532) {
+        advisePopUp(request, response, "ERROR",
+            Utility.messageBD(this, "ProcessStatus-E", vars.getLanguage()),
+            Utility.messageBD(this, "numberOfRowsExceeded", vars.getLanguage()));
       } else {
 
         AcctSchema acctSchema = OBDal.getInstance().get(AcctSchema.class, strcAcctSchemaId);