创建一个 java 过程来生成 idempiere 报告

create a java process to generate a idempiere report

我有 Postgres,它在单独运行时可以运行,但在集成到 java 中并在 idempiere 上调用时无法运行。我正在寻找建议。

我收到 ff 错误:

caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "00"
  Position: 1055; State=42601; ErrorCode=0
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:120)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:384)
    at jdk.internal.reflect.GeneratedMethodAccessor48.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.compiere.db.StatementProxy.invoke(StatementProxy.java:130)
    at com.sun.proxy.$Proxy11.executeUpdate(Unknown Source)
    at org.compiere.util.DB.executeUpdate(DB.java:1039)
    at org.compiere.util.DB.executeUpdate(DB.java:898)
    at org.compiere.util.DB.executeUpdate(DB.java:885)
    at ice.enterprise.base.report.StockAgingReport.createDetailLines(StockAgingReport.java:145)
    at ice.enterprise.base.report.StockAgingReport.doIt(StockAgingReport.java:72)
    at org.compiere.process.SvrProcess.process(SvrProcess.java:201)
    at org.compiere.process.SvrProcess.startProcess(SvrProcess.java:147)
    at org.adempiere.util.ProcessUtil.startJavaProcess(ProcessUtil.java:173)
    at org.compiere.apps.AbstractProcessCtl.startProcess(AbstractProcessCtl.java:467)
    at org.compiere.apps.AbstractProcessCtl.run(AbstractProcessCtl.java:235)

15:21:49.994===========> DataEngine.loadPrintData: null - ERROR: column "levelno" does not exist
  Position: 924
