From fd16f78caabb119dd0f969a9cbbacb9ff9aa1942 Mon Sep 17 00:00:00 2001 From: Nicolas Micoud Date: Tue, 4 Aug 2015 20:58:37 -0500 Subject: [PATCH 01/15] IDEMPIERE-2658 Show bpartner name instead of user name in description of allocations generated from Payment Allocation --- org.adempiere.base/src/org/compiere/model/MAllocationHdr.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/model/MAllocationHdr.java b/org.adempiere.base/src/org/compiere/model/MAllocationHdr.java index 3ea5950a06..0f6232eb00 100644 --- a/org.adempiere.base/src/org/compiere/model/MAllocationHdr.java +++ b/org.adempiere.base/src/org/compiere/model/MAllocationHdr.java @@ -54,8 +54,7 @@ public class MAllocationHdr extends X_C_AllocationHdr implements DocAction /** * */ - private static final long serialVersionUID = -7787519874581251920L; - + private static final long serialVersionUID = 8726957992840702609L; /** Tolerance Gain and Loss */ private static final BigDecimal TOLERANCE = BigDecimal.valueOf(0.02); @@ -1265,6 +1264,7 @@ public class MAllocationHdr extends X_C_AllocationHdr implements DocAction if (sysconfig_desc.contains("@")) { description = Env.parseVariable(sysconfig_desc, new MBPartner(getCtx(), bpartnerID, null), trxName, true); description = Env.parseVariable(description, this, trxName, true); + description = Msg.parseTranslation(getCtx(), description); } else description = Env.getContext(getCtx(), "#AD_User_Name"); // just to be sure From 6ffc8721267385477343143485028441b9f307c0 Mon Sep 17 00:00:00 2001 From: tsvikruha Date: Mon, 3 Aug 2015 11:40:07 +0200 Subject: [PATCH 02/15] IDEMPIERE-2749 Internal Use Inventory - Document type Print Format ignored --- .../src/org/compiere/model/SystemIDs.java | 1 + .../src/org/compiere/print/ReportEngine.java | 25 ++++++++++++++++--- .../org/compiere/print/ServerReportCtl.java | 2 ++ .../src/org/compiere/print/ReportCtl.java | 3 +++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/model/SystemIDs.java b/org.adempiere.base/src/org/compiere/model/SystemIDs.java index 5685464606..a1eee0a94b 100644 --- a/org.adempiere.base/src/org/compiere/model/SystemIDs.java +++ b/org.adempiere.base/src/org/compiere/model/SystemIDs.java @@ -79,6 +79,7 @@ public class SystemIDs public final static int PROCESS_RPT_C_DUNNING = 159; public final static int PROCESS_RPT_FINREPORT = 202; public final static int PROCESS_RPT_FINSTATEMENT = 204; + public final static int PROCESS_RPT_M_INVENTORY = 291; public final static int REFERENCE_DATATYPE_ACCOUNT = 25; public final static int REFERENCE_DATATYPE_AMOUNT = 12; diff --git a/org.adempiere.base/src/org/compiere/print/ReportEngine.java b/org.adempiere.base/src/org/compiere/print/ReportEngine.java index 079afc9909..6cf688c663 100644 --- a/org.adempiere.base/src/org/compiere/print/ReportEngine.java +++ b/org.adempiere.base/src/org/compiere/print/ReportEngine.java @@ -17,6 +17,7 @@ package org.compiere.print; import static org.compiere.model.SystemIDs.TABLE_AD_TABLE; +import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INVENTORY; import java.awt.Color; import java.awt.Font; @@ -74,9 +75,11 @@ import org.compiere.model.MClient; import org.compiere.model.MColumn; import org.compiere.model.MDunningRunEntry; import org.compiere.model.MInOut; +import org.compiere.model.MInventory; import org.compiere.model.MInvoice; import org.compiere.model.MOrder; import org.compiere.model.MPaySelectionCheck; +import org.compiere.model.MProcess; import org.compiere.model.MProject; import org.compiere.model.MQuery; import org.compiere.model.MRfQResponse; @@ -1398,6 +1401,8 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) public static final int MANUFACTURING_ORDER = 8; /** Distribution Order = 9 */ public static final int DISTRIBUTION_ORDER = 9; + /** Physical Inventory = 10 */ + public static final int INVENTORY = 10; // private static final String[] DOC_TABLES = new String[] { @@ -1409,17 +1414,17 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) "C_Order", "M_InOut", "C_Invoice", "C_Project", "C_RfQResponse", "C_PaySelectionCheck", "C_PaySelectionCheck", - "C_DunningRunEntry","PP_Order", "DD_Order"}; + "C_DunningRunEntry","PP_Order", "DD_Order", "M_Inventory"}; private static final String[] DOC_IDS = new String[] { "C_Order_ID", "M_InOut_ID", "C_Invoice_ID", "C_Project_ID", "C_RfQResponse_ID", "C_PaySelectionCheck_ID", "C_PaySelectionCheck_ID", - "C_DunningRunEntry_ID" , "PP_Order_ID" , "DD_Order_ID" }; + "C_DunningRunEntry_ID" , "PP_Order_ID" , "DD_Order_ID", "M_Inventory_ID" }; private static final int[] DOC_TABLE_ID = new int[] { MOrder.Table_ID, MInOut.Table_ID, MInvoice.Table_ID, MProject.Table_ID, MRfQResponse.Table_ID, MPaySelectionCheck.Table_ID, MPaySelectionCheck.Table_ID, - MDunningRunEntry.Table_ID, X_PP_Order.Table_ID, MDDOrder.Table_ID }; + MDunningRunEntry.Table_ID, X_PP_Order.Table_ID, MDDOrder.Table_ID, MInventory.Table_ID }; /************************************************************************** * Get Document Print Engine for Document Type. @@ -1555,6 +1560,12 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) .append("WHERE d." + DOC_IDS[type] + "=?") // info from PrintForm .append(" AND pf.AD_Org_ID IN (0,d.AD_Org_ID) ") .append("ORDER BY pf.AD_Org_ID DESC"); + else if (type == INVENTORY) + sql = new StringBuilder("SELECT COALESCE (dt.AD_PrintFormat_ID, 0), 0,") // 1..2 + .append(" NULL, 0 , d.DocumentNo ") // 3..5 + .append("FROM " + DOC_BASETABLES[type] + " d") + .append(" LEFT OUTER JOIN C_DocType dt ON (d.C_DocType_ID=dt.C_DocType_ID) ") + .append("WHERE d." + DOC_IDS[type] + "=?"); // info from PrintForm else // Get PrintFormat from Org or 0 of document client sql = new StringBuilder("SELECT pf.Order_PrintFormat_ID,pf.Shipment_PrintFormat_ID,") // 1..2 // Prio: 1. BPartner 2. DocType, 3. PrintFormat (Org) // see InvoicePrint @@ -1583,7 +1594,8 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) if (rs.next()) // first record only { if (type == CHECK || type == DUNNING || type == REMITTANCE - || type == PROJECT || type == RFQ || type == MANUFACTURING_ORDER || type == DISTRIBUTION_ORDER) + || type == PROJECT || type == RFQ || type == MANUFACTURING_ORDER || type == DISTRIBUTION_ORDER + || type == INVENTORY) { AD_PrintFormat_ID = rs.getInt(1); copies = 1; @@ -1599,6 +1611,11 @@ queued-job-count = 0 (class javax.print.attribute.standard.QueuedJobCount) } else DocumentNo = rs.getString(5); + + if(AD_PrintFormat_ID == 0 && type == INVENTORY){ + MProcess process = MProcess.get(ctx, PROCESS_RPT_M_INVENTORY); + AD_PrintFormat_ID = process.getAD_PrintFormat_ID(); + } } else { diff --git a/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java b/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java index 048f883255..d3778fa169 100644 --- a/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java +++ b/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java @@ -201,6 +201,8 @@ public class ServerReportCtl { else if (pi.getAD_Process_ID() == 202 // Financial Report || pi.getAD_Process_ID() == 204) // Financial Statement return startFinReport (pi); + else if (pi.getAD_Process_ID() == 291) // M_Inventory + return startDocumentPrint(ReportEngine.INVENTORY, null, pi.getRecord_ID(), null, pi); /******************** * Standard Report *******************/ diff --git a/org.adempiere.ui/src/org/compiere/print/ReportCtl.java b/org.adempiere.ui/src/org/compiere/print/ReportCtl.java index c857cf12d3..861ceaa49f 100644 --- a/org.adempiere.ui/src/org/compiere/print/ReportCtl.java +++ b/org.adempiere.ui/src/org/compiere/print/ReportCtl.java @@ -25,6 +25,7 @@ import static org.compiere.model.SystemIDs.PROCESS_RPT_C_RFQRESPONSE; import static org.compiere.model.SystemIDs.PROCESS_RPT_FINREPORT; import static org.compiere.model.SystemIDs.PROCESS_RPT_FINSTATEMENT; import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INOUT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INVENTORY; import java.util.Properties; import java.util.logging.Level; @@ -155,6 +156,8 @@ public class ReportCtl return startDocumentPrint(ReportEngine.RFQ, pi.getRecord_ID(), parent, WindowNo, !pi.isPrintPreview()); else if (pi.getAD_Process_ID() == PROCESS_RPT_C_PAYMENT) // C_Payment return startCheckPrint(pi.getRecord_ID(), !pi.isPrintPreview()); + else if (pi.getAD_Process_ID() == PROCESS_RPT_M_INVENTORY) // Physical Inventory + return startDocumentPrint(ReportEngine.INVENTORY, pi.getRecord_ID(), parent, WindowNo, !pi.isPrintPreview()); /** else if (pi.getAD_Process_ID() == 290) // Movement Submission by VHARCQ return startDocumentPrint(ReportEngine.MOVEMENT, pi.getRecord_ID(), parent, WindowNo, IsDirectPrint); From 6fc6bef52c2814b12ab35d03e38ef2b64dec2da0 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Tue, 4 Aug 2015 21:14:31 -0500 Subject: [PATCH 03/15] IDEMPIERE-2749 Internal Use Inventory - Document type Print Format ignored / peer review --- .../org/compiere/print/ServerReportCtl.java | 28 +++++++++++------ .../org/idempiere/adinterface/Process.java | 31 +++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java b/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java index d3778fa169..84c3117421 100644 --- a/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java +++ b/org.adempiere.base/src/org/compiere/print/ServerReportCtl.java @@ -1,5 +1,15 @@ package org.compiere.print; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_DUNNING; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_INVOICE; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_ORDER; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_PROJECT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_RFQRESPONSE; +import static org.compiere.model.SystemIDs.PROCESS_RPT_FINREPORT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_FINSTATEMENT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INOUT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INVENTORY; + import java.util.ArrayList; import java.util.Properties; import java.util.logging.Level; @@ -182,26 +192,26 @@ public class ServerReportCtl { /** * Order Print */ - if (pi.getAD_Process_ID() == 110) // C_Order + if (pi.getAD_Process_ID() == PROCESS_RPT_C_ORDER) // C_Order return startDocumentPrint(ReportEngine.ORDER, null, pi.getRecord_ID(), null, pi); if (pi.getAD_Process_ID() == MProcess.getProcess_ID("Rpt PP_Order", null)) // C_Order return startDocumentPrint(ReportEngine.MANUFACTURING_ORDER, null, pi.getRecord_ID(), null, pi); if (pi.getAD_Process_ID() == MProcess.getProcess_ID("Rpt DD_Order", null)) // C_Order return startDocumentPrint(ReportEngine.DISTRIBUTION_ORDER, null, pi.getRecord_ID(), null, pi); - else if (pi.getAD_Process_ID() == 116) // C_Invoice + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_INVOICE) // C_Invoice return startDocumentPrint(ReportEngine.INVOICE, null, pi.getRecord_ID(), null, pi); - else if (pi.getAD_Process_ID() == 117) // M_InOut + else if (pi.getAD_Process_ID() == PROCESS_RPT_M_INOUT) // M_InOut return startDocumentPrint(ReportEngine.SHIPMENT, null, pi.getRecord_ID(), null, pi); - else if (pi.getAD_Process_ID() == 217) // C_Project + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_PROJECT) // C_Project return startDocumentPrint(ReportEngine.PROJECT, null, pi.getRecord_ID(), null, pi); - else if (pi.getAD_Process_ID() == 276) // C_RfQResponse + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_RFQRESPONSE) // C_RfQResponse return startDocumentPrint(ReportEngine.RFQ, null, pi.getRecord_ID(), null, pi); - else if (pi.getAD_Process_ID() == 159) // Dunning + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_DUNNING) // Dunning return startDocumentPrint(ReportEngine.DUNNING, null, pi.getRecord_ID(), null, pi); - else if (pi.getAD_Process_ID() == 202 // Financial Report - || pi.getAD_Process_ID() == 204) // Financial Statement + else if (pi.getAD_Process_ID() == PROCESS_RPT_FINREPORT // Financial Report + || pi.getAD_Process_ID() == PROCESS_RPT_FINSTATEMENT) // Financial Statement return startFinReport (pi); - else if (pi.getAD_Process_ID() == 291) // M_Inventory + else if (pi.getAD_Process_ID() == PROCESS_RPT_M_INVENTORY) // M_Inventory return startDocumentPrint(ReportEngine.INVENTORY, null, pi.getRecord_ID(), null, pi); /******************** * Standard Report diff --git a/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/Process.java b/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/Process.java index 906ed17baa..612709788c 100644 --- a/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/Process.java +++ b/org.idempiere.webservices/WEB-INF/src/org/idempiere/adinterface/Process.java @@ -1,5 +1,16 @@ package org.idempiere.adinterface; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_DUNNING; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_INVOICE; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_ORDER; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_PAYMENT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_PROJECT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_C_RFQRESPONSE; +import static org.compiere.model.SystemIDs.PROCESS_RPT_FINREPORT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_FINSTATEMENT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INOUT; +import static org.compiere.model.SystemIDs.PROCESS_RPT_M_INVENTORY; + import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.math.BigDecimal; @@ -697,28 +708,30 @@ public class Process { /** * Order Print */ - if (pi.getAD_Process_ID() == 110) // C_Order + if (pi.getAD_Process_ID() == PROCESS_RPT_C_ORDER) // C_Order return startDocumentPrint(ReportEngine.ORDER, pi.getRecord_ID()); - else if (pi.getAD_Process_ID() == 116) // C_Invoice + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_INVOICE) // C_Invoice return startDocumentPrint(ReportEngine.INVOICE, pi.getRecord_ID()); - else if (pi.getAD_Process_ID() == 117) // M_InOut + else if (pi.getAD_Process_ID() == PROCESS_RPT_M_INOUT) // M_InOut return startDocumentPrint(ReportEngine.SHIPMENT, pi.getRecord_ID()); - else if (pi.getAD_Process_ID() == 217) // C_Project + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_PROJECT) // C_Project return startDocumentPrint(ReportEngine.PROJECT, pi.getRecord_ID()); - else if (pi.getAD_Process_ID() == 276) // C_RfQResponse + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_RFQRESPONSE) // C_RfQResponse return startDocumentPrint(ReportEngine.RFQ, pi.getRecord_ID()); - else if (pi.getAD_Process_ID() == 313) // C_Payment + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_PAYMENT) // C_Payment return startCheckPrint(pi.getRecord_ID()); + else if (pi.getAD_Process_ID() == PROCESS_RPT_M_INVENTORY) // Physical Inventory + return startDocumentPrint(ReportEngine.INVENTORY, pi.getRecord_ID()); /** else if (pi.AD_Process_ID == 9999999) // PaySelection return startDocumentPrint(CHECK, pi, IsDirectPrint); else if (pi.AD_Process_ID == 9999999) // PaySelection return startDocumentPrint(REMITTANCE, pi, IsDirectPrint); **/ - else if (pi.getAD_Process_ID() == 159) // Dunning + else if (pi.getAD_Process_ID() == PROCESS_RPT_C_DUNNING) // Dunning return startDocumentPrint(ReportEngine.DUNNING, pi.getRecord_ID()); - else if (pi.getAD_Process_ID() == 202 // Financial Report - || pi.getAD_Process_ID() == 204) // Financial Statement + else if (pi.getAD_Process_ID() == PROCESS_RPT_FINREPORT // Financial Report + || pi.getAD_Process_ID() == PROCESS_RPT_FINSTATEMENT) // Financial Statement return startFinReport (pi); /******************** * Standard Report From b493a2567d03d6f2da14b48ec9c8e688ff7a56b7 Mon Sep 17 00:00:00 2001 From: tsvikruha Date: Mon, 3 Aug 2015 08:25:10 +0200 Subject: [PATCH 04/15] IDEMPIERE-2746 Invoice (customer) doesnt load Sales Rep from Business Partner --- .../src/org/compiere/model/CalloutInvoice.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java b/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java index 6a98f5c025..729785cbc8 100644 --- a/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java +++ b/org.adempiere.base.callout/src/org/compiere/model/CalloutInvoice.java @@ -133,7 +133,7 @@ public class CalloutInvoice extends CalloutEngine + " p.SO_Description,p.IsDiscountPrinted," + " p.SO_CreditLimit, p.SO_CreditLimit-p.SO_CreditUsed AS CreditAvailable," + " l.C_BPartner_Location_ID,c.AD_User_ID," - + " COALESCE(p.PO_PriceList_ID,g.PO_PriceList_ID) AS PO_PriceList_ID, p.PaymentRulePO,p.PO_PaymentTerm_ID " + + " COALESCE(p.PO_PriceList_ID,g.PO_PriceList_ID) AS PO_PriceList_ID, p.PaymentRulePO,p.PO_PaymentTerm_ID, p.SalesRep_ID " + "FROM C_BPartner p" + " INNER JOIN C_BP_Group g ON (p.C_BP_Group_ID=g.C_BP_Group_ID)" + " LEFT OUTER JOIN C_BPartner_Location l ON (p.C_BPartner_ID=l.C_BPartner_ID AND l.IsBillTo='Y' AND l.IsActive='Y')" @@ -151,6 +151,13 @@ public class CalloutInvoice extends CalloutEngine // if (rs.next()) { + // Sales Rep - If BP has a default SalesRep then default it + Integer salesRep = rs.getInt("SalesRep_ID"); + if (IsSOTrx && salesRep != 0 ) + { + mTab.setValue("SalesRep_ID", salesRep); + } + // PriceList & IsTaxIncluded & Currency Integer ii = new Integer(rs.getInt(IsSOTrx ? "M_PriceList_ID" : "PO_PriceList_ID")); if (!rs.wasNull()) From a674a185a32529b60cd1b09448a147ab1f903ae8 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Tue, 4 Aug 2015 15:52:19 -0500 Subject: [PATCH 05/15] IDEMPIERE-2064 Implement toolbar+tab button / implement backward compatibility with 2packs generated before IDEMPIERE-2477 --- .../src/org/adempiere/pipo2/PoFiller.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/org.adempiere.pipo/src/org/adempiere/pipo2/PoFiller.java b/org.adempiere.pipo/src/org/adempiere/pipo2/PoFiller.java index 60fcb6ff04..5254ddd427 100644 --- a/org.adempiere.pipo/src/org/adempiere/pipo2/PoFiller.java +++ b/org.adempiere.pipo/src/org/adempiere/pipo2/PoFiller.java @@ -57,8 +57,16 @@ public class PoFiller{ return; else if (oldValue != null && oldValue.toString().equals(value)) return; - else + else { + if (po instanceof MColumn && "IsToolbarButton".equals(columnName)) { + // IDEMPIERE-2064 - backward compatibility with 2packs generated before IDEMPIERE-2477 + if ("true".equals(value)) + value ="Y"; + else if ("false".equals(value)) + value ="N"; + } po.set_ValueNoCheck(columnName, value); + } } /** From 2694d54b7180c8f04af090c8f13c0124b6b0375d Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 5 Aug 2015 07:11:13 -0500 Subject: [PATCH 06/15] IDEMPIERE-2752 Same Attribute Instance on many Products --- .../src/org/compiere/model/MProduct.java | 30 +++++++++++++------ .../webui/window/WPAttributeDialog.java | 4 +-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/model/MProduct.java b/org.adempiere.base/src/org/compiere/model/MProduct.java index d6c9ef5fb9..fcd11091af 100644 --- a/org.adempiere.base/src/org/compiere/model/MProduct.java +++ b/org.adempiere.base/src/org/compiere/model/MProduct.java @@ -598,17 +598,29 @@ public class MProduct extends X_M_Product m_precision = null; // AttributeSetInstance reset - if (is_ValueChanged(COLUMNNAME_M_AttributeSet_ID)) + if (getM_AttributeSetInstance_ID() > 0 && is_ValueChanged(COLUMNNAME_M_AttributeSet_ID)) { MAttributeSetInstance asi = new MAttributeSetInstance(getCtx(), getM_AttributeSetInstance_ID(), get_TrxName()); - setM_AttributeSetInstance_ID(0); - // Delete the old m_attributesetinstance - try { - asi.deleteEx(true, get_TrxName()); - } catch (AdempiereException ex) - { - log.saveError("Error", "Error deleting the AttributeSetInstance"); - return false; + if (asi.getM_AttributeSet_ID() != getM_AttributeSet_ID()) + setM_AttributeSetInstance_ID(0); + } + if (!newRecord && is_ValueChanged(COLUMNNAME_M_AttributeSetInstance_ID)) + { + // IDEMPIERE-2752 check if the ASI is referenced in other products before trying to delete it + int oldasiid = get_ValueOldAsInt(COLUMNNAME_M_AttributeSetInstance_ID); + if (oldasiid > 0) { + MAttributeSetInstance oldasi = new MAttributeSetInstance(getCtx(), get_ValueOldAsInt(COLUMNNAME_M_AttributeSetInstance_ID), get_TrxName()); + int cnt = DB.getSQLValueEx(get_TrxName(), "SELECT COUNT(*) FROM M_Product WHERE M_AttributeSetInstance_ID=?", oldasi.getM_AttributeSetInstance_ID()); + if (cnt == 1) { + // Delete the old m_attributesetinstance + try { + oldasi.deleteEx(true, get_TrxName()); + } catch (AdempiereException ex) + { + log.saveError("Error", "Error deleting the AttributeSetInstance"); + return false; + } + } } } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WPAttributeDialog.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WPAttributeDialog.java index 0527c39010..ef021501ae 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WPAttributeDialog.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/WPAttributeDialog.java @@ -253,7 +253,8 @@ public class WPAttributeDialog extends Window implements EventListener MAttributeSet as = null; - if (m_M_Product_ID != 0) + int M_AttributeSet_ID = Env.getContextAsInt(Env.getCtx(), m_WindowNoParent, "M_AttributeSet_ID"); + if (m_M_Product_ID != 0 && M_AttributeSet_ID == 0) { // Get Model m_masi = MAttributeSetInstance.get(Env.getCtx(), m_M_AttributeSetInstance_ID, m_M_Product_ID); @@ -269,7 +270,6 @@ public class WPAttributeDialog extends Window implements EventListener } else { - int M_AttributeSet_ID = Env.getContextAsInt(Env.getCtx(), m_WindowNoParent, "M_AttributeSet_ID"); m_masi = new MAttributeSetInstance (Env.getCtx(), m_M_AttributeSetInstance_ID, M_AttributeSet_ID, null); as = m_masi.getMAttributeSet(); } From a1702112f15d66b8cbadda0f4cca9c2413c7de7f Mon Sep 17 00:00:00 2001 From: Deepak Pansheriya Date: Wed, 5 Aug 2015 19:24:00 +0530 Subject: [PATCH 07/15] IDEMPIERE-2675: Adding custom table support in Tree --- .../oracle/201506241206_IDEMPIERE-2675.sql | 58 +++++++++++++++++++ .../201506241206_IDEMPIERE-2675.sql | 56 ++++++++++++++++++ .../src/org/compiere/model/I_AD_Tree.java | 15 +++++ .../src/org/compiere/model/MTree.java | 31 +++++++++- .../src/org/compiere/model/X_AD_Tree.java | 32 +++++++++- 5 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 migration/i2.1z/oracle/201506241206_IDEMPIERE-2675.sql create mode 100644 migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql diff --git a/migration/i2.1z/oracle/201506241206_IDEMPIERE-2675.sql b/migration/i2.1z/oracle/201506241206_IDEMPIERE-2675.sql new file mode 100644 index 0000000000..784db49eb5 --- /dev/null +++ b/migration/i2.1z/oracle/201506241206_IDEMPIERE-2675.sql @@ -0,0 +1,58 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jun 18, 2015 10:47:07 AM IST +INSERT INTO AD_Column (SeqNoSelection,AD_Column_ID,IsAlwaysUpdateable,IsSyncDatabase,AD_Client_ID,AD_Org_ID,CreatedBy,Updated,UpdatedBy,EntityType,IsSecure,IsEncrypted,IsParent,IsMandatory,IsIdentifier,SeqNo,Help,Version,FieldLength,IsKey,IsTranslated,Created,IsUpdateable,IsAutocomplete,IsAllowLogging,IsAllowCopy,Description,ColumnName,Name,IsSelectionColumn,AD_Column_UU,IsActive,IsToolbarButton,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID) VALUES (0,212212,'N','N',0,0,100,TO_DATE('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),100,'D','N','N','N','N','N',0,'The Database Table provides the information of the table definition',0,10,'N','N',TO_DATE('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),'Y','N','Y','Y','Database Table information','AD_Table_ID','Table','N','cd639a6d-243f-4737-80b7-e953534cafa6','Y','N','N',126,19,288) +; + +-- Jun 18, 2015 10:47:12 AM IST +UPDATE AD_Column SET FKConstraintType='N', FKConstraintName='ADTable_ADTree',Updated=TO_DATE('2015-06-18 10:47:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +-- Jun 18, 2015 10:47:12 AM IST +ALTER TABLE AD_Tree ADD AD_Table_ID NUMBER(10) DEFAULT NULL +; + +-- Jun 18, 2015 10:47:12 AM IST +ALTER TABLE AD_Tree ADD CONSTRAINT ADTable_ADTree FOREIGN KEY (AD_Table_ID) REFERENCES ad_table(ad_table_id) DEFERRABLE INITIALLY DEFERRED +; + +-- Jun 18, 2015 10:47:46 AM IST +INSERT INTO AD_Ref_List (AD_Ref_List_ID,CreatedBy,UpdatedBy,Created,Updated,EntityType,AD_Client_ID,AD_Org_ID,Description,Value,Name,IsActive,AD_Ref_List_UU,AD_Reference_ID) VALUES (200310,100,100,TO_DATE('2015-06-18 10:47:45','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2015-06-18 10:47:45','YYYY-MM-DD HH24:MI:SS'),'D',0,0,'Custom Table','TL','Custom Table','Y','e3104c45-9a71-4ea1-bd24-9125d33f07db',120) +; + +-- Jun 18, 2015 10:48:11 AM IST +INSERT INTO AD_Field (ColumnSpan,AD_Field_ID,AD_Client_ID,CreatedBy,AD_Org_ID,Updated,UpdatedBy,IsHeading,IsDisplayed,IsFieldOnly,IsSameLine,IsDisplayedGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,Created,EntityType,Name,IsEncrypted,DisplayLength,AD_Field_UU,IsActive,AD_Column_ID,AD_Tab_ID) VALUES (2,203825,0,100,0,TO_DATE('2015-06-18 10:48:05','YYYY-MM-DD HH24:MI:SS'),100,'N','N','N','N','N',100,'N','Y',TO_DATE('2015-06-18 10:48:05','YYYY-MM-DD HH24:MI:SS'),'D','AD_Tree_UU','N',36,'13075486-eba0-4882-8270-9205a2440b6f','Y',60514,243) +; + +-- Jun 18, 2015 10:48:11 AM IST +INSERT INTO AD_Field (ColumnSpan,AD_Field_ID,AD_Client_ID,CreatedBy,AD_Org_ID,Updated,UpdatedBy,IsHeading,Help,IsDisplayed,IsFieldOnly,IsSameLine,SeqNo,IsReadOnly,IsCentrallyMaintained,Created,EntityType,Name,Description,IsEncrypted,DisplayLength,AD_Field_UU,IsActive,AD_Column_ID,AD_Tab_ID) VALUES (2,203826,0,100,0,TO_DATE('2015-06-18 10:48:11','YYYY-MM-DD HH24:MI:SS'),100,'N','The Database Table provides the information of the table definition','Y','N','N',110,'N','Y',TO_DATE('2015-06-18 10:48:11','YYYY-MM-DD HH24:MI:SS'),'D','Table','Database Table information','N',10,'f7ca6a1b-4a96-48fe-938e-6784af276493','Y',212212,243) +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=203825 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=70,IsDisplayed='Y' WHERE AD_Field_ID=203826 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=80,IsDisplayed='Y' WHERE AD_Field_ID=5228 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=90,IsDisplayed='Y' WHERE AD_Field_ID=12421 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=100,IsDisplayed='Y' WHERE AD_Field_ID=8371 +; + +-- Jun 18, 2015 10:49:23 AM IST +UPDATE AD_Field SET DisplayLogic='@TreeType@=''TL''',Updated=TO_DATE('2015-06-18 10:49:23','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=203826 +; + + +SELECT register_migration_script('201506241206_IDEMPIERE-2675.sql') FROM dual +; \ No newline at end of file diff --git a/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql b/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql new file mode 100644 index 0000000000..92394278b6 --- /dev/null +++ b/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql @@ -0,0 +1,56 @@ + +-- Jun 18, 2015 10:47:07 AM IST +INSERT INTO AD_Column (SeqNoSelection,AD_Column_ID,IsAlwaysUpdateable,IsSyncDatabase,AD_Client_ID,AD_Org_ID,CreatedBy,Updated,UpdatedBy,EntityType,IsSecure,IsEncrypted,IsParent,IsMandatory,IsIdentifier,SeqNo,Help,Version,FieldLength,IsKey,IsTranslated,Created,IsUpdateable,IsAutocomplete,IsAllowLogging,IsAllowCopy,Description,ColumnName,Name,IsSelectionColumn,AD_Column_UU,IsActive,IsToolbarButton,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID) VALUES (0,212212,'N','N',0,0,100,TO_TIMESTAMP('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),100,'D','N','N','N','N','N',0,'The Database Table provides the information of the table definition',0,10,'N','N',TO_TIMESTAMP('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),'Y','N','Y','Y','Database Table information','AD_Table_ID','Table','N','cd639a6d-243f-4737-80b7-e953534cafa6','Y','N','N',126,19,288) +; + +-- Jun 18, 2015 10:47:12 AM IST +UPDATE AD_Column SET FKConstraintType='N', FKConstraintName='ADTable_ADTree',Updated=TO_TIMESTAMP('2015-06-18 10:47:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +-- Jun 18, 2015 10:47:12 AM IST +ALTER TABLE AD_Tree ADD COLUMN AD_Table_ID NUMERIC(10) DEFAULT NULL +; + +-- Jun 18, 2015 10:47:12 AM IST +ALTER TABLE AD_Tree ADD CONSTRAINT ADTable_ADTree FOREIGN KEY (AD_Table_ID) REFERENCES ad_table(ad_table_id) DEFERRABLE INITIALLY DEFERRED +; + +-- Jun 18, 2015 10:47:46 AM IST +INSERT INTO AD_Ref_List (AD_Ref_List_ID,CreatedBy,UpdatedBy,Created,Updated,EntityType,AD_Client_ID,AD_Org_ID,Description,Value,Name,IsActive,AD_Ref_List_UU,AD_Reference_ID) VALUES (200310,100,100,TO_TIMESTAMP('2015-06-18 10:47:45','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2015-06-18 10:47:45','YYYY-MM-DD HH24:MI:SS'),'D',0,0,'Custom Table','TL','Custom Table','Y','e3104c45-9a71-4ea1-bd24-9125d33f07db',120) +; + +-- Jun 18, 2015 10:48:11 AM IST +INSERT INTO AD_Field (ColumnSpan,AD_Field_ID,AD_Client_ID,CreatedBy,AD_Org_ID,Updated,UpdatedBy,IsHeading,IsDisplayed,IsFieldOnly,IsSameLine,IsDisplayedGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,Created,EntityType,Name,IsEncrypted,DisplayLength,AD_Field_UU,IsActive,AD_Column_ID,AD_Tab_ID) VALUES (2,203825,0,100,0,TO_TIMESTAMP('2015-06-18 10:48:05','YYYY-MM-DD HH24:MI:SS'),100,'N','N','N','N','N',100,'N','Y',TO_TIMESTAMP('2015-06-18 10:48:05','YYYY-MM-DD HH24:MI:SS'),'D','AD_Tree_UU','N',36,'13075486-eba0-4882-8270-9205a2440b6f','Y',60514,243) +; + +-- Jun 18, 2015 10:48:11 AM IST +INSERT INTO AD_Field (ColumnSpan,AD_Field_ID,AD_Client_ID,CreatedBy,AD_Org_ID,Updated,UpdatedBy,IsHeading,Help,IsDisplayed,IsFieldOnly,IsSameLine,SeqNo,IsReadOnly,IsCentrallyMaintained,Created,EntityType,Name,Description,IsEncrypted,DisplayLength,AD_Field_UU,IsActive,AD_Column_ID,AD_Tab_ID) VALUES (2,203826,0,100,0,TO_TIMESTAMP('2015-06-18 10:48:11','YYYY-MM-DD HH24:MI:SS'),100,'N','The Database Table provides the information of the table definition','Y','N','N',110,'N','Y',TO_TIMESTAMP('2015-06-18 10:48:11','YYYY-MM-DD HH24:MI:SS'),'D','Table','Database Table information','N',10,'f7ca6a1b-4a96-48fe-938e-6784af276493','Y',212212,243) +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=203825 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=70,IsDisplayed='Y' WHERE AD_Field_ID=203826 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=80,IsDisplayed='Y' WHERE AD_Field_ID=5228 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=90,IsDisplayed='Y' WHERE AD_Field_ID=12421 +; + +-- Jun 18, 2015 10:48:40 AM IST +UPDATE AD_Field SET SeqNo=100,IsDisplayed='Y' WHERE AD_Field_ID=8371 +; + +-- Jun 18, 2015 10:49:23 AM IST +UPDATE AD_Field SET DisplayLogic='@TreeType@=''TL''',Updated=TO_TIMESTAMP('2015-06-18 10:49:23','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=203826 +; + + +SELECT register_migration_script('201506241206_IDEMPIERE-2675.sql') FROM dual +; diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java b/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java index d03a294ab6..c95954af9e 100644 --- a/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java +++ b/org.adempiere.base/src/org/compiere/model/I_AD_Tree.java @@ -62,6 +62,21 @@ public interface I_AD_Tree */ public int getAD_Org_ID(); + /** Column name AD_Table_ID */ + public static final String COLUMNNAME_AD_Table_ID = "AD_Table_ID"; + + /** Set Table. + * Database Table information + */ + public void setAD_Table_ID (int AD_Table_ID); + + /** Get Table. + * Database Table information + */ + public int getAD_Table_ID(); + + public org.compiere.model.I_AD_Table getAD_Table() throws RuntimeException; + /** Column name AD_Tree_ID */ public static final String COLUMNNAME_AD_Tree_ID = "AD_Tree_ID"; diff --git a/org.adempiere.base/src/org/compiere/model/MTree.java b/org.adempiere.base/src/org/compiere/model/MTree.java index 669e751e78..f4a963e60b 100644 --- a/org.adempiere.base/src/org/compiere/model/MTree.java +++ b/org.adempiere.base/src/org/compiere/model/MTree.java @@ -159,6 +159,14 @@ public class MTree extends MTree_Base TreeType = TREETYPE_CMTemplate; else { + String tableName = keyColumnName.substring(0, keyColumnName.length() - 3); + String query = "SELECT tr.AD_Tree_ID FROM AD_Tree tr inner join AD_Table t on (tr.AD_Table_ID=t.AD_Table_ID) WHERE tr.AD_Client_ID=? AND tr.TreeType='" + + TREETYPE_Table + + " ' AND tr.IsActive='Y' AND tr.IsAllNodes='Y' AND t.TableName = ?"; + int treeID = DB.getSQLValue(null, query, Env.getAD_Client_ID(Env.getCtx()),tableName); + + if (treeID != -1) + return treeID; s_log.log(Level.SEVERE, "Could not map " + keyColumnName); return 0; } @@ -219,6 +227,11 @@ public class MTree extends MTree_Base else // IDEMPIERE 329 - nmicoud { String sourceTableName = getSourceTableName(getTreeType()); + if (sourceTableName == null) + { + if (getAD_Table_ID() > 0) + sourceTableName = MTable.getTableName(getCtx(), getAD_Table_ID()); + } sql = new StringBuffer("SELECT " + "tn.Node_ID,tn.Parent_ID,tn.SeqNo,st.IsActive " + "FROM ").append(sourceTableName).append(" st " @@ -449,13 +462,27 @@ public class MTree extends MTree_Base sqlNode.append("f.JSPURL"); sqlNode.append(" IS NOT NULL))"); } - } else if (isTreeDrivenByValue()) { + }else if(getAD_Table_ID() != 0) { + String tableName =MTable.getTableName(getCtx(), getAD_Table_ID()); + sqlNode.append("SELECT t.").append(tableName) + .append("_ID,"); + if (isTreeDrivenByValue()) + sqlNode.append("t.Value || ' - ' || t.Name,"); + else + sqlNode.append("t.Name,"); + + sqlNode.append("t.Description,t.IsSummary,").append(color) + .append(" FROM ").append(tableName).append(" t "); + if (!m_editable) + sqlNode.append(" WHERE t.IsActive='Y'"); + } else if (isTreeDrivenByValue()) { sqlNode.append("SELECT t.").append(columnNameX) .append("_ID, t.Value || ' - ' || t.Name, t.Description, t.IsSummary,").append(color) .append(" FROM ").append(fromClause); if (!m_editable) sqlNode.append(" WHERE t.IsActive='Y'"); - } else { + } + else { if (columnNameX == null) throw new IllegalArgumentException("Unknown TreeType=" + getTreeType()); sqlNode.append("SELECT t.").append(columnNameX) diff --git a/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java b/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java index 79a0bc6fb8..eadb6607ee 100644 --- a/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java +++ b/org.adempiere.base/src/org/compiere/model/X_AD_Tree.java @@ -30,7 +30,7 @@ public class X_AD_Tree extends PO implements I_AD_Tree, I_Persistent /** * */ - private static final long serialVersionUID = 20150111L; + private static final long serialVersionUID = 20150618L; /** Standard Constructor */ public X_AD_Tree (Properties ctx, int AD_Tree_ID, String trxName) @@ -77,6 +77,34 @@ public class X_AD_Tree extends PO implements I_AD_Tree, I_Persistent return sb.toString(); } + public org.compiere.model.I_AD_Table getAD_Table() throws RuntimeException + { + return (org.compiere.model.I_AD_Table)MTable.get(getCtx(), org.compiere.model.I_AD_Table.Table_Name) + .getPO(getAD_Table_ID(), get_TrxName()); } + + /** Set Table. + @param AD_Table_ID + Database Table information + */ + public void setAD_Table_ID (int AD_Table_ID) + { + if (AD_Table_ID < 1) + set_Value (COLUMNNAME_AD_Table_ID, null); + else + set_Value (COLUMNNAME_AD_Table_ID, Integer.valueOf(AD_Table_ID)); + } + + /** Get Table. + @return Database Table information + */ + public int getAD_Table_ID () + { + Integer ii = (Integer)get_Value(COLUMNNAME_AD_Table_ID); + if (ii == null) + return 0; + return ii.intValue(); + } + /** Set Tree. @param AD_Tree_ID Identifies a Tree @@ -286,6 +314,8 @@ public class X_AD_Tree extends PO implements I_AD_Tree, I_Persistent public static final String TREETYPE_CMTemplate = "CT"; /** CM Media = CM */ public static final String TREETYPE_CMMedia = "CM"; + /** Table = TL */ + public static final String TREETYPE_Table = "TL"; /** Set Type | Area. @param TreeType Element this tree is built on (i.e Product, Business Partner) From bdb7675ed16a00b65e9b8a7aa494c1685081999d Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 5 Aug 2015 09:19:31 -0500 Subject: [PATCH 08/15] IDEMPIERE-2747 Env.parseVariable doesn't work with CreatedBy/UpdatedBy --- org.adempiere.base/src/org/compiere/util/Env.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.adempiere.base/src/org/compiere/util/Env.java b/org.adempiere.base/src/org/compiere/util/Env.java index dcc4c73031..5d61f14c86 100644 --- a/org.adempiere.base/src/org/compiere/util/Env.java +++ b/org.adempiere.base/src/org/compiere/util/Env.java @@ -1582,7 +1582,7 @@ public final class Env String foreignTable = colToken.getReferenceTableName(); if (v != null) { if (format != null && format.length() > 0) { - if (v instanceof Integer && (Integer) v > 0 && token.endsWith("_ID")) { + if (v instanceof Integer && (Integer) v > 0 && !Util.isEmpty(foreignTable)) { int tblIndex = format.indexOf("."); String tableName = null; if (tblIndex > 0) From 3b866698947f06c8e1ac60a071f320bf85de5bab Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 5 Aug 2015 12:42:53 -0500 Subject: [PATCH 09/15] IDEMPIERE-2675: Adding custom table support in Tree --- .../oracle/201508051109_IDEMPIERE-2675.sql | 55 +++++++++++++++++++ .../201506241206_IDEMPIERE-2675.sql | 1 - .../201508051109_IDEMPIERE-2675.sql | 52 ++++++++++++++++++ .../src/org/compiere/model/MTree.java | 23 ++++++-- .../src/org/compiere/model/MTree_Base.java | 25 +++++---- .../src/org/compiere/model/PO.java | 43 +++++++++++++-- 6 files changed, 177 insertions(+), 22 deletions(-) create mode 100644 migration/i2.1z/oracle/201508051109_IDEMPIERE-2675.sql create mode 100644 migration/i2.1z/postgresql/201508051109_IDEMPIERE-2675.sql diff --git a/migration/i2.1z/oracle/201508051109_IDEMPIERE-2675.sql b/migration/i2.1z/oracle/201508051109_IDEMPIERE-2675.sql new file mode 100644 index 0000000000..a55d425796 --- /dev/null +++ b/migration/i2.1z/oracle/201508051109_IDEMPIERE-2675.sql @@ -0,0 +1,55 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-2675 Supporting tree on any custom table +-- Aug 5, 2015 11:07:44 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=888 +; + +-- Aug 5, 2015 11:07:47 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=891 +; + +-- Aug 5, 2015 11:07:52 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:52','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=889 +; + +-- Aug 5, 2015 11:07:55 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_DATE('2015-08-05 11:07:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=890 +; + +-- Aug 5, 2015 11:15:48 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:15:48','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=115 +; + +-- Aug 5, 2015 11:15:59 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:15:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=118 +; + +-- Aug 5, 2015 11:16:01 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:16:01','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=116 +; + +-- Aug 5, 2015 11:16:04 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_DATE('2015-08-05 11:16:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=117 +; + +-- Aug 5, 2015 11:25:19 AM COT +UPDATE AD_Column SET IsUpdateable='N',Updated=TO_DATE('2015-08-05 11:25:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +-- Aug 5, 2015 11:25:59 AM COT +UPDATE AD_Column SET MandatoryLogic='@TreeType@=''TL''',Updated=TO_DATE('2015-08-05 11:25:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +-- Aug 5, 2015 11:29:40 AM COT +INSERT INTO AD_Val_Rule (AD_Val_Rule_ID,Name,Type,Code,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Val_Rule_UU) VALUES (200083,'AD_Table with IsSummary','S','EXISTS (SELECT * FROM AD_Column c WHERE AD_Table.AD_Table_ID=c.AD_Table_ID AND c.ColumnName=''IsSummary'' AND c.IsActive=''Y'') AND AD_Table.IsView=''N''',0,0,'Y',TO_DATE('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,'D','8a00a911-354b-40c8-9cfa-a40ec65df11d') +; + +-- Aug 5, 2015 11:29:51 AM COT +UPDATE AD_Column SET AD_Val_Rule_ID=200083,Updated=TO_DATE('2015-08-05 11:29:51','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +SELECT register_migration_script('201508051109_IDEMPIERE-2675.sql') FROM dual +; + diff --git a/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql b/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql index 92394278b6..8776a6f474 100644 --- a/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql +++ b/migration/i2.1z/postgresql/201506241206_IDEMPIERE-2675.sql @@ -1,4 +1,3 @@ - -- Jun 18, 2015 10:47:07 AM IST INSERT INTO AD_Column (SeqNoSelection,AD_Column_ID,IsAlwaysUpdateable,IsSyncDatabase,AD_Client_ID,AD_Org_ID,CreatedBy,Updated,UpdatedBy,EntityType,IsSecure,IsEncrypted,IsParent,IsMandatory,IsIdentifier,SeqNo,Help,Version,FieldLength,IsKey,IsTranslated,Created,IsUpdateable,IsAutocomplete,IsAllowLogging,IsAllowCopy,Description,ColumnName,Name,IsSelectionColumn,AD_Column_UU,IsActive,IsToolbarButton,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID) VALUES (0,212212,'N','N',0,0,100,TO_TIMESTAMP('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),100,'D','N','N','N','N','N',0,'The Database Table provides the information of the table definition',0,10,'N','N',TO_TIMESTAMP('2015-06-18 10:47:06','YYYY-MM-DD HH24:MI:SS'),'Y','N','Y','Y','Database Table information','AD_Table_ID','Table','N','cd639a6d-243f-4737-80b7-e953534cafa6','Y','N','N',126,19,288) ; diff --git a/migration/i2.1z/postgresql/201508051109_IDEMPIERE-2675.sql b/migration/i2.1z/postgresql/201508051109_IDEMPIERE-2675.sql new file mode 100644 index 0000000000..bed5e97a49 --- /dev/null +++ b/migration/i2.1z/postgresql/201508051109_IDEMPIERE-2675.sql @@ -0,0 +1,52 @@ +-- IDEMPIERE-2675 Supporting tree on any custom table +-- Aug 5, 2015 11:07:44 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:44','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=888 +; + +-- Aug 5, 2015 11:07:47 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=891 +; + +-- Aug 5, 2015 11:07:52 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:52','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=889 +; + +-- Aug 5, 2015 11:07:55 AM COT +UPDATE AD_Ref_List SET IsActive='N',Updated=TO_TIMESTAMP('2015-08-05 11:07:55','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Ref_List_ID=890 +; + +-- Aug 5, 2015 11:15:48 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:15:48','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=115 +; + +-- Aug 5, 2015 11:15:59 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:15:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=118 +; + +-- Aug 5, 2015 11:16:01 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:16:01','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=116 +; + +-- Aug 5, 2015 11:16:04 AM COT +UPDATE AD_Tree SET IsActive='N', IsDefault='N',Updated=TO_TIMESTAMP('2015-08-05 11:16:04','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=117 +; + +-- Aug 5, 2015 11:25:19 AM COT +UPDATE AD_Column SET IsUpdateable='N',Updated=TO_TIMESTAMP('2015-08-05 11:25:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +-- Aug 5, 2015 11:25:59 AM COT +UPDATE AD_Column SET MandatoryLogic='@TreeType@=''TL''',Updated=TO_TIMESTAMP('2015-08-05 11:25:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +-- Aug 5, 2015 11:29:40 AM COT +INSERT INTO AD_Val_Rule (AD_Val_Rule_ID,Name,Type,Code,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,EntityType,AD_Val_Rule_UU) VALUES (200083,'AD_Table with IsSummary','S','EXISTS (SELECT * FROM AD_Column c WHERE AD_Table.AD_Table_ID=c.AD_Table_ID AND c.ColumnName=''IsSummary'' AND c.IsActive=''Y'') AND AD_Table.IsView=''N''',0,0,'Y',TO_TIMESTAMP('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2015-08-05 11:29:39','YYYY-MM-DD HH24:MI:SS'),100,'D','8a00a911-354b-40c8-9cfa-a40ec65df11d') +; + +-- Aug 5, 2015 11:29:51 AM COT +UPDATE AD_Column SET AD_Val_Rule_ID=200083,Updated=TO_TIMESTAMP('2015-08-05 11:29:51','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=212212 +; + +SELECT register_migration_script('201508051109_IDEMPIERE-2675.sql') FROM dual +; + diff --git a/org.adempiere.base/src/org/compiere/model/MTree.java b/org.adempiere.base/src/org/compiere/model/MTree.java index f4a963e60b..6a7a7f3030 100644 --- a/org.adempiere.base/src/org/compiere/model/MTree.java +++ b/org.adempiere.base/src/org/compiere/model/MTree.java @@ -29,6 +29,7 @@ import java.util.logging.Level; import javax.sql.RowSet; import org.compiere.print.MPrintColor; +import org.compiere.util.CCache; import org.compiere.util.CLogMgt; import org.compiere.util.CLogger; import org.compiere.util.DB; @@ -111,6 +112,8 @@ public class MTree extends MTree_Base /** Logger */ private static CLogger s_log = CLogger.getCLogger(MTree.class); + /** Cache */ + private static CCache tree_cache = new CCache("AD_Tree_ID", 5); /************************************************************************** * Get default (oldest) complete AD_Tree_ID for KeyColumn. @@ -121,6 +124,10 @@ public class MTree extends MTree_Base */ public static int getDefaultAD_Tree_ID (int AD_Client_ID, String keyColumnName) { + String key = AD_Client_ID + "|" + keyColumnName; + if (tree_cache.containsKey(key)) + return tree_cache.get(key); + s_log.config(keyColumnName); if (keyColumnName == null || keyColumnName.length() == 0) return 0; @@ -160,14 +167,19 @@ public class MTree extends MTree_Base else { String tableName = keyColumnName.substring(0, keyColumnName.length() - 3); - String query = "SELECT tr.AD_Tree_ID FROM AD_Tree tr inner join AD_Table t on (tr.AD_Table_ID=t.AD_Table_ID) WHERE tr.AD_Client_ID=? AND tr.TreeType='" - + TREETYPE_Table - + " ' AND tr.IsActive='Y' AND tr.IsAllNodes='Y' AND t.TableName = ?"; - int treeID = DB.getSQLValue(null, query, Env.getAD_Client_ID(Env.getCtx()),tableName); + String query = "SELECT tr.AD_Tree_ID " + + "FROM AD_Tree tr " + + "JOIN AD_Table t ON (tr.AD_Table_ID=t.AD_Table_ID) " + + "WHERE tr.AD_Client_ID=? AND tr.TreeType=? AND tr.IsActive='Y' AND tr.IsAllNodes='Y' AND t.TableName = ? " + + "ORDER BY tr.AD_Tree_ID"; + int treeID = DB.getSQLValueEx(null, query, Env.getAD_Client_ID(Env.getCtx()), TREETYPE_Table, tableName); - if (treeID != -1) + if (treeID != -1) { + tree_cache.put(key, treeID); return treeID; + } s_log.log(Level.SEVERE, "Could not map " + keyColumnName); + tree_cache.put(key, 0); return 0; } @@ -197,6 +209,7 @@ public class MTree extends MTree_Base pstmt = null; } + tree_cache.put(key, AD_Tree_ID); return AD_Tree_ID; } // getDefaultAD_Tree_ID diff --git a/org.adempiere.base/src/org/compiere/model/MTree_Base.java b/org.adempiere.base/src/org/compiere/model/MTree_Base.java index f0497df8bd..cddca0eeaf 100644 --- a/org.adempiere.base/src/org/compiere/model/MTree_Base.java +++ b/org.adempiere.base/src/org/compiere/model/MTree_Base.java @@ -190,10 +190,6 @@ public class MTree_Base extends X_AD_Tree treeType.equals(TREETYPE_User3) || treeType.equals(TREETYPE_User4)) sourceTable = "C_ElementValue"; - - // else if (treeType.equals(TREETYPE_User1)) - // sourceTable = "??"; - // end afalcone return sourceTable; } // getSourceTableName @@ -300,6 +296,11 @@ public class MTree_Base extends X_AD_Tree public String getSourceTableName (boolean tableNameOnly) { String tableName = getSourceTableName(getTreeType()); + if (tableName == null) + { + if (getAD_Table_ID() > 0) + tableName = MTable.getTableName(getCtx(), getAD_Table_ID()); + } if (tableNameOnly) return tableName; if ("M_Product".equals(tableName)) @@ -343,18 +344,22 @@ public class MTree_Base extends X_AD_Tree if (!isActive() || !isAllNodes()) setIsDefault(false); + String tableName = getSourceTableName(true); + MTable table = MTable.get(getCtx(), tableName); + if (table.getColumnIndex("IsSummary") < 0) { + // IsSummary is mandatory column to have a tree + log.saveError("Error", "IsSummary column required for tree tables"); + return false; + } if (isTreeDrivenByValue()) { - String tableName = getSourceTableName(true); - MTable table = MTable.get(getCtx(), tableName); - // Value and IsSummary are mandatory columns to have a tree driven by Value - if ( table.getColumn("Value") == null - || table.getColumn("IsSummary") == null) { + if (table.getColumnIndex("Value") < 0) { + // Value is mandatory column to have a tree driven by Value setIsTreeDrivenByValue(false); } } return true; - } // beforeSabe + } // beforeSave /** * After Save diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index 83bb9c1e3d..750f900ef9 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -2241,6 +2241,15 @@ public abstract class PO insertTranslations(); else updateTranslations(); + + // table with potential tree + if (get_ColumnIndex("IsSummary") >= 0) { + if (newRecord) + insert_Tree(MTree_Base.TREETYPE_Table); + int idxValue = get_ColumnIndex("Value"); + if (newRecord || (idxValue >= 0 && is_ValueChanged(idxValue))) + update_Tree(MTree_Base.TREETYPE_Table); + } } // try @@ -3250,6 +3259,9 @@ public abstract class PO { // deleteTranslations(localTrxName); + if (get_ColumnIndex("IsSummary") >= 0) { + delete_Tree(MTree_Base.TREETYPE_Table); + } // Delete Cascade AD_Table_ID/Record_ID (Attachments, ..) PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName); @@ -3859,6 +3871,8 @@ public abstract class PO .append(C_Element_ID).append(" AND t.AD_Tree_ID=ae.AD_Tree_ID)"); else // std trees sb.append(" AND t.IsAllNodes='Y' AND t.TreeType='").append(treeType).append("'"); + if (MTree_Base.TREETYPE_Table.equals(treeType)) + sb.append(" AND t.AD_Table_ID=").append(get_Table_ID()); // Duplicate Check sb.append(" AND NOT EXISTS (SELECT * FROM " + MTree_Base.getNodeTableName(treeType) + " e " + "WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=").append(get_ID()).append(")"); @@ -3895,16 +3909,27 @@ public abstract class PO return; String tableName = MTree_Base.getNodeTableName(treeType); - String sourceTableName = MTree_Base.getSourceTableName(treeType); + String sourceTableName; + String whereTree; + Object[] parameters; + if (MTree_Base.TREETYPE_Table.equals(treeType)) { + sourceTableName = this.get_TableName(); + whereTree = "TreeType=? AND AD_Table_ID=?"; + parameters = new Object[]{treeType, this.get_Table_ID()}; + } else { + sourceTableName = MTree_Base.getSourceTableName(treeType); + whereTree = "TreeType=?"; + parameters = new Object[]{treeType}; + } String updateSeqNo = "UPDATE " + tableName + " SET SeqNo=SeqNo+1 WHERE Parent_ID=? AND SeqNo>=? AND AD_Tree_ID=?"; String update = "UPDATE " + tableName + " SET SeqNo=?, Parent_ID=? WHERE Node_ID=? AND AD_Tree_ID=?"; String selMinSeqNo = "SELECT COALESCE(MIN(tn.SeqNo),-1) FROM AD_TreeNode tn JOIN " + sourceTableName + " n ON (tn.Node_ID=n." + sourceTableName + "_ID) WHERE tn.Parent_ID=? AND tn.AD_Tree_ID=? AND n.Value>?"; String selMaxSeqNo = "SELECT COALESCE(MAX(tn.SeqNo)+1,999) FROM AD_TreeNode tn JOIN " + sourceTableName + " n ON (tn.Node_ID=n." + sourceTableName + "_ID) WHERE tn.Parent_ID=? AND tn.AD_Tree_ID=? AND n.Value trees = new Query(getCtx(), MTree_Base.Table_Name, "TreeType=?", get_TrxName()) + List trees = new Query(getCtx(), MTree_Base.Table_Name, whereTree, get_TrxName()) .setClient_ID() .setOnlyActiveRecords(true) - .setParameters(treeType) + .setParameters(parameters) .list(); for (MTree_Base tree : trees) { @@ -3948,8 +3973,11 @@ public abstract class PO // IDEMPIERE-2453 StringBuilder countSql = new StringBuilder("SELECT COUNT(*) FROM ") .append(MTree_Base.getNodeTableName(treeType)) - .append(" WHERE Parent_ID=?"); - int cnt = DB.getSQLValue( get_TrxName(), countSql.toString(), id); + .append(" n JOIN AD_Tree t ON n.AD_Tree_ID=t.AD_Tree_ID") + .append(" WHERE Parent_ID=? AND t.TreeType=?"); + if (MTree_Base.TREETYPE_Table.equals(treeType)) + countSql.append(" AND t.AD_Table_ID=").append(get_Table_ID()); + int cnt = DB.getSQLValueEx( get_TrxName(), countSql.toString(), id, treeType); if (cnt > 0) throw new AdempiereException(Msg.getMsg(Env.getCtx(),"NoParentDelete", new Object[] {cnt})); @@ -3958,7 +3986,10 @@ public abstract class PO .append(" n WHERE Node_ID=").append(id) .append(" AND EXISTS (SELECT * FROM AD_Tree t " + "WHERE t.AD_Tree_ID=n.AD_Tree_ID AND t.TreeType='") - .append(treeType).append("')"); + .append(treeType).append("'"); + if (MTree_Base.TREETYPE_Table.equals(treeType)) + sb.append(" AND t.AD_Table_ID=").append(get_Table_ID()); + sb.append(")"); int no = DB.executeUpdate(sb.toString(), get_TrxName()); if (no > 0) { if (log.isLoggable(Level.FINE)) log.fine("#" + no + " - TreeType=" + treeType); From 45ce71ef4807035a3b7ca5b3f20f471b84200e56 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Thu, 6 Aug 2015 17:30:03 -0500 Subject: [PATCH 10/15] IDEMPIERE-2757 Key for M_Storage wrongly defined on dictionary --- migration/i2.1/oracle/201508061729_IDEMPIERE-2757.sql | 11 +++++++++++ .../i2.1/postgresql/201508061729_IDEMPIERE-2757.sql | 8 ++++++++ 2 files changed, 19 insertions(+) create mode 100644 migration/i2.1/oracle/201508061729_IDEMPIERE-2757.sql create mode 100644 migration/i2.1/postgresql/201508061729_IDEMPIERE-2757.sql diff --git a/migration/i2.1/oracle/201508061729_IDEMPIERE-2757.sql b/migration/i2.1/oracle/201508061729_IDEMPIERE-2757.sql new file mode 100644 index 0000000000..5322ede126 --- /dev/null +++ b/migration/i2.1/oracle/201508061729_IDEMPIERE-2757.sql @@ -0,0 +1,11 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- IDEMPIERE-2757 Key for M_Storage wrongly defined on dictionary +-- Aug 6, 2015 5:28:43 PM COT +UPDATE AD_Column SET IsParent='Y', IsUpdateable='N',Updated=TO_DATE('2015-08-06 17:28:43','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=210887 +; + +SELECT register_migration_script('201508061729_IDEMPIERE-2757.sql') FROM dual +; + diff --git a/migration/i2.1/postgresql/201508061729_IDEMPIERE-2757.sql b/migration/i2.1/postgresql/201508061729_IDEMPIERE-2757.sql new file mode 100644 index 0000000000..8c2d659cd1 --- /dev/null +++ b/migration/i2.1/postgresql/201508061729_IDEMPIERE-2757.sql @@ -0,0 +1,8 @@ +-- IDEMPIERE-2757 Key for M_Storage wrongly defined on dictionary +-- Aug 6, 2015 5:28:43 PM COT +UPDATE AD_Column SET IsParent='Y', IsUpdateable='N',Updated=TO_TIMESTAMP('2015-08-06 17:28:43','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=210887 +; + +SELECT register_migration_script('201508061729_IDEMPIERE-2757.sql') FROM dual +; + From d726d9c75a4bb178c9f7e1cba63a0fa406ca1eca Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 7 Aug 2015 10:03:18 -0500 Subject: [PATCH 11/15] IDEMPIERE-2756 Background threads losing context when user log out --- org.adempiere.base/src/org/compiere/model/PO.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index 83bb9c1e3d..430dd1fd48 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -1989,6 +1989,7 @@ public abstract class PO */ public boolean save() { + checkValidContext(); CLogger.resetLast(); boolean newRecord = is_new(); // save locally as load resets if (!newRecord && !is_Changed()) @@ -3107,6 +3108,7 @@ public abstract class PO */ public boolean delete (boolean force) { + checkValidContext(); CLogger.resetLast(); if (is_new()) return true; @@ -4670,4 +4672,10 @@ public abstract class PO log.saveError(msg, info); } } + + private void checkValidContext() { + if (getCtx().size() == 0) + throw new AdempiereException("Context lost"); + } + } // PO From ad6290e09c637305d3f360786d5bc84633e92916 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 7 Aug 2015 10:03:50 -0500 Subject: [PATCH 12/15] IDEMPIERE-2756 Background threads losing context when user log out / integrate fix from hengsin for the server services --- .../org/compiere/server/AdempiereServer.java | 337 ++++++++++-------- .../server/org/compiere/server/Scheduler.java | 34 +- 2 files changed, 200 insertions(+), 171 deletions(-) diff --git a/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java b/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java index 4afb642e17..5f0c5e453a 100644 --- a/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java +++ b/org.adempiere.server/src/main/server/org/compiere/server/AdempiereServer.java @@ -1,8 +1,8 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * 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 * +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * @@ -16,62 +16,62 @@ *****************************************************************************/ package org.compiere.server; -import java.sql.Timestamp; -import java.util.Properties; -import java.util.logging.Level; - -import org.compiere.model.AdempiereProcessor; -import org.compiere.model.AdempiereProcessor2; -import org.compiere.model.AdempiereProcessorLog; -import org.compiere.model.MClient; -import org.compiere.model.MSchedule; -import org.compiere.model.MSystem; -import org.compiere.util.CLogger; -import org.compiere.util.Env; -import org.compiere.util.TimeUtil; - -/** - * Adempiere Server Base - * - * @author Jorg Janke - * @version $Id: AdempiereServer.java,v 1.3 2006/10/09 00:23:26 jjanke Exp $ - */ -public abstract class AdempiereServer implements Runnable -{ +import java.sql.Timestamp; +import java.util.Properties; +import java.util.logging.Level; + +import org.adempiere.util.ServerContext; +import org.compiere.model.AdempiereProcessor; +import org.compiere.model.AdempiereProcessor2; +import org.compiere.model.AdempiereProcessorLog; +import org.compiere.model.MClient; +import org.compiere.model.MSchedule; +import org.compiere.model.MSystem; +import org.compiere.model.PO; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.compiere.util.TimeUtil; + +/** + * Adempiere Server Base + * + * @author Jorg Janke + * @version $Id: AdempiereServer.java,v 1.3 2006/10/09 00:23:26 jjanke Exp $ + */ +public abstract class AdempiereServer implements Runnable +{ /************************************************************************** * Server Base Class - * @param model model - * @param initialNap delay time running in sec - */ - protected AdempiereServer (AdempiereProcessor model, int initialNap) - { - p_model = model; - m_ctx = new Properties(model.getCtx()); - if (p_system == null) - p_system = MSystem.get(m_ctx); - p_client = MClient.get(m_ctx); - Env.setContext(m_ctx, "#AD_Client_ID", p_client.getAD_Client_ID()); - m_initialNap = initialNap; - - Timestamp dateNextRun = getDateNextRun(true); - if (dateNextRun != null) - m_nextWork = dateNextRun.getTime(); - - long now = System.currentTimeMillis(); - if (m_nextWork > now) - { - m_sleepMS = m_nextWork - now; + * @param model model + * @param initialNap delay time running in sec + */ + protected AdempiereServer (AdempiereProcessor model, int initialNap) + { + p_model = model; + if (p_system == null) + p_system = MSystem.get(model.getCtx()); + p_client = MClient.get(model.getCtx(), model.getAD_Client_ID()); + m_initialNap = initialNap; + + Timestamp dateNextRun = getDateNextRun(true); + if (dateNextRun != null) + m_nextWork = dateNextRun.getTime(); + + long now = System.currentTimeMillis(); + if (m_nextWork > now) + { + m_sleepMS = m_nextWork - now; } - } // ServerBase - - /** The Processor Model */ - protected volatile AdempiereProcessor p_model; - /** Initial nap is seconds */ - private int m_initialNap = 0; - - /** Milliseconds to sleep - 0 Sec default */ - protected long m_sleepMS = 0; + } // ServerBase + + /** The Processor Model */ + protected volatile AdempiereProcessor p_model; + /** Initial nap is seconds */ + private int m_initialNap = 0; + + /** Milliseconds to sleep - 0 Sec default */ + protected long m_sleepMS = 0; /** Sleeping */ private volatile boolean m_sleeping = true; /** Server start time */ @@ -89,8 +89,6 @@ public abstract class AdempiereServer implements Runnable /** Logger */ protected CLogger log = CLogger.getCLogger(getClass()); - /** Context */ - private Properties m_ctx = null; /** System */ protected volatile static MSystem p_system = null; /** Client */ @@ -102,7 +100,7 @@ public abstract class AdempiereServer implements Runnable */ public Properties getCtx() { - return m_ctx; + return Env.getCtx(); } // getCtx /** @@ -112,18 +110,41 @@ public abstract class AdempiereServer implements Runnable { return m_sleepMS; } // getSleepMS - - public long getInitialNap() - { - return m_initialNap; + + public long getInitialNap() + { + return m_initialNap; } + public void runNow() + { + Properties context = new Properties(); + Env.setContext(context, "#AD_Client_ID", p_model.getAD_Client_ID()); + if (p_model instanceof PO) { + PO po = (PO) p_model; + if (po.get_ColumnIndex("AD_Org_ID") >= 0) + Env.setContext(context, "#AD_Org_ID", po.get_ValueAsInt("AD_Org_ID")); + if (po.get_ColumnIndex("AD_User_ID") >= 0) + Env.setContext(context, "#AD_User_ID", po.get_ValueAsInt("AD_User_ID")); + } + + Properties prevContext = ServerContext.getCurrentInstance(); + try { + ServerContext.setCurrentInstance(context); + m_sleeping = false; + doRunNow(); + } finally { + ServerContext.dispose(); + ServerContext.setCurrentInstance(prevContext); + m_sleeping = true; + } + } + /** * Run Now */ - public void runNow() - { - m_sleeping = false; + public void doRunNow() + { p_startWork = System.currentTimeMillis(); doWork(); long now = System.currentTimeMillis(); @@ -135,31 +156,55 @@ public abstract class AdempiereServer implements Runnable // p_model.setDateLastRun(new Timestamp(now)); p_model.saveEx(); - // + // if (log.isLoggable(Level.FINE)) - log.fine(getStatistics()); - m_sleeping = true; + log.fine(getStatistics()); } // runNow + public void run() + { + final Thread currentThread = Thread.currentThread(); + final String oldThreadName = currentThread.getName(); + String newThreadName = getName(); + boolean renamed = false; + if (!oldThreadName.equals(newThreadName)) { + try { + currentThread.setName(newThreadName); + renamed = true; + } catch (SecurityException e) {} + } + + Properties context = new Properties(); + Env.setContext(context, "#AD_Client_ID", p_model.getAD_Client_ID()); + if (p_model instanceof PO) { + PO po = (PO) p_model; + if (po.get_ColumnIndex("AD_Org_ID") >= 0) + Env.setContext(context, "#AD_Org_ID", po.get_ValueAsInt("AD_Org_ID")); + if (po.get_ColumnIndex("AD_User_ID") >= 0) + Env.setContext(context, "#AD_User_ID", po.get_ValueAsInt("AD_User_ID")); + } + + try { + ServerContext.setCurrentInstance(context); + m_sleeping = false; + doRun(); + } finally { + m_sleeping = true; + ServerContext.dispose(); + if (renamed) { + // Revert the name back if the current thread was renamed. + // We do not check the exception here because we know it works. + currentThread.setName(oldThreadName); + } + } + } /************************************************************************** * Run async */ - public void run () - { - final Thread currentThread = Thread.currentThread(); - final String oldThreadName = currentThread.getName(); - String newThreadName = getName(); - boolean renamed = false; - if (!oldThreadName.equals(newThreadName)) { - try { - currentThread.setName(newThreadName); - renamed = true; - } catch (SecurityException e) {} - } - - m_sleeping = false; - if (m_start == 0) - m_start = System.currentTimeMillis(); + protected void doRun() + { + if (m_start == 0) + m_start = System.currentTimeMillis(); // --------------- p_startWork = System.currentTimeMillis(); @@ -169,35 +214,29 @@ public abstract class AdempiereServer implements Runnable p_runCount++; m_runLastMS = now - p_startWork; - m_runTotalMS += m_runLastMS; + m_runTotalMS += m_runLastMS; // Finished work - calculate datetime for next run - Timestamp lastRun = new Timestamp(now); - if (p_model instanceof AdempiereProcessor2) - { - AdempiereProcessor2 ap = (AdempiereProcessor2) p_model; - if (ap.isIgnoreProcessingTime()) - { - lastRun = new Timestamp(p_startWork); - } - } - - m_nextWork = MSchedule.getNextRunMS(lastRun.getTime(), - p_model.getScheduleType(), p_model.getFrequencyType(), - p_model.getFrequency(), p_model.getCronPattern()); - - m_sleepMS = m_nextWork - now; - if (log.isLoggable(Level.INFO)) log.info(" Next run: " + new Timestamp(m_nextWork) + " sleep " + m_sleepMS); + Timestamp lastRun = new Timestamp(now); + if (p_model instanceof AdempiereProcessor2) + { + AdempiereProcessor2 ap = (AdempiereProcessor2) p_model; + if (ap.isIgnoreProcessingTime()) + { + lastRun = new Timestamp(p_startWork); + } + } + + m_nextWork = MSchedule.getNextRunMS(lastRun.getTime(), + p_model.getScheduleType(), p_model.getFrequencyType(), + p_model.getFrequency(), p_model.getCronPattern()); + + m_sleepMS = m_nextWork - now; + if (log.isLoggable(Level.INFO)) log.info(" Next run: " + new Timestamp(m_nextWork) + " sleep " + m_sleepMS); // p_model.setDateLastRun(lastRun); p_model.setDateNextRun(new Timestamp(m_nextWork)); - p_model.saveEx(); - m_sleeping = true; - if (renamed) { - // Revert the name back if the current thread was renamed. - // We do not check the exception here because we know it works. - currentThread.setName(oldThreadName); - } + p_model.saveEx(); } // run /** @@ -261,13 +300,13 @@ public abstract class AdempiereServer implements Runnable } // getDescription /** - * Get Model - * @return Model - */ - public AdempiereProcessor getModel() - { - return p_model; - } // getModel + * Get Model + * @return Model + */ + public AdempiereProcessor getModel() + { + return p_model; + } // getModel /** * Is Sleeping @@ -317,35 +356,35 @@ public abstract class AdempiereServer implements Runnable } // getStartTime /** - * Get Processor Logs - * @return logs - */ - public AdempiereProcessorLog[] getLogs() - { - return p_model.getLogs(); - } // getLogs - - - protected boolean isInterrupted() { - return Thread.currentThread().isInterrupted(); - } - - - public String getName() { - return p_model.getName(); - } - - - public static boolean isOKtoRunOnIP(AdempiereProcessor model) { - if (model instanceof AdempiereProcessor2) { - int AD_Schedule_ID = ((AdempiereProcessor2)model).getAD_Schedule_ID(); - MSchedule schedule = MSchedule.get(Env.getCtx(), AD_Schedule_ID); - if (!schedule.isOKtoRunOnIP()) - { - return false; // done - } - } - return true; - } - -} // AdempiereServer + * Get Processor Logs + * @return logs + */ + public AdempiereProcessorLog[] getLogs() + { + return p_model.getLogs(); + } // getLogs + + + protected boolean isInterrupted() { + return Thread.currentThread().isInterrupted(); + } + + + public String getName() { + return p_model.getName(); + } + + + public static boolean isOKtoRunOnIP(AdempiereProcessor model) { + if (model instanceof AdempiereProcessor2) { + int AD_Schedule_ID = ((AdempiereProcessor2)model).getAD_Schedule_ID(); + MSchedule schedule = MSchedule.get(Env.getCtx(), AD_Schedule_ID); + if (!schedule.isOKtoRunOnIP()) + { + return false; // done + } + } + return true; + } + +} // AdempiereServer diff --git a/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java b/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java index 38a91b3cc7..539cfec5fc 100644 --- a/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java +++ b/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java @@ -27,10 +27,8 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; -import java.util.Properties; import java.util.logging.Level; -import org.adempiere.util.ServerContext; import org.compiere.model.MAttachment; import org.compiere.model.MClient; import org.compiere.model.MNote; @@ -83,9 +81,6 @@ public class Scheduler extends AdempiereServer /** Transaction */ protected Trx m_trx = null; - // ctx for the report/process - protected Properties m_schedulerctx = new Properties(); - /** * Work */ @@ -95,29 +90,27 @@ public class Scheduler extends AdempiereServer .append(" - "); // Prepare a ctx for the report/process - BF [1966880] - m_schedulerctx.clear(); MClient schedclient = MClient.get(getCtx(), m_model.getAD_Client_ID()); - Env.setContext(m_schedulerctx, "#AD_Client_ID", schedclient.getAD_Client_ID()); - Env.setContext(m_schedulerctx, "#AD_Language", schedclient.getAD_Language()); - Env.setContext(m_schedulerctx, "#AD_Org_ID", m_model.getAD_Org_ID()); + Env.setContext(getCtx(), "#AD_Client_ID", schedclient.getAD_Client_ID()); + Env.setContext(getCtx(), "#AD_Language", schedclient.getAD_Language()); + Env.setContext(getCtx(), "#AD_Org_ID", m_model.getAD_Org_ID()); if (m_model.getAD_Org_ID() != 0) { MOrgInfo schedorg = MOrgInfo.get(getCtx(), m_model.getAD_Org_ID(), null); if (schedorg.getM_Warehouse_ID() > 0) - Env.setContext(m_schedulerctx, "#M_Warehouse_ID", schedorg.getM_Warehouse_ID()); + Env.setContext(getCtx(), "#M_Warehouse_ID", schedorg.getM_Warehouse_ID()); } - Env.setContext(m_schedulerctx, "#AD_User_ID", getAD_User_ID()); - Env.setContext(m_schedulerctx, "#SalesRep_ID", getAD_User_ID()); + Env.setContext(getCtx(), "#AD_User_ID", getAD_User_ID()); + Env.setContext(getCtx(), "#SalesRep_ID", getAD_User_ID()); // TODO: It can be convenient to add AD_Scheduler.AD_Role_ID MUser scheduser = MUser.get(getCtx(), getAD_User_ID()); MRole[] schedroles = scheduser.getRoles(m_model.getAD_Org_ID()); if (schedroles != null && schedroles.length > 0) - Env.setContext(m_schedulerctx, "#AD_Role_ID", schedroles[0].getAD_Role_ID()); // first role, ordered by AD_Role_ID + Env.setContext(getCtx(), "#AD_Role_ID", schedroles[0].getAD_Role_ID()); // first role, ordered by AD_Role_ID Timestamp ts = new Timestamp(System.currentTimeMillis()); SimpleDateFormat dateFormat4Timestamp = new SimpleDateFormat("yyyy-MM-dd"); - Env.setContext(m_schedulerctx, "#Date", dateFormat4Timestamp.format(ts)+" 00:00:00" ); // JDBC format - ServerContext.setCurrentInstance(m_schedulerctx); + Env.setContext(getCtx(), "#Date", dateFormat4Timestamp.format(ts)+" 00:00:00" ); // JDBC format - MProcess process = new MProcess(m_schedulerctx, m_model.getAD_Process_ID(), null); + MProcess process = new MProcess(getCtx(), m_model.getAD_Process_ID(), null); try { m_trx = Trx.get(Trx.createTrxName("Scheduler"), true); @@ -137,9 +130,6 @@ public class Scheduler extends AdempiereServer m_trx.close(); } - // clear thread local context - ServerContext.dispose(); - // int no = m_model.deleteLog(); m_summary.append(" Logs deleted=").append(no); @@ -161,7 +151,7 @@ public class Scheduler extends AdempiereServer if (log.isLoggable(Level.INFO)) log.info(process.toString()); boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0 || process.getJasperReport() != null || process.getAD_PrintFormat_ID() > 0); - String schedulerName = Env.parseContext(m_schedulerctx, -1, m_model.getName(), false, true); + String schedulerName = Env.parseContext(getCtx(), -1, m_model.getName(), false, true); // Process (see also MWFActivity.performWork int AD_Table_ID = m_model.getAD_Table_ID(); @@ -449,7 +439,7 @@ public class Scheduler extends AdempiereServer String sql = variable.substring(5); // w/o tag //sql = Env.parseContext(m_vo.ctx, m_vo.WindowNo, sql, false, true); // replace variables //hengsin, capture unparseable error to avoid subsequent sql exception - sql = Env.parseContext(m_schedulerctx, 0, sql, false, false); // replace variables + sql = Env.parseContext(getCtx(), 0, sql, false, false); // replace variables if (sql.equals("")) log.log(Level.WARNING, "(" + sPara.getColumnName() + ") - Default SQL variable parse failed: " + variable); else { @@ -493,7 +483,7 @@ public class Scheduler extends AdempiereServer String tail=index < (columnName.length()-1) ? columnName.substring(index+1) : null; columnName = columnName.substring(0, index); // try Env - String env = Env.getContext(m_schedulerctx, columnName); + String env = Env.getContext(getCtx(), columnName); if (env == null || env.length() == 0) env = Env.getContext(getCtx(), columnName); if (env.length() == 0) From 966bcefc52c8497b0bec202acb117466fbfbadd7 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 7 Aug 2015 10:25:18 -0500 Subject: [PATCH 13/15] IDEMPIERE-2756 Background threads losing context when user log out / additional fix on development --- .../src/main/server/org/compiere/server/Scheduler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java b/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java index 1f8fae6872..a2b58be502 100644 --- a/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java +++ b/org.adempiere.server/src/main/server/org/compiere/server/Scheduler.java @@ -269,14 +269,14 @@ public class Scheduler extends AdempiereServer if (email) { - MMailText mailTemplate = new MMailText(m_schedulerctx, m_model.getR_MailText_ID(), null); + MMailText mailTemplate = new MMailText(getCtx(), m_model.getR_MailText_ID(), null); String mailContent = ""; if (mailTemplate.is_new()){ mailContent = m_model.getDescription(); }else{ mailTemplate.setUser(user); - mailTemplate.setLanguage(Env.getContext(m_schedulerctx, "#AD_Language")); + mailTemplate.setLanguage(Env.getContext(getCtx(), "#AD_Language")); // if user has bpartner link. maybe use language depend user mailContent = mailTemplate.getMailText(true); schedulerName = mailTemplate.getMailHeader(); From b1c16a2441732645b942851095e9871045ccc837 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 7 Aug 2015 16:48:18 -0500 Subject: [PATCH 14/15] IDEMPIERE-2756 Background threads losing context when user log out --- .../org/adempiere/webui/LoggedSessionListener.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/LoggedSessionListener.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/LoggedSessionListener.java index 7976a753df..572c782734 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/LoggedSessionListener.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/LoggedSessionListener.java @@ -66,13 +66,10 @@ public class LoggedSessionListener implements HttpSessionListener, ServletContex } public void removeADSession(String sessionID, String serverName) { - String whereClause = "WebSession=? AND ServerName=? AND Processed='N'"; - List sessions = new Query(Env.getCtx(), MSession.Table_Name, whereClause, null) - .setParameters(sessionID, serverName) - .list(); - for (MSession session : sessions) { - session.setProcessed(true); - session.saveEx(); + String sql = "UPDATE AD_Session SET Processed='Y' WHERE WebSession=? AND ServerName=? AND Processed='N'"; + int no = DB.executeUpdate(sql, new Object[] {sessionID, serverName}, false, null); + if (no < 0) { + throw new AdempiereException("UpdateSession: Cannot Destroy Session"); } } From 90bee84c7a91ed7c9a6f1f50f072420972468d7d Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Fri, 7 Aug 2015 17:43:39 -0500 Subject: [PATCH 15/15] minor - assigning wrongly ID for a new record in Journal Batch - this is controlled actually on PO so is harmless - but better remove that line just in case --- org.adempiere.base/src/org/compiere/model/MJournalBatch.java | 1 - 1 file changed, 1 deletion(-) diff --git a/org.adempiere.base/src/org/compiere/model/MJournalBatch.java b/org.adempiere.base/src/org/compiere/model/MJournalBatch.java index 8903646cd3..69c64251f2 100644 --- a/org.adempiere.base/src/org/compiere/model/MJournalBatch.java +++ b/org.adempiere.base/src/org/compiere/model/MJournalBatch.java @@ -135,7 +135,6 @@ public class MJournalBatch extends X_GL_JournalBatch implements DocAction { this (original.getCtx(), 0, original.get_TrxName()); setClientOrg(original); - setGL_JournalBatch_ID(original.getGL_JournalBatch_ID()); // // setC_AcctSchema_ID(original.getC_AcctSchema_ID()); // setGL_Budget_ID(original.getGL_Budget_ID());