From ec1d6bdc009320fdc2b47357fee50581cfcc5749 Mon Sep 17 00:00:00 2001 From: hieplq Date: Mon, 17 Oct 2016 16:11:21 +0700 Subject: [PATCH 1/7] IDEMPIERE-3220:read-only field can edit by development tool --- .../webui/session/SessionContextListener.java | 2 + .../session/ValidateReadonlyComponent.java | 116 ++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java index d69ad71bbf..6efd564e81 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/SessionContextListener.java @@ -304,6 +304,8 @@ public class SessionContextListener implements ExecutionInit, if(Executions.getCurrent()==null) return; + desktop.addListener(new ValidateReadonlyComponent()); + if (ServerContext.getCurrentInstance().isEmpty() || !isContextValid()) { setupExecutionContextFromSession(Executions.getCurrent()); diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java new file mode 100644 index 0000000000..e0179fd6ef --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java @@ -0,0 +1,116 @@ +/****************************************************************************** + * Product: iDempiere ERP & CRM Smart Business Solution * + * Copyright (C) 2014 T.G.I. * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + *****************************************************************************/ + +package org.adempiere.webui.session; + +import java.util.logging.Level; + +import org.compiere.util.CLogger; +import org.zkoss.zk.au.AuRequest; +import org.zkoss.zk.au.AuService; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.WrongValueException; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.ext.Disable; +import org.zkoss.zk.ui.ext.Readonly; +import org.zkoss.zul.Button; +import org.zkoss.zul.Checkbox; +import org.zkoss.zul.Combobox; +import org.zkoss.zul.impl.InputElement; + + +/** + * + * this service is interception into desktop process, + * it will denied request to modify a readonly file or action on readonly button + * @author hieplq + * + */ +public class ValidateReadonlyComponent implements AuService { + private static CLogger log = CLogger.getCLogger (ValidateReadonlyComponent.class); + /** + * throw WrongValueException when denied request, other false + */ + @Override + public boolean service(AuRequest request, boolean everError) { + String cmd = request.getCommand(); + + // event is reason change value of component + boolean considerEvent = Events.ON_CHANGE.equals(cmd) || Events.ON_CHECK.equals(cmd) || + Events.ON_SELECT.equals(cmd) || Events.ON_OPEN.equals(cmd) || + Events.ON_CLICK.equals(cmd) || Events.ON_DOUBLE_CLICK.equals(cmd) || Events.ON_OK.equals(cmd) || Events.ON_UPLOAD.equals(cmd); + + if (!considerEvent){ + return false; // don't denied + } + + Component comp = request.getComponent(); + + // get necessary interface + Disable iDisable = null; + Readonly iReadonly = null; + + if (comp instanceof Disable){ + iDisable = (Disable)comp; + } + + if (comp instanceof Readonly){ + iReadonly = (Readonly)comp; + } + + boolean isCannotEdit = (iDisable != null && iDisable.isDisabled()) || (iReadonly != null && iReadonly.isReadonly()); + + // don't care editable component + if (!isCannotEdit){ + return false; + } + + // detect kind of component raise event + InputElement inputComp = null; + Checkbox checkbox = null; + Combobox comb = null; + Button button = null; + + if (comp instanceof Combobox){// have to check before InputElement + comb = (Combobox)comp; + }if (comp instanceof InputElement){ + inputComp = (InputElement)comp;// textbox, datebox, numberbox,... + }else if (comp instanceof Checkbox){ + checkbox = (Checkbox)comp; + }if (comp instanceof Button){// have to check latest + button = (Button)comp; + }else {//HtmlBasedComponent + log.log(Level.SEVERE, String.format("Consider to denied event of control %1$s when it's readonly on event %2$s", comp.getClass(), cmd)); + return false;// just log to investigate don't lock process + } + + + if (isCannotEdit){ + boolean editing = (inputComp != null && Events.ON_CHANGE.equals(cmd)) || + (checkbox != null && Events.ON_CHECK.equals(cmd)) || + (comb != null && (Events.ON_CHANGE.equals(cmd) || Events.ON_SELECT.equals(cmd) || Events.ON_OPEN.equals(cmd))) || + (button != null && (Events.ON_CLICK.equals(cmd) || Events.ON_OK.equals(cmd) || Events.ON_UPLOAD.equals(cmd)));; + + // for combobox each change have both event onchange and onselect, so will have dupplicate message + // dupplicate is acceptable for hack guy + if (editing){ + comp.invalidate(); + throw new WrongValueException ("I know you. Don't try to hack me"); + } + } + + return false; + } + +} From cfb33c3e20c0129ce772a77b554700a25e45acc9 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Mon, 17 Oct 2016 18:42:35 +0200 Subject: [PATCH 2/7] IDEMPIERE-3220 read-only field can edit by development tool / peer review --- .../session/ValidateReadonlyComponent.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java index e0179fd6ef..52276ec6ad 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/session/ValidateReadonlyComponent.java @@ -33,7 +33,7 @@ import org.zkoss.zul.impl.InputElement; /** * * this service is interception into desktop process, - * it will denied request to modify a readonly file or action on readonly button + * it will deny request to modify a readonly field or action on readonly button * @author hieplq * */ @@ -82,15 +82,15 @@ public class ValidateReadonlyComponent implements AuService { Combobox comb = null; Button button = null; - if (comp instanceof Combobox){// have to check before InputElement + if (comp instanceof Combobox) {// have to check before InputElement comb = (Combobox)comp; - }if (comp instanceof InputElement){ + } else if (comp instanceof InputElement) { inputComp = (InputElement)comp;// textbox, datebox, numberbox,... - }else if (comp instanceof Checkbox){ + } else if (comp instanceof Checkbox) { checkbox = (Checkbox)comp; - }if (comp instanceof Button){// have to check latest + } else if (comp instanceof Button) {// have to check latest button = (Button)comp; - }else {//HtmlBasedComponent + } else {//HtmlBasedComponent log.log(Level.SEVERE, String.format("Consider to denied event of control %1$s when it's readonly on event %2$s", comp.getClass(), cmd)); return false;// just log to investigate don't lock process } @@ -102,15 +102,15 @@ public class ValidateReadonlyComponent implements AuService { (comb != null && (Events.ON_CHANGE.equals(cmd) || Events.ON_SELECT.equals(cmd) || Events.ON_OPEN.equals(cmd))) || (button != null && (Events.ON_CLICK.equals(cmd) || Events.ON_OK.equals(cmd) || Events.ON_UPLOAD.equals(cmd)));; - // for combobox each change have both event onchange and onselect, so will have dupplicate message - // dupplicate is acceptable for hack guy + // for combobox each change have both event onchange and onselect, so will have duplicate message + // duplicate is acceptable for hack guy if (editing){ comp.invalidate(); - throw new WrongValueException ("I know you. Don't try to hack me"); + throw new WrongValueException ("Field is read only"); } } return false; } -} +} \ No newline at end of file From f4c6b6f89c8f4d952a271157519b4c0839deef0b Mon Sep 17 00:00:00 2001 From: Diego Ruiz Date: Fri, 21 Oct 2016 18:07:11 +0200 Subject: [PATCH 3/7] IDEMPIERE-3224 Web service call ERROR: operator does not exist: numeric = character varying --- .../src/org/idempiere/webservices/AbstractService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org.idempiere.webservices/WEB-INF/src/org/idempiere/webservices/AbstractService.java b/org.idempiere.webservices/WEB-INF/src/org/idempiere/webservices/AbstractService.java index 48685917e1..bec6018169 100644 --- a/org.idempiere.webservices/WEB-INF/src/org/idempiere/webservices/AbstractService.java +++ b/org.idempiere.webservices/WEB-INF/src/org/idempiere/webservices/AbstractService.java @@ -446,6 +446,10 @@ public class AbstractService { if (indDot == -1) { if (varName.charAt(0) == '#') { val = getCompiereService().getCtx().getProperty(varName); + if (varName.endsWith("_ID") && val != null) { + Integer intVal = Integer.parseInt((String) val); + val = intVal; + } } else { // If there is no table name, then it should be // primitive data type From ebe2d323016ca7ddb242ca4d76978e0ea66aa588 Mon Sep 17 00:00:00 2001 From: "Redhuan D. Oon" Date: Wed, 26 Oct 2016 13:44:40 +0200 Subject: [PATCH 4/7] IDEMPIERE-3223 NPE when choose document type of sale order --- .../src/org/compiere/model/CalloutOrder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java b/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java index 670d252e26..e7af41069b 100644 --- a/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java +++ b/org.adempiere.base.callout/src/org/compiere/model/CalloutOrder.java @@ -84,7 +84,7 @@ public class CalloutOrder extends CalloutEngine int oldAD_Sequence_ID = 0; // Get old AD_SeqNo for comparison - if (!newDocNo && oldC_DocType_ID.intValue() != 0) + if (!newDocNo && oldC_DocType_ID != null && oldC_DocType_ID.intValue() != 0) { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, oldC_DocType_ID.intValue()); From e8d5bde8cbce9506b0edf01fea68d841b17b73c5 Mon Sep 17 00:00:00 2001 From: "Redhuan D. Oon" Date: Wed, 26 Oct 2016 17:13:16 +0200 Subject: [PATCH 5/7] IDEMPIERE-3225 Workflow editor menu is not updated / integrate patch from Flemming Birch (sjeffen) --- org.adempiere.base/src/org/compiere/wf/MWFNode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.adempiere.base/src/org/compiere/wf/MWFNode.java b/org.adempiere.base/src/org/compiere/wf/MWFNode.java index d0745c41a7..92d09ae777 100644 --- a/org.adempiere.base/src/org/compiere/wf/MWFNode.java +++ b/org.adempiere.base/src/org/compiere/wf/MWFNode.java @@ -252,6 +252,7 @@ public class MWFNode extends X_AD_WF_Node */ public MWFNodeNext[] getTransitions(int AD_Client_ID) { + loadNext(); ArrayList list = new ArrayList(); for (int i = 0; i < m_next.size(); i++) { From 81e3e9afbfcc4bf5d0c3d96aea88f7316a77692b Mon Sep 17 00:00:00 2001 From: Hans Auler GmbH Date: Tue, 25 Oct 2016 12:02:05 +0200 Subject: [PATCH 6/7] IDEMPIERE-3229 - Wrong accounting facts by using the GL Distribution - Line_ID is not transfered In the method distribute() from Fact.java is the line_id for factLine with 0 defined and later not updated, so the posting has always Line_ID=null in the destination-accounting-record. Queries like taxcorrection by discount or write off are searching for accounting facts with line_id = null and get wrong information. --- org.adempiere.base/src/org/compiere/acct/Fact.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.adempiere.base/src/org/compiere/acct/Fact.java b/org.adempiere.base/src/org/compiere/acct/Fact.java index d731e023b5..4565ec1622 100644 --- a/org.adempiere.base/src/org/compiere/acct/Fact.java +++ b/org.adempiere.base/src/org/compiere/acct/Fact.java @@ -734,7 +734,7 @@ public final class Fact if (!dl.isActive() || dl.getAmt().signum() == 0) continue; FactLine factLine = new FactLine (m_doc.getCtx(), m_doc.get_Table_ID(), - m_doc.get_ID(), 0, m_trxName); + m_doc.get_ID(), dLine.getLine_ID(), m_trxName); // Set Info & Account factLine.setDocumentInfo(m_doc, dLine.getDocLine()); factLine.setAccount(m_acctSchema, dl.getAccount()); From 6600f1a34f421c85ab4147b96ddae2d185cc505a Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 26 Oct 2016 22:59:09 +0200 Subject: [PATCH 7/7] IDEMPIERE-3231 Production document affecting storage for non-stocked products --- org.adempiere.base/src/org/compiere/model/MProductionLine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.adempiere.base/src/org/compiere/model/MProductionLine.java b/org.adempiere.base/src/org/compiere/model/MProductionLine.java index 94e0e9ec40..d91aa87553 100644 --- a/org.adempiere.base/src/org/compiere/model/MProductionLine.java +++ b/org.adempiere.base/src/org/compiere/model/MProductionLine.java @@ -81,7 +81,7 @@ public class MProductionLine extends X_M_ProductionLine { MProduct prod = new MProduct(getCtx(), getM_Product_ID(), get_TrxName()); if (log.isLoggable(Level.FINE))log.log(Level.FINE,"Loaded Product " + prod.toString()); - if ( prod.getProductType().compareTo(MProduct.PRODUCTTYPE_Item ) != 0 ) { + if ( !prod.isStocked() || prod.getProductType().compareTo(MProduct.PRODUCTTYPE_Item ) != 0 ) { // no need to do any movements if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Production Line " + getLine() + " does not require stock movement"); return "";