Added unique constraint/already updated/referenced item checking, improved message handling
authorMartin Taal <martin.taal@openbravo.com>
Tue, 11 Jan 2011 10:55:50 +0100
changeset 9697 8cf50d66f398
parent 9696 f69329bb98d9
child 9698 0da89c00434a
Added unique constraint/already updated/referenced item checking, improved message handling
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-messagebar.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-standard-view.js
modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-view-form.js
modules/org.openbravo.service.json/src-db/database/sourcedata/AD_MESSAGE.xml
modules/org.openbravo.service.json/src-db/database/sourcedata/AD_MODULE_DBPREFIX.xml
modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java
modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonConstants.java
modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonToDataConverter.java
modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonUtils.java
modules/org.openbravo.service.json/src/org/openbravo/service/json/OBStaleObjectException.java
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-messagebar.js	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-messagebar.js	Tue Jan 11 10:55:50 2011 +0100
@@ -101,7 +101,7 @@
     this.setText(title || this.getDefaultTitle(type), text);
     this.show();
   },
-
+  
   // calls te OB.I18N.getLabel to asynchronously get a label
   // and display it  
   setLabel: function(type, title, label, params){
@@ -111,6 +111,57 @@
         me.setMessage(type, title, text);
       }
     }, 'setLabel');
+  },
+  
+  // handles different ways by which an error can be passed from the 
+  // system, translates this to an object with a type, title and message
+  setErrorMessageFromResponse: function(resp, data, req){
+    // only handle it once
+    if (resp._errorMessageHandled) {
+      return true;
+    }
+    var msg = '', title = null, type = isc.OBMessageBar.TYPE_ERROR, isLabel = false, params = null;
+    if (isc.isA.String(data)) {
+      msg = data;
+    } else if (data && data.response && data.response.error) {
+      var error = data.response.error;
+      if (error.type && error.type === 'user') {
+        isLabel = true;
+        msg = error.message;
+        params = error.params;
+      } else if (error.message) {
+        type = error.messageType || type;
+        params = error.params;
+        // error.messageType can be Error
+        type = type.toLowerCase();
+        title = error.title || title;
+        msg = error.message;
+      } else {
+        // hope that someone else will handle it
+        return false;
+      }
+    } else if (data.data) {
+      // try it with data.data
+      return this.setErrorMessageFromResponse(resp, data.data, req);
+    } else {    
+      // hope that someone else will handle it
+      return false;
+    }
+
+    req.willHandleError = true;
+    resp._errorMessageHandled = true;
+    if (msg.indexOf('@') !== -1) {
+      index1 = msg.indexOf('@');
+      index2 = msg.indexOf('@', index1 + 1);
+      if (index2 !== -1) {
+        errorCode = msg.substring(index1 + 1, index2);
+        this.setLabel(type, title, errorCode, params);
+      }
+    } else if (isLabel) {
+      this.setLabel(type, title, msg, params);
+    } else {
+      this.setMessage(type, title, msg);
+    }
+    return true;
   }
