diff --git a/web/org.openbravo.userinterface.smartclient/js/utilities.js b/web/org.openbravo.userinterface.smartclient/js/utilities.js
--- a/web/org.openbravo.userinterface.smartclient/js/utilities.js
+++ b/web/org.openbravo.userinterface.smartclient/js/utilities.js
@@ -98,16 +98,72 @@
   return str1 === str2;
 };
 
+OB.Utilities.processLogoutQueue = function() {
+  var q = OB.Utilities.logoutWorkQueue,
+          qElement, result, tab, tabID;
+
+  if(q && q.length === 0) {
+    return;
+  }
+
+  if(typeof arguments[1] === "string") {
+    // The 2nd parameter in a sendRequest callback is the 'data' parameter
+	// http://www.smartclient.com/docs/7.0rc2/a/b/c/go.html#type..RPCCallback
+    result = eval("("+arguments[1]+")");
+    if(result && result.oberror) {
+      if(result.oberror.type === "Error") {
+        tab = OB.MainView.TabSet.getTab(arguments[2].params.tabID);
+        if(tab) {
+          tab.pane.getAppFrameWindow().location.href = result.redirect;
+        }
+        q = [];
+        return;
+      }
+    }
+  }
+
+  // Process one element at the time,
+  // the save callbacks will empty the queue
+  qElement = q.pop();
+  if(qElement.func && qElement.args !== undefined) {
+    qElement.func.apply(qElement.self, qElement.args);
+  }
+};
 
 // ** {{{ OB.Utilities.logout }}} **
 // Logout from the application, removes server side session info and redirects
 // the client to the
 // Login page.
 OB.Utilities.logout = function() {
-  var redirectCallback = function() {
-    window.location.replace(OB.Application.loginPage);
-  };
-  OB.RemoteCallManager.call('org.openbravo.client.application.LogOutActionHandler', {}, {}, redirectCallback);
+	
+  var q = OB.Utilities.logoutWorkQueue = [],
+      i, tabs = OB.MainView.TabSet.tabs,
+      tabsLength = tabs.length, appFrame;
+
+  // Push the logout process to the 'end' of the queue
+  q.push({func: OB.RemoteCallManager.call,
+	      self: this,
+		  args: ['org.openbravo.client.application.LogOutActionHandler', {}, {}, function() {
+		            window.location.href = OB.Application.loginPage;
+		          }
+                ]});
+
+  for(i = 0; i < tabsLength; i++) {
+    if(tabs[i].pane.Class === "ClassicOBWindow") {
+      appFrame = tabs[i].pane.appFrameWindow || tabs[i].pane.getAppFrameWindow();
+      if(appFrame && appFrame.isUserChanges) {
+        if(appFrame.validate && !appFrame.validate()) {
+          q = [];
+          return;
+        }
+        q.push({func: tabs[i].pane.saveRecord,
+                self: tabs[i].pane,
+                args: [tabs[i].ID, OB.Utilities.processLogoutQueue]});
+      }
+    }
+  }
+
+  OB.Utilities.processLogoutQueue();
 };
 
 
@@ -204,10 +260,14 @@
 // 
 // Parameters:
 // * {{{criteria}}}: the current criteria object.
-OB.Utilities.addFormInputsToCriteria = function (/* Object */criteria) {
-  var elementsLength = document.frmMain.elements.length;
+// * {{{win}}}: (Optional) a reference to the global context (window) where to get the document
+//   and functions are located, if not passed, the current window is used
+OB.Utilities.addFormInputsToCriteria = function (/*Object*/ criteria, /*Window*/ win) {
+  var d = (win && win.document ? win.document : null) || window.document,
+      elementsLength = (d.frmMain ? d.frmMain.elements.length : 0),
+      inputValue = (win && win.inputValue ? win.inputValue : null) || window.inputValue;
   for (var i = 0; i < elementsLength; i++) {
-    var elem = document.frmMain.elements[i];
+    var elem = d.frmMain.elements[i];
     if(elem.name) {
       criteria[elem.name] = inputValue(elem);
     }
@@ -216,8 +276,8 @@
   // the form can have an organization field,
   // in the server it is used to determine the accessible orgs
   // TODO: make this optional or make it possible to set the orgid html id
-  if (document.frmMain.inpadOrgId) {
-    criteria[OB.Constants.ORG_PARAMETER] = inputValue(document.frmMain.inpadOrgId);
+  if (d.frmMain.inpadOrgId) {
+    criteria[OB.Constants.ORG_PARAMETER] = inputValue(d.frmMain.inpadOrgId);
   }
 };
 