SQL=SELECT T_ReportStockAgeing.CurrentCost,T_ReportStockAgeing.Date1,T_ReportStockAgeing_ICE.Description,T_ReportStockAgeing.OnHand,(SELECT NVL(AD_PInstance.Name,'-1') ||'_'|| NVL(CAST (AD_PInstance.AD_PInstance_ID AS Text),'-1') ||'_'|| NVL((SELECT NVL(AD_Process.Name,'-1') ||'_'|| NVL(AD_Process.Value,'-1') FROM AD_Process WHERE AD_PInstance.AD_Process_ID=AD_Process.AD_Process_ID),'-1') FROM AD_PInstance WHERE T_ReportStockAgeing.AD_PInstance_ID=AD_PInstance.AD_PInstance_ID) AS AAD_PInstance_ID,T_ReportStockAgeing.AD_PInstance_ID AS AD_PInstance_ID,T_ReportStockAgeing.ProductCode,T_ReportStockAgeing.Qty1,T_ReportStockAgeing.Qty2,T_ReportStockAgeing.Qty3,T_ReportStockAgeing.Qty4,T_ReportStockAgeing.Value1,T_ReportStockAgeing.Valu2,T_ReportStockAgeing.Value3,T_ReportStockAgeing.Value4,T_ReportStockAgeing_ICE.T_ReportStockAgeing_ICE_UU,LevelNo FROM T_ReportStockAgeing_ICE WHERE T_ReportStockAgeing_ICE.AD_PInstance_ID=2109500 [136]
15:21:50.030===========> AbstractProcessDialog.doRun: org.postgresql.util.PSQLException: ERROR: column "levelno" does not exist
import java.math.BigDecimal;
    import java.sql.Timestamp;
    import java.util.logging.Level;

    import org.compiere.print.MPrintFormat;
    import org.compiere.process.ProcessInfoParameter;
    import org.compiere.process.SvrProcess;
    import org.compiere.util.DB;
    import org.compiere.util.Env;
    import org.compiere.util.Ini;

    public class StockAgingReport extends SvrProcess {


        private int                 p_AD_Org_ID = 0;
        private int                 p_AD_Client_ID =  0; 
        private int                 p_C_AcctSchema_ID = 0;
        private int                 p_M_Product_Category_ID = 0;
        private Timestamp           p_Date = null;
        private long                m_start = System.currentTimeMillis();

        @Override
        protected void prepare() {
            StringBuffer sb = new StringBuffer ("Record_ID=")
                    .append(getRecord_ID());
            //  Parameter
            ProcessInfoParameter[] para = getParameter();
            for (int i = 0; i < para.length; i++)
            {
                String name = para[i].getParameterName();
                if (para[i].getParameter() == null && para[i].getParameter_To() == null)
                    ;

                else if (name.equals("Date"))
                {
                    p_Date = (Timestamp)para[i].getParameter();
                }
                else if (name.equals("AD_Org_ID"))
                    p_AD_Org_ID = ((BigDecimal)para[i].getParameter()).intValue();
                else if (name.equals("AD_Client_ID"))
                    p_AD_Client_ID = para[i].getParameterAsInt();
                else if (name.equals("C_AcctSchema_ID")) 
                    p_C_AcctSchema_ID =  para[i].getParameterAsInt();
                else if (name.equals("M_Product_Category_ID")) 
                    p_M_Product_Category_ID = para[i].getParameterAsInt();
                else
                    log.log(Level.SEVERE, "Unknown Parameter: " + name);
            }
            log.fine(sb.toString());

        }

        @Override
        protected String doIt() throws Exception {

            createDetailLines();

            int AD_PrintFormat_ID = DB.getSQLValue(get_TrxName(), "Select AD_PrintFormat_ID from AD_PrintFormat Where name = 'Stock_Ageing'");   
            if (AD_PrintFormat_ID > 0) {
                if (Ini.isClient())
                    getProcessInfo().setTransientObject (MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false));
                else
                    getProcessInfo().setSerializableObject(MPrintFormat.get (getCtx(), AD_PrintFormat_ID, false));
            }

            if (log.isLoggable(Level.FINE)) log.fine((System.currentTimeMillis() - m_start) + " ms");
            return "";
        }


        private void createDetailLines() {

            StringBuffer sb = new StringBuffer ("INSERT INTO T_ReportStockAgeing "
                    + "(AD_PInstance_ID, AD_Client_ID, AD_Org_ID, ProductCode, Description, CurrentCost,"
                    + " Qty1, Qty2, Qty3, Qty4, OnHand,"
                    + " Value1, Valu2, Value3 ,Value4) ");



            sb.append("SELECT ").append(getAD_PInstance_ID()).append(", ").append(Env.getAD_Client_ID(getCtx())).append(", ").append(Env.getAD_Org_ID(getCtx())).append(", ")
            .append( "ProductCode, Description, Case OnHand WHEN 0 THEN 0 ELSE CurrentCost*OnHand END AS CurrentCost," 
                    + "Qty1, Qty2, Qty3, Qty4, OnHand,"
                    + "CASE OnHand  WHEN 0 THEN 0 ELSE round((CurrentCost) * Qty1,2) END as Value1, " 
                    + "CASE OnHand  WHEN 0 THEN 0 ELSE round((CurrentCost) * Qty2,2) END as Valu2, " 
                    + "CASE OnHand  WHEN 0 THEN 0 ELSE round((CurrentCost) * Qty3,2) END as Value3, " 
                    + "CASE OnHand  WHEN 0 THEN 0 ELSE round((CurrentCost) * Qty4,2) END as Value4 " 
                    + "FROM ( " 
                    + "SELECT " 

                    + "prod.value as ProductCode, " 
                    + "prod.description as Description, " 
                    + "M_Product_Category_ID, " 
                    + "(SELECT COALESCE (max(c.CurrentCostPrice),0) FROM   M_Cost c  WHERE c.AD_Org_ID =" +p_AD_Org_ID +" AND c.C_AcctSchema_ID= "+p_C_AcctSchema_ID+"  AND prod.M_Product_ID = c.M_Product_ID AND prod.ProductType !='A'  ) as CurrentCost, " 
                    + "(SELECT COALESCE (SUM (st.qtyonhand),0)FROM M_Storage st "
                    + "WHERE prod.M_Product_ID = st.M_Product_ID  "
                    + "AND st.DateMaterialPolicy >= ( ("+p_Date+"::date) - interval '3 month' ) " 
                    + "AND st.DateMaterialPolicy <= ("+p_Date+"::date) " 
                    + "AND st.AD_Org_ID =  "+p_AD_Org_ID+"  AND prod.ProductType !='A' " 
                    + ") as Qty1, " 
                    + "(SELECT COALESCE (SUM (st.qtyonhand),0)FROM M_Storage st " 
                    + "WHERE prod.M_Product_ID = st.M_Product_ID " 
                    + "AND st.DateMaterialPolicy >= ("+p_Date+"::date- interval '6 month' ) " 
                    + "AND st.DateMaterialPolicy <= ("+p_Date+"::date - interval '3 month') "
                    + "AND st.AD_Org_ID =  "+p_AD_Org_ID+" AND prod.ProductType !='A') "
                    + "as Qty2, " 
                    + "(SELECT COALESCE (SUM (st.qtyonhand),0)FROM M_Storage st " 
                    + "WHERE prod.M_Product_ID = st.M_Product_ID " 
                    + "AND st.DateMaterialPolicy >= ("+p_Date+"::date - interval '12 month' ) " 
                    + "AND st.DateMaterialPolicy <= ("+p_Date+"::date- interval '6 month') " 
                    + "AND st.AD_Org_ID =  "+p_AD_Org_ID+"  AND prod.ProductType !='A' " 
                    + ") as Qty3, " 
                    + "(SELECT COALESCE (SUM (st.qtyonhand),0)FROM M_Storage st " 
                    + "WHERE prod.M_Product_ID = st.M_Product_ID  " 
                    + "AND st.DateMaterialPolicy < ("+p_Date+"::date- interval '12 month') " 
                    + "AND st.AD_Org_ID = "+p_AD_Org_ID+"  AND prod.ProductType !='A' " 
                    + ") as Qty4, "
                    + "(SELECT COALESCE (SUM (st.qtyonhand),0)FROM M_Storage st "
                    + "WHERE prod.M_Product_ID = st.M_Product_ID " 
                    + "AND st.AD_Org_ID = "+p_AD_Org_ID+"  AND prod.ProductType !='A' "
                    + ") as OnHand  " 
                    + "FROM M_Product prod " 
                    + "LEFT JOIN AD_Org org ON org.AD_Org_ID = "+p_AD_Org_ID+"  "
                    + "LEFT JOIN M_Product_Category prodcat ON  prodcat.M_Product_Category_ID  = "+p_M_Product_Category_ID+" AND prodcat.AD_Client_ID =  "+p_AD_Client_ID+" " 
                    + "WHERE  prod.M_Product_Category_ID = "+ p_M_Product_Category_ID+"  AND prod.ProductType !='A' " 
                    +  ")temp ");


            sb.append(" ) as temp ");
            int no = DB.executeUpdate(sb.toString(), get_TrxName());
            log.fine("#" + no);
            log.finest(sb.toString());

        }

    }

我试图在 iDempiere 中集成您的 class 示例进行测试,但正如 GhostCat 指出的那样,最好创建一个最小的可重现示例,而且也很重要,请 post 也请指出错误这是系统抛出的,在 UI and/or 控制台日志中。

class 没有一些导入,所有变量都没有被使用,私有方法 createDetailLines 也从未被调用,我假设你提到的错误是在那个方法中,但是有无法知道是否未调用。

现在,回顾 SQL,有两点需要注意:

1 - 它没有为 java 格式化,你使用 "AND c.C_AcctSchema_ID= $P{C_AcctSchema_ID}" 而这不是 java 管理变量的方式,这听起来像 jasper 报告语法而不是 java.对于 JDBC 你必须使用 ?作为绑定变量的替代

2 - iDempiere是多数据库的,系统的设计方式是写oracle兼容的SQL语法,并且有一个翻译层将oracle语句转换成postgresql句法。因此,最好避免使用 postgresql 特定语法,如“::date”或间隔“3 个月”——它可以工作,但转换层也可能有问题。如果你想使用特定的 postgresql 语法并避免转换层被混淆,你可以用 NATIVE_PostgreSQL_KEYWORK 包围 postgresql 特定的语法 - 请不要因为这个错误而责备我常量:-)