-  
 });
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-standard-view.js	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-standard-view.js	Tue Jan 11 10:55:50 2011 +0100
@@ -218,18 +218,18 @@
       view: this,
       
       showProgress: function(editedRecord){
-        
+      
         // don't show it, done to quickly
         if (!editedRecord._showProgressAfterDelay) {
           return;
         }
-
+        
         if (editedRecord && editedRecord.editColumnLayout) {
           if (this.view.viewGrid.isVisible()) {
             editedRecord.editColumnLayout.toggleProgressIcon(true);
           }
         }
-
+        
         if (this.view.viewForm.isVisible()) {
           var btn = this.view.toolBar.getLeftMember(isc.OBToolbar.TYPE_SAVE);
           btn.customState = 'Progress';
@@ -252,7 +252,7 @@
       },
       
       performDSOperation: function(operationType, data, callback, requestProperties){
-//        requestProperties.showPrompt = false;
+        //        requestProperties.showPrompt = false;
         // set the current selected record before the delay
         var currentRecord = this.view.viewGrid.getSelectedRecord();
         if (currentRecord) {
@@ -283,22 +283,9 @@
         
         var errorStatus = !jsonData.response || jsonData.response.status === 'undefined' || jsonData.response.status !== isc.RPCResponse.STATUS_SUCCESS;
         if (errorStatus) {
-          if (jsonData.response && jsonData.response.error) {
-            var error = jsonData.response.error;
-            if (error.type && error.type === 'user') {
-              dsRequest.willHandleError = true;
-              this.view.messageBar.setLabel(isc.OBMessageBar.TYPE_ERROR, null, error.message, error.params);
-            } else if (!dsRequest.willHandleError) {
+          var handled = this.view.messageBar.setErrorMessageFromResponse(dsResponse, jsonData, dsRequest);
+          if (!handled && !dsRequest.willHandleError) {
               OB.KernelUtilities.handleSystemException(error.message);
-            }
-          } else if (!dsRequest.willHandleError) {
-            OB.KernelUtilities.handleSystemException('Error occured');
-          } else if (dsResponse.status && dsResponse.status === isc.RPCResponse.STATUS_FAILURE) {
-            dsRequest.willHandleError = true;
-            this.view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, jsonData.data);
-          } else {
-            dsRequest.willHandleError = true;
-            this.view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, OB.I18N.getLabel('OBUIAPP_ErrorInFields'));
           }
         } else {
           // there are some cases where the jsonData is not passed, in case of errors
@@ -1023,15 +1010,11 @@
           for (i = 0; i < selection.length; i++) {
             deleteData.ids.push(selection[i][OB.Constants.ID]);
           }
-          OB.RemoteCallManager.call('org.openbravo.client.application.MultipleDeleteActionHandler', deleteData, {
-            willHandleError: true
-          }, removeCallBack, {
+          OB.RemoteCallManager.call('org.openbravo.client.application.MultipleDeleteActionHandler', deleteData, {}, removeCallBack, {
             refreshGrid: true
           });
         } else {
-          view.viewGrid.removeData(selection[0], removeCallBack, {
-            willHandleError: true
-          });
+          view.viewGrid.removeData(selection[0], removeCallBack, {});
         }
       }
     };
--- a/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-view-form.js	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.client.application/web/org.openbravo.client.application/js/ob-view-form.js	Tue Jan 11 10:55:50 2011 +0100
@@ -440,18 +440,7 @@
         view.toolBar.setLeftMemberDisabled(isc.OBToolbar.TYPE_SAVE, false);
         form.handleFieldErrors(resp.errors, autoSave);
       } else {
-        if (isc.isA.String(data) && data.indexOf('@') !== -1) {
-          index1 = data.indexOf('@');
-          index2 = data.indexOf('@', index1 + 1);
-          if (index2 !== -1) {
-            errorCode = data.substring(index1 + 1, index2);
-            view.messageBar.setLabel(isc.OBMessageBar.TYPE_ERROR, null, errorCode);
-          } else {
-            view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, data);
-          }
-        } else {
-          view.messageBar.setMessage(isc.OBMessageBar.TYPE_ERROR, null, data);
-        }
+        view.messageBar.setErrorMessageFromResponse(resp, data, req);
         view.toolBar.setLeftMemberDisabled(isc.OBToolbar.TYPE_SAVE, false);
       }
       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.json/src-db/database/sourcedata/AD_MESSAGE.xml	Tue Jan 11 10:55:50 2011 +0100
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<data>
+<!--FF8081812D744D38012D745E4B22001F--><AD_MESSAGE>
+<!--FF8081812D744D38012D745E4B22001F-->  <AD_MESSAGE_ID><![CDATA[FF8081812D744D38012D745E4B22001F]]></AD_MESSAGE_ID>
+<!--FF8081812D744D38012D745E4B22001F-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--FF8081812D744D38012D745E4B22001F-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--FF8081812D744D38012D745E4B22001F-->  <ISACTIVE><![CDATA[N]]></ISACTIVE>
+<!--FF8081812D744D38012D745E4B22001F-->  <VALUE><![CDATA[OBJSON_StaleDate]]></VALUE>
+<!--FF8081812D744D38012D745E4B22001F-->  <MSGTEXT><![CDATA[The record you are saving has already been changed by another user or process. Refresh the data by clicking the refresh button, you will loose your current changes.]]></MSGTEXT>
+<!--FF8081812D744D38012D745E4B22001F-->  <MSGTYPE><![CDATA[I]]></MSGTYPE>
+<!--FF8081812D744D38012D745E4B22001F-->  <AD_MODULE_ID><![CDATA[F8D1B3ECB3474E8DA5C216473C840DF1]]></AD_MODULE_ID>
+<!--FF8081812D744D38012D745E4B22001F--></AD_MESSAGE>
+
+</data>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.json/src-db/database/sourcedata/AD_MODULE_DBPREFIX.xml	Tue Jan 11 10:55:50 2011 +0100
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<data>
+<!--FF8081812D744D38012D745E37B4001C--><AD_MODULE_DBPREFIX>
+<!--FF8081812D744D38012D745E37B4001C-->  <AD_MODULE_DBPREFIX_ID><![CDATA[FF8081812D744D38012D745E37B4001C]]></AD_MODULE_DBPREFIX_ID>
+<!--FF8081812D744D38012D745E37B4001C-->  <AD_CLIENT_ID><![CDATA[0]]></AD_CLIENT_ID>
+<!--FF8081812D744D38012D745E37B4001C-->  <AD_ORG_ID><![CDATA[0]]></AD_ORG_ID>
+<!--FF8081812D744D38012D745E37B4001C-->  <ISACTIVE><![CDATA[Y]]></ISACTIVE>
+<!--FF8081812D744D38012D745E37B4001C-->  <AD_MODULE_ID><![CDATA[F8D1B3ECB3474E8DA5C216473C840DF1]]></AD_MODULE_ID>
+<!--FF8081812D744D38012D745E37B4001C-->  <NAME><![CDATA[OBJSON]]></NAME>
+<!--FF8081812D744D38012D745E37B4001C--></AD_MODULE_DBPREFIX>
+
+</data>
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/DefaultJsonDataService.java	Tue Jan 11 10:55:50 2011 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2009 Openbravo SLU 
+ * All portions are Copyright (C) 2009-2011 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -260,8 +260,8 @@
         OBDal.getInstance().commitAndClose();
 
         return jsonResult.toString();
-      } catch (JSONException e) {
-        return JsonUtils.convertExceptionToJson(e);
+      } catch (Throwable t) {
+        return JsonUtils.convertExceptionToJson(t);
       }
     } else {
       return JsonUtils.convertExceptionToJson(new IllegalStateException("Object not found"));
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonConstants.java	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonConstants.java	Tue Jan 11 10:55:50 2011 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2009-2010 Openbravo SLU 
+ * All portions are Copyright (C) 2009-2011 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -77,6 +77,7 @@
   public static final String RESPONSE_STARTROW = "startRow";
   public static final String RESPONSE_ENDROW = "endRow";
   public static final String RESPONSE_TOTALROWS = "totalRows";
+  public static final String RESPONSE_ERROR = "error";
   public static final String RESPONSE_ERRORS = "errors";
   public static final String RESPONSE_ERRORMESSAGE = "errorMessage";
   public static final String RESPONSE_DATA = "data";
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonToDataConverter.java	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonToDataConverter.java	Tue Jan 11 10:55:50 2011 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2009 Openbravo SLU 
+ * All portions are Copyright (C) 2009-2011 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -35,13 +35,16 @@
 import org.codehaus.jettison.json.JSONException;
 import org.codehaus.jettison.json.JSONObject;
 import org.jfree.util.Log;
+import org.openbravo.base.exception.OBException;
 import org.openbravo.base.model.Entity;
 import org.openbravo.base.model.Property;
 import org.openbravo.base.provider.OBProvider;
 import org.openbravo.base.structure.BaseOBObject;
+import org.openbravo.base.structure.Traceable;
 import org.openbravo.base.util.Check;
 import org.openbravo.dal.service.OBDal;
 import org.openbravo.dal.service.OBQuery;
+import org.openbravo.model.common.enterprise.Organization;
 
 /**
  * Converts json data to Openbravo business object(s).
@@ -219,6 +222,26 @@
    *          the target of the data
    */
   protected void setData(JSONObject jsonObject, BaseOBObject obObject) throws JSONException {
+
+    // just use a random entity to get the name of the updated property
+    if (jsonObject.has(Organization.PROPERTY_UPDATED) && obObject instanceof Traceable) {
+      final String jsonDateStr = jsonObject.getString(Organization.PROPERTY_UPDATED);
+      if (jsonDateStr != null) {
+        try {
+          final Date jsonDate = new Timestamp(xmlDateTimeFormat.parse(jsonDateStr).getTime());
+          final Date objectDate = ((Traceable) obObject).getUpdated();
+          if (!areDatesEqual(jsonDate, objectDate, true)) {
+            // return this message code to let the client show a translated label
+            throw new OBStaleObjectException("@OBJSON_StaleDate@");
+          }
+        } catch (OBStaleObjectException x) {
+          throw x;
+        } catch (Exception e) {
+          throw new OBException("Exception when updating " + obObject, e);
+        }
+      }
+    }
+
     final Entity entity = obObject.getEntity();
 
     // collect the keys
--- a/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonUtils.java	Tue Jan 11 10:44:49 2011 +0100
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/JsonUtils.java	Tue Jan 11 10:55:50 2011 +0100
@@ -11,7 +11,7 @@
  * under the License. 
  * The Original Code is Openbravo ERP. 
  * The Initial Developer of the Original Code is Openbravo SLU 
- * All portions are Copyright (C) 2009 Openbravo SLU 
+ * All portions are Copyright (C) 2009-2011 Openbravo SLU 
  * All Rights Reserved. 
  * Contributor(s):  ______________________________________.
  ************************************************************************
@@ -25,11 +25,19 @@
 import java.util.List;
 import java.util.Map;
 
+import org.apache.log4j.Logger;
 import org.codehaus.jettison.json.JSONArray;
 import org.codehaus.jettison.json.JSONObject;
 import org.jfree.util.Log;
 import org.openbravo.base.model.Entity;
 import org.openbravo.base.model.Property;
+import org.openbravo.base.secureApp.VariablesSecureApp;
+import org.openbravo.client.kernel.RequestContext;
+import org.openbravo.dal.core.OBContext;
+import org.openbravo.dal.service.OBDal;
+import org.openbravo.erpCommon.utility.OBError;
+import org.openbravo.erpCommon.utility.Utility;
+import org.openbravo.service.db.DalConnectionProvider;
 
 /**
  * Contains utility methods used in this module.
@@ -37,6 +45,7 @@
  * @author mtaal
  */
 public class JsonUtils {
+  private static final Logger log = Logger.getLogger(JsonUtils.class);
 
   /**
    * @return a new instance of the {@link SimpleDateFormat} using a format of yyyy-MM-dd (xml schema
@@ -103,7 +112,29 @@
       final JSONObject jsonResult = new JSONObject();
       final JSONObject jsonResponse = new JSONObject();
       jsonResponse.put(JsonConstants.RESPONSE_STATUS, JsonConstants.RPCREQUEST_STATUS_FAILURE);
-      jsonResponse.put(JsonConstants.RESPONSE_DATA, localThrowable.getMessage());
+
+      try {
+        // get rid of the current transaction
+        OBDal.getInstance().rollbackAndClose();
+      } catch (Exception e) {
+        // ignored on purpose
+        log.error(e.getMessage(), e);
+      }
+
+      final VariablesSecureApp vars = RequestContext.get().getVariablesSecureApp();
+      final OBError obError = Utility.translateError(new DalConnectionProvider(), vars, OBContext
+          .getOBContext().getLanguage().getLanguage(), localThrowable.getMessage());
+
+      if (obError != null) {
+        final JSONObject error = new JSONObject();
+        error.put("message", obError.getMessage());
+        error.put("messageType", obError.getType());
+        error.put("title", obError.getTitle());
+        jsonResponse.put(JsonConstants.RESPONSE_ERROR, error);
+      } else {
+        jsonResponse.put(JsonConstants.RESPONSE_DATA, localThrowable.getMessage());
+      }
+
       jsonResponse.put(JsonConstants.RESPONSE_TOTALROWS, 0);
       jsonResult.put(JsonConstants.RESPONSE_RESPONSE, jsonResponse);
       return jsonResult.toString();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/org.openbravo.service.json/src/org/openbravo/service/json/OBStaleObjectException.java	Tue Jan 11 10:55:50 2011 +0100
@@ -0,0 +1,45 @@
+/*
+ *************************************************************************
+ * 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) 2011 Openbravo SLU 
+ * All Rights Reserved. 
+ * Contributor(s):  ______________________________________.
+ ************************************************************************
+ */
+
+package org.openbravo.service.json;
+
+import org.openbravo.base.exception.OBException;
+
+/**
+ * Is thrown when the json converter tries to update a BaseOBObject and the json value for the
+ * updated column is different from the value in the BaseOBObject.
+ * 
+ * @author mtaal
+ */
+public class OBStaleObjectException extends OBException {
+
+  private static final long serialVersionUID = 1L;
+
+  public OBStaleObjectException() {
+    super();
+  }
+
+  public OBStaleObjectException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public OBStaleObjectException(String message) {
+    super(message);
+  }
+}